summaryrefslogtreecommitdiff
path: root/node_modules/svgo/plugins/cleanupIds.js
diff options
context:
space:
mode:
authorlittleblack111 <littleblack11111@gmail.com>2026-05-18 23:10:59 +0800
committerlittleblack111 <littleblack11111@gmail.com>2026-05-18 23:41:44 +0800
commitfc87c009806dcc98867f6b58efe29b042aa01dee (patch)
tree8f59b3f4a5b66e9dfef2d40c8d318e258a521228 /node_modules/svgo/plugins/cleanupIds.js
parent3336b2356ee6152d9c6ae59bd9b87ccbc0958407 (diff)
node: updatemain
Diffstat (limited to 'node_modules/svgo/plugins/cleanupIds.js')
-rw-r--r--node_modules/svgo/plugins/cleanupIds.js265
1 files changed, 0 insertions, 265 deletions
diff --git a/node_modules/svgo/plugins/cleanupIds.js b/node_modules/svgo/plugins/cleanupIds.js
deleted file mode 100644
index bfabcca5..00000000
--- a/node_modules/svgo/plugins/cleanupIds.js
+++ /dev/null
@@ -1,265 +0,0 @@
-'use strict';
-
-/**
- * @typedef {import('../lib/types').XastElement} XastElement
- */
-
-const { visitSkip } = require('../lib/xast.js');
-const { hasScripts, findReferences } = require('../lib/svgo/tools');
-
-exports.name = 'cleanupIds';
-exports.description = 'removes unused IDs and minifies used';
-
-const generateIdChars = [
- 'a',
- 'b',
- 'c',
- 'd',
- 'e',
- 'f',
- 'g',
- 'h',
- 'i',
- 'j',
- 'k',
- 'l',
- 'm',
- 'n',
- 'o',
- 'p',
- 'q',
- 'r',
- 's',
- 't',
- 'u',
- 'v',
- 'w',
- 'x',
- 'y',
- 'z',
- 'A',
- 'B',
- 'C',
- 'D',
- 'E',
- 'F',
- 'G',
- 'H',
- 'I',
- 'J',
- 'K',
- 'L',
- 'M',
- 'N',
- 'O',
- 'P',
- 'Q',
- 'R',
- 'S',
- 'T',
- 'U',
- 'V',
- 'W',
- 'X',
- 'Y',
- 'Z',
-];
-const maxIdIndex = generateIdChars.length - 1;
-
-/**
- * Check if an ID starts with any one of a list of strings.
- *
- * @type {(string: string, prefixes: string[]) => boolean}
- */
-const hasStringPrefix = (string, prefixes) => {
- for (const prefix of prefixes) {
- if (string.startsWith(prefix)) {
- return true;
- }
- }
- return false;
-};
-
-/**
- * Generate unique minimal ID.
- *
- * @param {?number[]} currentId
- * @returns {number[]}
- */
-const generateId = (currentId) => {
- if (currentId == null) {
- return [0];
- }
- currentId[currentId.length - 1] += 1;
- for (let i = currentId.length - 1; i > 0; i--) {
- if (currentId[i] > maxIdIndex) {
- currentId[i] = 0;
- if (currentId[i - 1] !== undefined) {
- currentId[i - 1]++;
- }
- }
- }
- if (currentId[0] > maxIdIndex) {
- currentId[0] = 0;
- currentId.unshift(0);
- }
- return currentId;
-};
-
-/**
- * Get string from generated ID array.
- *
- * @type {(arr: number[]) => string}
- */
-const getIdString = (arr) => {
- return arr.map((i) => generateIdChars[i]).join('');
-};
-
-/**
- * Remove unused and minify used IDs
- * (only if there are no any <style> or <script>).
- *
- * @author Kir Belevich
- *
- * @type {import('./plugins-types').Plugin<'cleanupIds'>}
- */
-exports.fn = (_root, params) => {
- const {
- remove = true,
- minify = true,
- preserve = [],
- preservePrefixes = [],
- force = false,
- } = params;
- const preserveIds = new Set(
- Array.isArray(preserve) ? preserve : preserve ? [preserve] : [],
- );
- const preserveIdPrefixes = Array.isArray(preservePrefixes)
- ? preservePrefixes
- : preservePrefixes
- ? [preservePrefixes]
- : [];
- /**
- * @type {Map<string, XastElement>}
- */
- const nodeById = new Map();
- /**
- * @type {Map<string, {element: XastElement, name: string }[]>}
- */
- const referencesById = new Map();
- let deoptimized = false;
-
- return {
- element: {
- enter: (node) => {
- if (!force) {
- // deoptimize if style or scripts are present
- if (
- (node.name === 'style' && node.children.length !== 0) ||
- hasScripts(node)
- ) {
- deoptimized = true;
- return;
- }
-
- // avoid removing IDs if the whole SVG consists only of defs
- if (node.name === 'svg') {
- let hasDefsOnly = true;
- for (const child of node.children) {
- if (child.type !== 'element' || child.name !== 'defs') {
- hasDefsOnly = false;
- break;
- }
- }
- if (hasDefsOnly) {
- return visitSkip;
- }
- }
- }
-
- for (const [name, value] of Object.entries(node.attributes)) {
- if (name === 'id') {
- // collect all ids
- const id = value;
- if (nodeById.has(id)) {
- delete node.attributes.id; // remove repeated id
- } else {
- nodeById.set(id, node);
- }
- } else {
- const ids = findReferences(name, value);
- for (const id of ids) {
- let refs = referencesById.get(id);
- if (refs == null) {
- refs = [];
- referencesById.set(id, refs);
- }
- refs.push({ element: node, name });
- }
- }
- }
- },
- },
-
- root: {
- exit: () => {
- if (deoptimized) {
- return;
- }
- /**
- * @param {string} id
- * @returns {boolean}
- */
- const isIdPreserved = (id) =>
- preserveIds.has(id) || hasStringPrefix(id, preserveIdPrefixes);
- /** @type {?number[]} */
- let currentId = null;
- for (const [id, refs] of referencesById) {
- const node = nodeById.get(id);
- if (node != null) {
- // replace referenced IDs with the minified ones
- if (minify && isIdPreserved(id) === false) {
- /** @type {?string} */
- let currentIdString = null;
- do {
- currentId = generateId(currentId);
- currentIdString = getIdString(currentId);
- } while (
- isIdPreserved(currentIdString) ||
- (referencesById.has(currentIdString) &&
- nodeById.get(currentIdString) == null)
- );
- node.attributes.id = currentIdString;
- for (const { element, name } of refs) {
- const value = element.attributes[name];
- if (value.includes('#')) {
- // replace id in href and url()
- element.attributes[name] = value.replace(
- `#${encodeURI(id)}`,
- `#${currentIdString}`,
- );
- } else {
- // replace id in begin attribute
- element.attributes[name] = value.replace(
- `${id}.`,
- `${currentIdString}.`,
- );
- }
- }
- }
- // keep referenced node
- nodeById.delete(id);
- }
- }
- // remove non-referenced IDs attributes from elements
- if (remove) {
- for (const [id, node] of nodeById) {
- if (isIdPreserved(id) === false) {
- delete node.attributes.id;
- }
- }
- }
- },
- },
- };
-};