summaryrefslogtreecommitdiff
path: root/node_modules/svgo/plugins/sortAttrs.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/sortAttrs.js
parent3fd9400d4dccc25aa29b5702216732e0b7542073 (diff)
postcss,(plugins): nanocss, postcss-preset-env
Diffstat (limited to 'node_modules/svgo/plugins/sortAttrs.js')
-rw-r--r--node_modules/svgo/plugins/sortAttrs.js108
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;
+ },
+ },
+ };
+};