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/convertStyleToAttrs.js | |
| parent | 3fd9400d4dccc25aa29b5702216732e0b7542073 (diff) | |
postcss,(plugins): nanocss, postcss-preset-env
Diffstat (limited to 'node_modules/svgo/plugins/convertStyleToAttrs.js')
| -rw-r--r-- | node_modules/svgo/plugins/convertStyleToAttrs.js | 137 |
1 files changed, 137 insertions, 0 deletions
diff --git a/node_modules/svgo/plugins/convertStyleToAttrs.js b/node_modules/svgo/plugins/convertStyleToAttrs.js new file mode 100644 index 00000000..5d5107d6 --- /dev/null +++ b/node_modules/svgo/plugins/convertStyleToAttrs.js @@ -0,0 +1,137 @@ +'use strict'; + +const { attrsGroups } = require('./_collections'); + +exports.name = 'convertStyleToAttrs'; +exports.description = 'converts style to attributes'; + +/** + * @type {(...args: string[]) => string} + */ +const g = (...args) => { + return '(?:' + args.join('|') + ')'; +}; + +const stylingProps = attrsGroups.presentation; +const rEscape = '\\\\(?:[0-9a-f]{1,6}\\s?|\\r\\n|.)'; // Like \" or \2051. Code points consume one space. +const rAttr = '\\s*(' + g('[^:;\\\\]', rEscape) + '*?)\\s*'; // attribute name like ‘fill’ +const rSingleQuotes = "'(?:[^'\\n\\r\\\\]|" + rEscape + ")*?(?:'|$)"; // string in single quotes: 'smth' +const rQuotes = '"(?:[^"\\n\\r\\\\]|' + rEscape + ')*?(?:"|$)'; // string in double quotes: "smth" +const rQuotedString = new RegExp('^' + g(rSingleQuotes, rQuotes) + '$'); +// Parentheses, E.g.: url(data:image/png;base64,iVBO...). +// ':' and ';' inside of it should be threated as is. (Just like in strings.) +const rParenthesis = + '\\(' + g('[^\'"()\\\\]+', rEscape, rSingleQuotes, rQuotes) + '*?' + '\\)'; +// The value. It can have strings and parentheses (see above). Fallbacks to anything in case of unexpected input. +const rValue = + '\\s*(' + + g( + '[^!\'"();\\\\]+?', + rEscape, + rSingleQuotes, + rQuotes, + rParenthesis, + '[^;]*?' + ) + + '*?' + + ')'; +// End of declaration. Spaces outside of capturing groups help to do natural trimming. +const rDeclEnd = '\\s*(?:;\\s*|$)'; +// Important rule +const rImportant = '(\\s*!important(?![-(\\w]))?'; +// Final RegExp to parse CSS declarations. +const regDeclarationBlock = new RegExp( + rAttr + ':' + rValue + rImportant + rDeclEnd, + 'ig' +); +// Comments expression. Honors escape sequences and strings. +const regStripComments = new RegExp( + g(rEscape, rSingleQuotes, rQuotes, '/\\*[^]*?\\*/'), + 'ig' +); + +/** + * Convert style in attributes. Cleanups comments and illegal declarations (without colon) as a side effect. + * + * @example + * <g style="fill:#000; color: #fff;"> + * ⬇ + * <g fill="#000" color="#fff"> + * + * @example + * <g style="fill:#000; color: #fff; -webkit-blah: blah"> + * ⬇ + * <g fill="#000" color="#fff" style="-webkit-blah: blah"> + * + * @author Kir Belevich + * + * @type {import('./plugins-types').Plugin<'convertStyleToAttrs'>} + */ +exports.fn = (_root, params) => { + const { keepImportant = false } = params; + return { + element: { + enter: (node) => { + if (node.attributes.style != null) { + // ['opacity: 1', 'color: #000'] + let styles = []; + /** + * @type {Record<string, string>} + */ + const newAttributes = {}; + + // Strip CSS comments preserving escape sequences and strings. + const styleValue = node.attributes.style.replace( + regStripComments, + (match) => { + return match[0] == '/' + ? '' + : match[0] == '\\' && /[-g-z]/i.test(match[1]) + ? match[1] + : match; + } + ); + + regDeclarationBlock.lastIndex = 0; + // eslint-disable-next-line no-cond-assign + for (var rule; (rule = regDeclarationBlock.exec(styleValue)); ) { + if (!keepImportant || !rule[3]) { + styles.push([rule[1], rule[2]]); + } + } + + if (styles.length) { + styles = styles.filter(function (style) { + if (style[0]) { + var prop = style[0].toLowerCase(), + val = style[1]; + + if (rQuotedString.test(val)) { + val = val.slice(1, -1); + } + + if (stylingProps.includes(prop)) { + newAttributes[prop] = val; + + return false; + } + } + + return true; + }); + + Object.assign(node.attributes, newAttributes); + + if (styles.length) { + node.attributes.style = styles + .map((declaration) => declaration.join(':')) + .join(';'); + } else { + delete node.attributes.style; + } + } + } + }, + }, + }; +}; |
