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/sortAttrs.js | |
| parent | 3fd9400d4dccc25aa29b5702216732e0b7542073 (diff) | |
postcss,(plugins): nanocss, postcss-preset-env
Diffstat (limited to 'node_modules/svgo/plugins/sortAttrs.js')
| -rw-r--r-- | node_modules/svgo/plugins/sortAttrs.js | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/node_modules/svgo/plugins/sortAttrs.js b/node_modules/svgo/plugins/sortAttrs.js new file mode 100644 index 00000000..6347f65e --- /dev/null +++ b/node_modules/svgo/plugins/sortAttrs.js @@ -0,0 +1,108 @@ +'use strict'; + +exports.name = 'sortAttrs'; +exports.description = 'Sort element attributes for better compression'; + +/** + * Sort element attributes for better compression + * + * @author Nikolay Frantsev + * + * @type {import('./plugins-types').Plugin<'sortAttrs'>} + */ +exports.fn = (_root, params) => { + const { + order = [ + 'id', + 'width', + 'height', + 'x', + 'x1', + 'x2', + 'y', + 'y1', + 'y2', + 'cx', + 'cy', + 'r', + 'fill', + 'stroke', + 'marker', + 'd', + 'points', + ], + xmlnsOrder = 'front', + } = params; + + /** + * @type {(name: string) => number} + */ + const getNsPriority = (name) => { + if (xmlnsOrder === 'front') { + // put xmlns first + if (name === 'xmlns') { + return 3; + } + // xmlns:* attributes second + if (name.startsWith('xmlns:')) { + return 2; + } + } + // other namespaces after and sort them alphabetically + if (name.includes(':')) { + return 1; + } + // other attributes + return 0; + }; + + /** + * @type {(a: [string, string], b: [string, string]) => number} + */ + const compareAttrs = ([aName], [bName]) => { + // sort namespaces + const aPriority = getNsPriority(aName); + const bPriority = getNsPriority(bName); + const priorityNs = bPriority - aPriority; + if (priorityNs !== 0) { + return priorityNs; + } + // extract the first part from attributes + // for example "fill" from "fill" and "fill-opacity" + const [aPart] = aName.split('-'); + const [bPart] = bName.split('-'); + // rely on alphabetical sort when the first part is the same + if (aPart !== bPart) { + const aInOrderFlag = order.includes(aPart) ? 1 : 0; + const bInOrderFlag = order.includes(bPart) ? 1 : 0; + // sort by position in order param + if (aInOrderFlag === 1 && bInOrderFlag === 1) { + return order.indexOf(aPart) - order.indexOf(bPart); + } + // put attributes from order param before others + const priorityOrder = bInOrderFlag - aInOrderFlag; + if (priorityOrder !== 0) { + return priorityOrder; + } + } + // sort alphabetically + return aName < bName ? -1 : 1; + }; + + return { + element: { + enter: (node) => { + const attrs = Object.entries(node.attributes); + attrs.sort(compareAttrs); + /** + * @type {Record<string, string>} + */ + const sortedAttributes = {}; + for (const [name, value] of attrs) { + sortedAttributes[name] = value; + } + node.attributes = sortedAttributes; + }, + }, + }; +}; |
