diff options
| author | littleblack111 <littleblack11111@gmail.com> | 2023-10-14 15:05:55 +0800 |
|---|---|---|
| committer | littleblack111 <littleblack11111@gmail.com> | 2023-10-14 15:05:55 +0800 |
| commit | c06f7ee0a40255214c477e13d9b956a7e07c2900 (patch) | |
| tree | f5982a568ef8fab865d0142e71c7494fea3e4c1b /node_modules/svgo/plugins/minifyStyles.js | |
| parent | 3fd9400d4dccc25aa29b5702216732e0b7542073 (diff) | |
postcss,(plugins): nanocss, postcss-preset-env
Diffstat (limited to 'node_modules/svgo/plugins/minifyStyles.js')
| -rw-r--r-- | node_modules/svgo/plugins/minifyStyles.js | 139 |
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; + } + }, + }, + }; +}; |
