summaryrefslogtreecommitdiff
path: root/node_modules/svgo/plugins/minifyStyles.js
diff options
context:
space:
mode:
authorlittleblack111 <littleblack11111@gmail.com>2023-10-14 15:05:55 +0800
committerlittleblack111 <littleblack11111@gmail.com>2023-10-14 15:05:55 +0800
commitc06f7ee0a40255214c477e13d9b956a7e07c2900 (patch)
treef5982a568ef8fab865d0142e71c7494fea3e4c1b /node_modules/svgo/plugins/minifyStyles.js
parent3fd9400d4dccc25aa29b5702216732e0b7542073 (diff)
postcss,(plugins): nanocss, postcss-preset-env
Diffstat (limited to 'node_modules/svgo/plugins/minifyStyles.js')
-rw-r--r--node_modules/svgo/plugins/minifyStyles.js139
1 files changed, 139 insertions, 0 deletions
diff --git a/node_modules/svgo/plugins/minifyStyles.js b/node_modules/svgo/plugins/minifyStyles.js
new file mode 100644
index 00000000..a10b8d20
--- /dev/null
+++ b/node_modules/svgo/plugins/minifyStyles.js
@@ -0,0 +1,139 @@
+'use strict';
+
+/**
+ * @typedef {import('../lib/types').XastElement} XastElement
+ */
+
+const csso = require('csso');
+
+exports.name = 'minifyStyles';
+exports.description =
+ 'minifies styles and removes unused styles based on usage data';
+
+/**
+ * Minifies styles (<style> element + style attribute) using CSSO
+ *
+ * @author strarsis <strarsis@gmail.com>
+ *
+ * @type {import('./plugins-types').Plugin<'minifyStyles'>}
+ */
+exports.fn = (_root, { usage, ...params }) => {
+ let enableTagsUsage = true;
+ let enableIdsUsage = true;
+ let enableClassesUsage = true;
+ // force to use usage data even if it unsafe (document contains <script> or on* attributes)
+ let forceUsageDeoptimized = false;
+ if (typeof usage === 'boolean') {
+ enableTagsUsage = usage;
+ enableIdsUsage = usage;
+ enableClassesUsage = usage;
+ } else if (usage) {
+ enableTagsUsage = usage.tags == null ? true : usage.tags;
+ enableIdsUsage = usage.ids == null ? true : usage.ids;
+ enableClassesUsage = usage.classes == null ? true : usage.classes;
+ forceUsageDeoptimized = usage.force == null ? false : usage.force;
+ }
+ /**
+ * @type {Array<XastElement>}
+ */
+ const styleElements = [];
+ /**
+ * @type {Array<XastElement>}
+ */
+ const elementsWithStyleAttributes = [];
+ let deoptimized = false;
+ /**
+ * @type {Set<string>}
+ */
+ const tagsUsage = new Set();
+ /**
+ * @type {Set<string>}
+ */
+ const idsUsage = new Set();
+ /**
+ * @type {Set<string>}
+ */
+ const classesUsage = new Set();
+
+ return {
+ element: {
+ enter: (node) => {
+ // detect deoptimisations
+ if (node.name === 'script') {
+ deoptimized = true;
+ }
+ for (const name of Object.keys(node.attributes)) {
+ if (name.startsWith('on')) {
+ deoptimized = true;
+ }
+ }
+ // collect tags, ids and classes usage
+ tagsUsage.add(node.name);
+ if (node.attributes.id != null) {
+ idsUsage.add(node.attributes.id);
+ }
+ if (node.attributes.class != null) {
+ for (const className of node.attributes.class.split(/\s+/)) {
+ classesUsage.add(className);
+ }
+ }
+ // collect style elements or elements with style attribute
+ if (node.name === 'style' && node.children.length !== 0) {
+ styleElements.push(node);
+ } else if (node.attributes.style != null) {
+ elementsWithStyleAttributes.push(node);
+ }
+ },
+ },
+
+ root: {
+ exit: () => {
+ /**
+ * @type {csso.Usage}
+ */
+ const cssoUsage = {};
+ if (deoptimized === false || forceUsageDeoptimized === true) {
+ if (enableTagsUsage && tagsUsage.size !== 0) {
+ cssoUsage.tags = Array.from(tagsUsage);
+ }
+ if (enableIdsUsage && idsUsage.size !== 0) {
+ cssoUsage.ids = Array.from(idsUsage);
+ }
+ if (enableClassesUsage && classesUsage.size !== 0) {
+ cssoUsage.classes = Array.from(classesUsage);
+ }
+ }
+ // minify style elements
+ for (const node of styleElements) {
+ if (
+ node.children[0].type === 'text' ||
+ node.children[0].type === 'cdata'
+ ) {
+ const cssText = node.children[0].value;
+ const minified = csso.minify(cssText, {
+ ...params,
+ usage: cssoUsage,
+ }).css;
+ // preserve cdata if necessary
+ // TODO split cdata -> text optimisation into separate plugin
+ if (cssText.indexOf('>') >= 0 || cssText.indexOf('<') >= 0) {
+ node.children[0].type = 'cdata';
+ node.children[0].value = minified;
+ } else {
+ node.children[0].type = 'text';
+ node.children[0].value = minified;
+ }
+ }
+ }
+ // minify style attributes
+ for (const node of elementsWithStyleAttributes) {
+ // style attribute
+ const elemStyle = node.attributes.style;
+ node.attributes.style = csso.minifyBlock(elemStyle, {
+ ...params,
+ }).css;
+ }
+ },
+ },
+ };
+};