Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/frontend/startup_css/clean_css.js')
-rw-r--r--scripts/frontend/startup_css/clean_css.js83
1 files changed, 83 insertions, 0 deletions
diff --git a/scripts/frontend/startup_css/clean_css.js b/scripts/frontend/startup_css/clean_css.js
new file mode 100644
index 00000000000..67a0453e816
--- /dev/null
+++ b/scripts/frontend/startup_css/clean_css.js
@@ -0,0 +1,83 @@
+const { memoize, isString, isRegExp } = require('lodash');
+const { parse } = require('postcss');
+const { CSS_TO_REMOVE } = require('./constants');
+
+const getSelectorRemoveTesters = memoize(() =>
+ CSS_TO_REMOVE.map((x) => {
+ if (isString(x)) {
+ return (selector) => x === selector;
+ }
+ if (isRegExp(x)) {
+ return (selector) => x.test(selector);
+ }
+
+ throw new Error(`Unexpected type in CSS_TO_REMOVE content "${x}". Expected String or RegExp.`);
+ }),
+);
+
+const getRemoveTesters = memoize(() => {
+ const selectorTesters = getSelectorRemoveTesters();
+
+ // These are mostly carried over from the previous project
+ // https://gitlab.com/gitlab-org/frontend/gitlab-css-statistics/-/blob/2aa00af25dba08fc71081c77206f45efe817ea4b/lib/gl_startup_extract.js
+ return [
+ (node) => node.type === 'comment',
+ (node) =>
+ node.type === 'atrule' &&
+ (node.params === 'print' ||
+ node.params === 'prefers-reduced-motion: reduce' ||
+ node.name === 'keyframe' ||
+ node.name === 'charset'),
+ (node) => node.selector && node.selectors && !node.selectors.length,
+ (node) => node.selector && selectorTesters.some((fn) => fn(node.selector)),
+ (node) =>
+ node.type === 'decl' &&
+ (node.prop === 'transition' ||
+ node.prop.indexOf('-webkit-') > -1 ||
+ node.prop.indexOf('-ms-') > -1),
+ ];
+});
+
+const getNodesToRemove = (nodes) => {
+ const removeTesters = getRemoveTesters();
+ const remNodes = [];
+
+ nodes.forEach((node) => {
+ if (removeTesters.some((fn) => fn(node))) {
+ remNodes.push(node);
+ } else if (node.nodes?.length) {
+ remNodes.push(...getNodesToRemove(node.nodes));
+ }
+ });
+
+ return remNodes;
+};
+
+const getEmptyNodesToRemove = (nodes) =>
+ nodes
+ .filter((node) => node.nodes)
+ .reduce((acc, node) => {
+ if (node.nodes.length) {
+ acc.push(...getEmptyNodesToRemove(node.nodes));
+ } else {
+ acc.push(node);
+ }
+
+ return acc;
+ }, []);
+
+const cleanCSS = (css) => {
+ const cssRoot = parse(css);
+
+ getNodesToRemove(cssRoot.nodes).forEach((node) => {
+ node.remove();
+ });
+
+ getEmptyNodesToRemove(cssRoot.nodes).forEach((node) => {
+ node.remove();
+ });
+
+ return cssRoot.toResult().css;
+};
+
+module.exports = { cleanCSS };