Merge remote-tracking branch 'upstream/main'

This commit is contained in:
2026-08-26 09:31:34 +08:00
parent 9b8c4bfab6
commit 394eb0285d
34137 changed files with 3589424 additions and 0 deletions
@@ -0,0 +1,35 @@
const { getRoot } = require('../utils');
/**
* @return {Function} PostHTML plugin
*/
function extractNamespacesToRoot() {
return (tree) => {
const namespaces = {};
tree.match({ tag: /.*/ }, (node) => {
const attrs = node.attrs || {};
Object.keys(attrs).forEach((attr) => {
if (attr.startsWith('xmlns')) {
if (attr in namespaces === false) {
namespaces[attr] = attrs[attr];
}
delete node.attrs[attr];
}
});
return node;
});
const root = getRoot(tree);
root.attrs = root.attrs || {};
Object.keys(namespaces).forEach(name => root.attrs[name] = namespaces[name]);
return tree;
};
}
module.exports = extractNamespacesToRoot;
@@ -0,0 +1,38 @@
const traverse = require('traverse');
const clone = require('clone');
// Fixes Firefox bug https://bugzilla.mozilla.org/show_bug.cgi?id=353575
const defaultConfig = {
tags: ['linearGradient', 'radialGradient', 'pattern', 'clipPath', 'mask']
};
function moveFromSymbolToRoot(config = null) {
const cfg = Object.assign({}, defaultConfig, config);
return (tree) => {
traverse(tree).forEach(function (node) {
if (!this.isLeaf && node.tag && node.tag === 'symbol') {
const symbol = this.parent.node;
const nodesToRemove = [];
traverse(node.content).forEach(function (n) {
if (!this.isLeaf && n.tag && cfg.tags.indexOf(n.tag) !== -1) {
const parent = this.parent.node;
const cloned = clone(this.node);
symbol.push(cloned);
nodesToRemove.push({ parent, node: n });
}
});
nodesToRemove.forEach((item) => {
const nodeIndex = item.parent.indexOf(item.node);
item.parent.splice(nodeIndex, 1);
});
}
});
return tree;
};
}
module.exports = moveFromSymbolToRoot;
@@ -0,0 +1,34 @@
const merge = require('merge-options');
const { getRoot } = require('../utils');
const defaultConfig = {
removeDimensions: false
};
/**
* @param {Object} [config] {@see defaultConfig}
* @return {Function} PostHTML plugin
*/
function normalizeViewBox(config = {}) {
const cfg = merge(defaultConfig, config);
return (tree) => {
const root = getRoot(tree);
root.attrs = root.attrs || {};
const attrs = root.attrs;
const { width, height, viewBox } = attrs;
if (!viewBox && width && height) {
attrs.viewBox = `0 0 ${parseFloat(width).toString()} ${parseFloat(height).toString()}`;
if (cfg.removeDimensions) {
delete attrs.width;
delete attrs.height;
}
}
return tree;
};
}
module.exports = normalizeViewBox;
@@ -0,0 +1,30 @@
const Promise = require('bluebird');
const decodeEntities = require('he').decode;
const postcss = require('postcss');
const prefixSelectors = require('postcss-prefix-selector');
/**
* @return {Function} PostHTML plugin
*/
function prefixStyleSelectors(prefix) {
return (tree) => {
const styleNodes = [];
tree.match({ tag: 'style' }, (node) => {
styleNodes.push(node);
return node;
});
return Promise.map(styleNodes, (node) => {
const content = node.content ? decodeEntities(node.content.join('')) : '';
return postcss()
.use(prefixSelectors({ prefix }))
.process(content)
.then(prefixedStyles => node.content = prefixedStyles.css);
}).then(() => tree);
};
}
module.exports = prefixStyleSelectors;
+23
View File
@@ -0,0 +1,23 @@
const getImageSize = require('image-size');
const { svg, xlink } = require('../../namespaces');
/**
* TODO rasterToSVG#getPixelRatioFromFilename
* @param {Buffer} buffer
* @return {string}
*/
function rasterToSVG(buffer) {
const info = getImageSize(buffer);
const { width, height, type } = info;
const defaultNS = `${svg.name}="${svg.uri}"`;
const xlinkNS = `${xlink.name}="${xlink.uri}"`;
const data = `data:image/${type};base64,${buffer.toString('base64')}`;
return [
`<svg ${defaultNS} ${xlinkNS} width="${width}" height="${height}" viewBox="0 0 ${width} ${height}">`,
`<image xlink:href="${data}" width="${width}" height="${height}" />`,
'</svg>'
].join('');
}
module.exports = rasterToSVG;
+52
View File
@@ -0,0 +1,52 @@
const micromatch = require('micromatch');
const { getRoot } = require('../utils');
const defaultConfig = {
id: undefined,
preserve: [
'viewBox',
'preserveAspectRatio',
'class',
'overflow',
'stroke?(-*)',
'fill?(-*)',
'xmlns?(:*)',
'role',
'aria-*'
]
};
/**
* @param {Object} [config] {@see defaultConfig}
* @return {Function} PostHTML plugin
*/
function svgToSymbol(config = null) {
const cfg = Object.assign({}, defaultConfig, config);
return (tree) => {
const root = getRoot(tree);
root.tag = 'symbol';
root.attrs = root.attrs || {};
const attrNames = Object.keys(root.attrs);
const attrNamesToPreserve = micromatch(attrNames, cfg.preserve);
attrNames.forEach((name) => {
if (!attrNamesToPreserve.includes(name)) {
delete root.attrs[name];
}
});
if (cfg.id) {
root.attrs.id = cfg.id;
}
// Remove all elements and add symbol node
tree.splice(0, tree.length, root);
return tree;
};
}
module.exports = svgToSymbol;