From f06956efd2dc4bf77244a9fcce2b883a00b925af Mon Sep 17 00:00:00 2001 From: littleblack111 Date: Thu, 21 Dec 2023 22:46:53 +0800 Subject: updated node modules --- node_modules/svgo/plugins/removeXlink.js | 226 +++++++++++++++++++++++++++++++ 1 file changed, 226 insertions(+) create mode 100644 node_modules/svgo/plugins/removeXlink.js (limited to 'node_modules/svgo/plugins/removeXlink.js') diff --git a/node_modules/svgo/plugins/removeXlink.js b/node_modules/svgo/plugins/removeXlink.js new file mode 100644 index 00000000..d341b673 --- /dev/null +++ b/node_modules/svgo/plugins/removeXlink.js @@ -0,0 +1,226 @@ +'use strict'; + +const { elems } = require('./_collections'); + +/** + * @typedef {import('../lib/types').XastElement} XastElement + */ + +exports.name = 'removeXlink'; +exports.description = + 'remove xlink namespace and replaces attributes with the SVG 2 equivalent where applicable'; + +/** URI indicating the Xlink namespace. */ +const XLINK_NAMESPACE = 'http://www.w3.org/1999/xlink'; + +/** + * Map of `xlink:show` values to the SVG 2 `target` attribute values. + * + * @type {Record} + * @see https://developer.mozilla.org/docs/Web/SVG/Attribute/xlink:show#usage_notes + */ +const SHOW_TO_TARGET = { + new: '_blank', + replace: '_self', +}; + +/** + * Elements that use xlink:href, but were deprecated in SVG 2 and therefore + * don't support the SVG 2 href attribute. + * + * @type {string[]} + * @see https://developer.mozilla.org/docs/Web/SVG/Attribute/xlink:href + * @see https://developer.mozilla.org/docs/Web/SVG/Attribute/href + */ +const LEGACY_ELEMENTS = [ + 'cursor', + 'filter', + 'font-face-uri', + 'glyphRef', + 'tref', +]; + +/** + * @param {XastElement} node + * @param {string[]} prefixes + * @param {string} attr + * @returns {string[]} + */ +const findPrefixedAttrs = (node, prefixes, attr) => { + return prefixes + .map((prefix) => `${prefix}:${attr}`) + .filter((attr) => node.attributes[attr] != null); +}; + +/** + * Removes XLink namespace prefixes and converts references to XLink attributes + * to the native SVG equivalent. + * + * The XLink namespace is deprecated in SVG 2. + * + * @type {import('./plugins-types').Plugin<'removeXlink'>} + * @see https://developer.mozilla.org/docs/Web/SVG/Attribute/xlink:href + */ +exports.fn = (_, params) => { + const { includeLegacy } = params; + + /** + * XLink namespace prefixes that are currently in the stack. + * + * @type {string[]} + */ + const xlinkPrefixes = []; + + /** + * Namespace prefixes that exist in {@link xlinkPrefixes} but were overridden + * in a child element to point to another namespace, and so is not treated as + * an XLink attribute. + * + * @type {string[]} + */ + const overriddenPrefixes = []; + + /** + * Namespace prefixes that were used in one of the {@link LEGACY_ELEMENTS}. + * + * @type {string[]} + */ + const usedInLegacyElement = []; + + return { + element: { + enter: (node) => { + for (const [key, value] of Object.entries(node.attributes)) { + if (key.startsWith('xmlns:')) { + const prefix = key.split(':', 2)[1]; + + if (value === XLINK_NAMESPACE) { + xlinkPrefixes.push(prefix); + continue; + } + + if (xlinkPrefixes.includes(prefix)) { + overriddenPrefixes.push(prefix); + } + } + } + + if ( + overriddenPrefixes.some((prefix) => xlinkPrefixes.includes(prefix)) + ) { + return; + } + + const showAttrs = findPrefixedAttrs(node, xlinkPrefixes, 'show'); + let showHandled = node.attributes.target != null; + for (let i = showAttrs.length - 1; i >= 0; i--) { + const attr = showAttrs[i]; + const value = node.attributes[attr]; + const mapping = SHOW_TO_TARGET[value]; + + if (showHandled || mapping == null) { + delete node.attributes[attr]; + continue; + } + + if (mapping !== elems[node.name]?.defaults?.target) { + node.attributes.target = mapping; + } + + delete node.attributes[attr]; + showHandled = true; + } + + const titleAttrs = findPrefixedAttrs(node, xlinkPrefixes, 'title'); + for (let i = titleAttrs.length - 1; i >= 0; i--) { + const attr = titleAttrs[i]; + const value = node.attributes[attr]; + const hasTitle = node.children.filter( + (child) => child.type === 'element' && child.name === 'title' + ); + + if (hasTitle.length > 0) { + delete node.attributes[attr]; + continue; + } + + /** @type {XastElement} */ + const titleTag = { + type: 'element', + name: 'title', + attributes: {}, + children: [ + { + type: 'text', + value, + }, + ], + }; + + Object.defineProperty(titleTag, 'parentNode', { + writable: true, + value: node, + }); + + node.children.unshift(titleTag); + delete node.attributes[attr]; + } + + const hrefAttrs = findPrefixedAttrs(node, xlinkPrefixes, 'href'); + + if ( + hrefAttrs.length > 0 && + LEGACY_ELEMENTS.includes(node.name) && + !includeLegacy + ) { + hrefAttrs + .map((attr) => attr.split(':', 1)[0]) + .forEach((prefix) => usedInLegacyElement.push(prefix)); + return; + } + + for (let i = hrefAttrs.length - 1; i >= 0; i--) { + const attr = hrefAttrs[i]; + const value = node.attributes[attr]; + + if (node.attributes.href != null) { + delete node.attributes[attr]; + continue; + } + + node.attributes.href = value; + delete node.attributes[attr]; + } + }, + exit: (node) => { + for (const [key, value] of Object.entries(node.attributes)) { + const [prefix, attr] = key.split(':', 2); + + if ( + xlinkPrefixes.includes(prefix) && + !overriddenPrefixes.includes(prefix) && + !usedInLegacyElement.includes(prefix) && + !includeLegacy + ) { + delete node.attributes[key]; + continue; + } + + if (key.startsWith('xmlns:') && !usedInLegacyElement.includes(attr)) { + if (value === XLINK_NAMESPACE) { + const index = xlinkPrefixes.indexOf(attr); + xlinkPrefixes.splice(index, 1); + delete node.attributes[key]; + continue; + } + + if (overriddenPrefixes.includes(prefix)) { + const index = overriddenPrefixes.indexOf(attr); + overriddenPrefixes.splice(index, 1); + } + } + } + }, + }, + }; +}; -- cgit v1.2.3