This commit is contained in:
2025-09-19 14:25:20 +08:00
parent 269893a435
commit fbf3f77229
24949 changed files with 2839404 additions and 0 deletions

517
node_modules/svgo/lib/svgo/coa.js generated vendored Normal file
View File

@@ -0,0 +1,517 @@
'use strict';
const fs = require('fs');
const path = require('path');
const colors = require('picocolors');
const { loadConfig, optimize } = require('../svgo-node.js');
const pluginsMap = require('../../plugins/plugins.js');
const PKG = require('../../package.json');
const { encodeSVGDatauri, decodeSVGDatauri } = require('./tools.js');
const regSVGFile = /\.svg$/i;
/**
* Synchronously check if path is a directory. Tolerant to errors like ENOENT.
* @param {string} path
*/
function checkIsDir(path) {
try {
return fs.lstatSync(path).isDirectory();
} catch (e) {
return false;
}
}
module.exports = function makeProgram(program) {
program
.name(PKG.name)
.description(PKG.description, {
INPUT: 'Alias to --input',
})
.version(PKG.version, '-v, --version')
.arguments('[INPUT...]')
.option('-i, --input <INPUT...>', 'Input files, "-" for STDIN')
.option('-s, --string <STRING>', 'Input SVG data string')
.option(
'-f, --folder <FOLDER>',
'Input folder, optimize and rewrite all *.svg files'
)
.option(
'-o, --output <OUTPUT...>',
'Output file or folder (by default the same as the input), "-" for STDOUT'
)
.option(
'-p, --precision <INTEGER>',
'Set number of digits in the fractional part, overrides plugins params'
)
.option('--config <CONFIG>', 'Custom config file, only .js is supported')
.option(
'--datauri <FORMAT>',
'Output as Data URI string (base64), URI encoded (enc) or unencoded (unenc)'
)
.option(
'--multipass',
'Pass over SVGs multiple times to ensure all optimizations are applied'
)
.option('--pretty', 'Make SVG pretty printed')
.option('--indent <INTEGER>', 'Indent number when pretty printing SVGs')
.option(
'--eol <EOL>',
'Line break to use when outputting SVG: lf, crlf. If unspecified, uses platform default.'
)
.option('--final-newline', 'Ensure SVG ends with a line break')
.option(
'-r, --recursive',
"Use with '--folder'. Optimizes *.svg files in folders recursively."
)
.option(
'--exclude <PATTERN...>',
"Use with '--folder'. Exclude files matching regular expression pattern."
)
.option(
'-q, --quiet',
'Only output error messages, not regular status messages'
)
.option('--show-plugins', 'Show available plugins and exit')
// used by picocolors internally
.option('--no-color', 'Output plain text without color')
.action(action);
};
async function action(args, opts, command) {
var input = opts.input || args;
var output = opts.output;
var config = {};
if (opts.precision != null) {
const number = Number.parseInt(opts.precision, 10);
if (Number.isNaN(number)) {
console.error(
"error: option '-p, --precision' argument must be an integer number"
);
process.exit(1);
} else {
opts.precision = number;
}
}
if (opts.datauri != null) {
if (
opts.datauri !== 'base64' &&
opts.datauri !== 'enc' &&
opts.datauri !== 'unenc'
) {
console.error(
"error: option '--datauri' must have one of the following values: 'base64', 'enc' or 'unenc'"
);
process.exit(1);
}
}
if (opts.indent != null) {
const number = Number.parseInt(opts.indent, 10);
if (Number.isNaN(number)) {
console.error(
"error: option '--indent' argument must be an integer number"
);
process.exit(1);
} else {
opts.indent = number;
}
}
if (opts.eol != null && opts.eol !== 'lf' && opts.eol !== 'crlf') {
console.error(
"error: option '--eol' must have one of the following values: 'lf' or 'crlf'"
);
process.exit(1);
}
// --show-plugins
if (opts.showPlugins) {
showAvailablePlugins();
return;
}
// w/o anything
if (
(input.length === 0 || input[0] === '-') &&
!opts.string &&
!opts.stdin &&
!opts.folder &&
process.stdin.isTTY === true
) {
return command.help();
}
if (
typeof process == 'object' &&
process.versions &&
process.versions.node &&
PKG &&
PKG.engines.node
) {
var nodeVersion = String(PKG.engines.node).match(/\d*(\.\d+)*/)[0];
if (parseFloat(process.versions.node) < parseFloat(nodeVersion)) {
throw Error(
`${PKG.name} requires Node.js version ${nodeVersion} or higher.`
);
}
}
// --config
const loadedConfig = await loadConfig(opts.config);
if (loadedConfig != null) {
config = loadedConfig;
}
// --quiet
if (opts.quiet) {
config.quiet = opts.quiet;
}
// --recursive
if (opts.recursive) {
config.recursive = opts.recursive;
}
// --exclude
config.exclude = opts.exclude
? opts.exclude.map((pattern) => RegExp(pattern))
: [];
// --precision
if (opts.precision != null) {
var precision = Math.min(Math.max(0, opts.precision), 20);
config.floatPrecision = precision;
}
// --multipass
if (opts.multipass) {
config.multipass = true;
}
// --pretty
if (opts.pretty) {
config.js2svg = config.js2svg || {};
config.js2svg.pretty = true;
if (opts.indent != null) {
config.js2svg.indent = opts.indent;
}
}
// --eol
if (opts.eol) {
config.js2svg = config.js2svg || {};
config.js2svg.eol = opts.eol;
}
// --final-newline
if (opts.finalNewline) {
config.js2svg = config.js2svg || {};
config.js2svg.finalNewline = true;
}
// --output
if (output) {
if (input.length && input[0] != '-') {
if (output.length == 1 && checkIsDir(output[0])) {
var dir = output[0];
for (var i = 0; i < input.length; i++) {
output[i] = checkIsDir(input[i])
? input[i]
: path.resolve(dir, path.basename(input[i]));
}
} else if (output.length < input.length) {
output = output.concat(input.slice(output.length));
}
}
} else if (input.length) {
output = input;
} else if (opts.string) {
output = '-';
}
if (opts.datauri) {
config.datauri = opts.datauri;
}
// --folder
if (opts.folder) {
var ouputFolder = (output && output[0]) || opts.folder;
await optimizeFolder(config, opts.folder, ouputFolder);
}
// --input
if (input.length !== 0) {
// STDIN
if (input[0] === '-') {
return new Promise((resolve, reject) => {
var data = '',
file = output[0];
process.stdin
.on('data', (chunk) => (data += chunk))
.once('end', () =>
processSVGData(config, { input: 'string' }, data, file).then(
resolve,
reject
)
);
});
// file
} else {
await Promise.all(
input.map((file, n) => optimizeFile(config, file, output[n]))
);
}
// --string
} else if (opts.string) {
var data = decodeSVGDatauri(opts.string);
return processSVGData(config, { input: 'string' }, data, output[0]);
}
}
/**
* Optimize SVG files in a directory.
* @param {Object} config options
* @param {string} dir input directory
* @param {string} output output directory
* @return {Promise}
*/
function optimizeFolder(config, dir, output) {
if (!config.quiet) {
console.log(`Processing directory '${dir}':\n`);
}
return fs.promises
.readdir(dir)
.then((files) => processDirectory(config, dir, files, output));
}
/**
* Process given files, take only SVG.
* @param {Object} config options
* @param {string} dir input directory
* @param {Array} files list of file names in the directory
* @param {string} output output directory
* @return {Promise}
*/
function processDirectory(config, dir, files, output) {
// take only *.svg files, recursively if necessary
var svgFilesDescriptions = getFilesDescriptions(config, dir, files, output);
return svgFilesDescriptions.length
? Promise.all(
svgFilesDescriptions.map((fileDescription) =>
optimizeFile(
config,
fileDescription.inputPath,
fileDescription.outputPath
)
)
)
: Promise.reject(
new Error(`No SVG files have been found in '${dir}' directory.`)
);
}
/**
* Get svg files descriptions
* @param {Object} config options
* @param {string} dir input directory
* @param {Array} files list of file names in the directory
* @param {string} output output directory
* @return {Array}
*/
function getFilesDescriptions(config, dir, files, output) {
const filesInThisFolder = files
.filter(
(name) =>
regSVGFile.test(name) &&
!config.exclude.some((regExclude) => regExclude.test(name))
)
.map((name) => ({
inputPath: path.resolve(dir, name),
outputPath: path.resolve(output, name),
}));
return config.recursive
? [].concat(
filesInThisFolder,
files
.filter((name) => checkIsDir(path.resolve(dir, name)))
.map((subFolderName) => {
const subFolderPath = path.resolve(dir, subFolderName);
const subFolderFiles = fs.readdirSync(subFolderPath);
const subFolderOutput = path.resolve(output, subFolderName);
return getFilesDescriptions(
config,
subFolderPath,
subFolderFiles,
subFolderOutput
);
})
.reduce((a, b) => [].concat(a, b), [])
)
: filesInThisFolder;
}
/**
* Read SVG file and pass to processing.
* @param {Object} config options
* @param {string} file
* @param {string} output
* @return {Promise}
*/
function optimizeFile(config, file, output) {
return fs.promises.readFile(file, 'utf8').then(
(data) =>
processSVGData(config, { input: 'file', path: file }, data, output, file),
(error) => checkOptimizeFileError(config, file, output, error)
);
}
/**
* Optimize SVG data.
* @param {Object} config options
* @param {string} data SVG content to optimize
* @param {string} output where to write optimized file
* @param {string} [input] input file name (being used if output is a directory)
* @return {Promise}
*/
function processSVGData(config, info, data, output, input) {
var startTime = Date.now(),
prevFileSize = Buffer.byteLength(data, 'utf8');
const result = optimize(data, { ...config, ...info });
if (result.modernError) {
console.error(colors.red(result.modernError.toString()));
process.exit(1);
}
if (config.datauri) {
result.data = encodeSVGDatauri(result.data, config.datauri);
}
var resultFileSize = Buffer.byteLength(result.data, 'utf8'),
processingTime = Date.now() - startTime;
return writeOutput(input, output, result.data).then(
function () {
if (!config.quiet && output != '-') {
if (input) {
console.log(`\n${path.basename(input)}:`);
}
printTimeInfo(processingTime);
printProfitInfo(prevFileSize, resultFileSize);
}
},
(error) =>
Promise.reject(
new Error(
error.code === 'ENOTDIR'
? `Error: output '${output}' is not a directory.`
: error
)
)
);
}
/**
* Write result of an optimization.
* @param {string} input
* @param {string} output output file name. '-' for stdout
* @param {string} data data to write
* @return {Promise}
*/
function writeOutput(input, output, data) {
if (output == '-') {
console.log(data);
return Promise.resolve();
}
fs.mkdirSync(path.dirname(output), { recursive: true });
return fs.promises
.writeFile(output, data, 'utf8')
.catch((error) => checkWriteFileError(input, output, data, error));
}
/**
* Write a time taken by optimization.
* @param {number} time time in milliseconds.
*/
function printTimeInfo(time) {
console.log(`Done in ${time} ms!`);
}
/**
* Write optimizing information in human readable format.
* @param {number} inBytes size before optimization.
* @param {number} outBytes size after optimization.
*/
function printProfitInfo(inBytes, outBytes) {
var profitPercents = 100 - (outBytes * 100) / inBytes;
console.log(
Math.round((inBytes / 1024) * 1000) / 1000 +
' KiB' +
(profitPercents < 0 ? ' + ' : ' - ') +
colors.green(Math.abs(Math.round(profitPercents * 10) / 10) + '%') +
' = ' +
Math.round((outBytes / 1024) * 1000) / 1000 +
' KiB'
);
}
/**
* Check for errors, if it's a dir optimize the dir.
* @param {Object} config
* @param {string} input
* @param {string} output
* @param {Error} error
* @return {Promise}
*/
function checkOptimizeFileError(config, input, output, error) {
if (error.code == 'EISDIR') {
return optimizeFolder(config, input, output);
} else if (error.code == 'ENOENT') {
return Promise.reject(
new Error(`Error: no such file or directory '${error.path}'.`)
);
}
return Promise.reject(error);
}
/**
* Check for saving file error. If the output is a dir, then write file there.
* @param {string} input
* @param {string} output
* @param {string} data
* @param {Error} error
* @return {Promise}
*/
function checkWriteFileError(input, output, data, error) {
if (error.code == 'EISDIR' && input) {
return fs.promises.writeFile(
path.resolve(output, path.basename(input)),
data,
'utf8'
);
} else {
return Promise.reject(error);
}
}
/**
* Show list of available plugins with short description.
*/
function showAvailablePlugins() {
const list = Object.entries(pluginsMap)
.sort(([a], [b]) => a.localeCompare(b))
.map(([name, plugin]) => ` [ ${colors.green(name)} ] ${plugin.description}`)
.join('\n');
console.log('Currently available plugins:\n' + list);
}
module.exports.checkIsDir = checkIsDir;

138
node_modules/svgo/lib/svgo/config.js generated vendored Normal file
View File

@@ -0,0 +1,138 @@
'use strict';
const pluginsMap = require('../../plugins/plugins.js');
const pluginsOrder = [
'removeDoctype',
'removeXMLProcInst',
'removeComments',
'removeMetadata',
'removeXMLNS',
'removeEditorsNSData',
'cleanupAttrs',
'mergeStyles',
'inlineStyles',
'minifyStyles',
'convertStyleToAttrs',
'cleanupIDs',
'prefixIds',
'removeRasterImages',
'removeUselessDefs',
'cleanupNumericValues',
'cleanupListOfValues',
'convertColors',
'removeUnknownsAndDefaults',
'removeNonInheritableGroupAttrs',
'removeUselessStrokeAndFill',
'removeViewBox',
'cleanupEnableBackground',
'removeHiddenElems',
'removeEmptyText',
'convertShapeToPath',
'convertEllipseToCircle',
'moveElemsAttrsToGroup',
'moveGroupAttrsToElems',
'collapseGroups',
'convertPathData',
'convertTransform',
'removeEmptyAttrs',
'removeEmptyContainers',
'mergePaths',
'removeUnusedNS',
'sortAttrs',
'sortDefsChildren',
'removeTitle',
'removeDesc',
'removeDimensions',
'removeAttrs',
'removeAttributesBySelector',
'removeElementsByAttr',
'addClassesToSVGElement',
'removeStyleElement',
'removeScriptElement',
'addAttributesToSVGElement',
'removeOffCanvasPaths',
'reusePaths',
];
const defaultPlugins = pluginsOrder.filter((name) => pluginsMap[name].active);
exports.defaultPlugins = defaultPlugins;
const extendDefaultPlugins = (plugins) => {
console.warn(
'\n"extendDefaultPlugins" utility is deprecated.\n' +
'Use "preset-default" plugin with overrides instead.\n' +
'For example:\n' +
`{\n` +
` name: 'preset-default',\n` +
` params: {\n` +
` overrides: {\n` +
` // customize plugin options\n` +
` convertShapeToPath: {\n` +
` convertArcs: true\n` +
` },\n` +
` // disable plugins\n` +
` convertPathData: false\n` +
` }\n` +
` }\n` +
`}\n`
);
const extendedPlugins = pluginsOrder.map((name) => ({
name,
active: pluginsMap[name].active,
}));
for (const plugin of plugins) {
const resolvedPlugin = resolvePluginConfig(plugin);
const index = pluginsOrder.indexOf(resolvedPlugin.name);
if (index === -1) {
extendedPlugins.push(plugin);
} else {
extendedPlugins[index] = plugin;
}
}
return extendedPlugins;
};
exports.extendDefaultPlugins = extendDefaultPlugins;
const resolvePluginConfig = (plugin) => {
let configParams = {};
if (typeof plugin === 'string') {
// resolve builtin plugin specified as string
const pluginConfig = pluginsMap[plugin];
if (pluginConfig == null) {
throw Error(`Unknown builtin plugin "${plugin}" specified.`);
}
return {
...pluginConfig,
name: plugin,
active: true,
params: { ...pluginConfig.params, ...configParams },
};
}
if (typeof plugin === 'object' && plugin != null) {
if (plugin.name == null) {
throw Error(`Plugin name should be specified`);
}
if (plugin.fn) {
// resolve custom plugin with implementation
return {
active: true,
...plugin,
params: { ...configParams, ...plugin.params },
};
} else {
// resolve builtin plugin specified as object without implementation
const pluginConfig = pluginsMap[plugin.name];
if (pluginConfig == null) {
throw Error(`Unknown builtin plugin "${plugin.name}" specified.`);
}
return {
...pluginConfig,
active: true,
...plugin,
params: { ...pluginConfig.params, ...configParams, ...plugin.params },
};
}
}
return null;
};
exports.resolvePluginConfig = resolvePluginConfig;

72
node_modules/svgo/lib/svgo/css-class-list.js generated vendored Normal file
View File

@@ -0,0 +1,72 @@
'use strict';
var CSSClassList = function (node) {
this.parentNode = node;
this.classNames = new Set();
const value = node.attributes.class;
if (value != null) {
this.addClassValueHandler();
this.setClassValue(value);
}
};
// attr.class.value
CSSClassList.prototype.addClassValueHandler = function () {
Object.defineProperty(this.parentNode.attributes, 'class', {
get: this.getClassValue.bind(this),
set: this.setClassValue.bind(this),
enumerable: true,
configurable: true,
});
};
CSSClassList.prototype.getClassValue = function () {
var arrClassNames = Array.from(this.classNames);
return arrClassNames.join(' ');
};
CSSClassList.prototype.setClassValue = function (newValue) {
if (typeof newValue === 'undefined') {
this.classNames.clear();
return;
}
var arrClassNames = newValue.split(' ');
this.classNames = new Set(arrClassNames);
};
CSSClassList.prototype.add = function (/* variadic */) {
this.addClassValueHandler();
Object.values(arguments).forEach(this._addSingle.bind(this));
};
CSSClassList.prototype._addSingle = function (className) {
this.classNames.add(className);
};
CSSClassList.prototype.remove = function (/* variadic */) {
this.addClassValueHandler();
Object.values(arguments).forEach(this._removeSingle.bind(this));
};
CSSClassList.prototype._removeSingle = function (className) {
this.classNames.delete(className);
};
CSSClassList.prototype.item = function (index) {
var arrClassNames = Array.from(this.classNames);
return arrClassNames[index];
};
CSSClassList.prototype.toggle = function (className, force) {
if (this.contains(className) || force === false) {
this.classNames.delete(className);
}
this.classNames.add(className);
};
CSSClassList.prototype.contains = function (className) {
return this.classNames.has(className);
};
module.exports = CSSClassList;

2
node_modules/svgo/lib/svgo/css-select-adapter.d.ts generated vendored Normal file
View File

@@ -0,0 +1,2 @@
declare let obj: any;
export = obj;

120
node_modules/svgo/lib/svgo/css-select-adapter.js generated vendored Normal file
View File

@@ -0,0 +1,120 @@
'use strict';
const isTag = (node) => {
return node.type === 'element';
};
const existsOne = (test, elems) => {
return elems.some((elem) => {
if (isTag(elem)) {
return test(elem) || existsOne(test, getChildren(elem));
} else {
return false;
}
});
};
const getAttributeValue = (elem, name) => {
return elem.attributes[name];
};
const getChildren = (node) => {
return node.children || [];
};
const getName = (elemAst) => {
return elemAst.name;
};
const getParent = (node) => {
return node.parentNode || null;
};
const getSiblings = (elem) => {
var parent = getParent(elem);
return parent ? getChildren(parent) : [];
};
const getText = (node) => {
if (node.children[0].type === 'text' && node.children[0].type === 'cdata') {
return node.children[0].value;
}
return '';
};
const hasAttrib = (elem, name) => {
return elem.attributes[name] !== undefined;
};
const removeSubsets = (nodes) => {
let idx = nodes.length;
let node;
let ancestor;
let replace;
// Check if each node (or one of its ancestors) is already contained in the
// array.
while (--idx > -1) {
node = ancestor = nodes[idx];
// Temporarily remove the node under consideration
nodes[idx] = null;
replace = true;
while (ancestor) {
if (nodes.includes(ancestor)) {
replace = false;
nodes.splice(idx, 1);
break;
}
ancestor = getParent(ancestor);
}
// If the node has been found to be unique, re-insert it.
if (replace) {
nodes[idx] = node;
}
}
return nodes;
};
const findAll = (test, elems) => {
const result = [];
for (const elem of elems) {
if (isTag(elem)) {
if (test(elem)) {
result.push(elem);
}
result.push(...findAll(test, getChildren(elem)));
}
}
return result;
};
const findOne = (test, elems) => {
for (const elem of elems) {
if (isTag(elem)) {
if (test(elem)) {
return elem;
}
const result = findOne(test, getChildren(elem));
if (result) {
return result;
}
}
}
return null;
};
const svgoCssSelectAdapter = {
isTag,
existsOne,
getAttributeValue,
getChildren,
getName,
getParent,
getSiblings,
getText,
hasAttrib,
removeSubsets,
findAll,
findOne,
};
module.exports = svgoCssSelectAdapter;

232
node_modules/svgo/lib/svgo/css-style-declaration.js generated vendored Normal file
View File

@@ -0,0 +1,232 @@
'use strict';
var csstree = require('css-tree'),
csstools = require('../css-tools');
var CSSStyleDeclaration = function (node) {
this.parentNode = node;
this.properties = new Map();
this.hasSynced = false;
this.styleValue = null;
this.parseError = false;
const value = node.attributes.style;
if (value != null) {
this.addStyleValueHandler();
this.setStyleValue(value);
}
};
// attr.style.value
CSSStyleDeclaration.prototype.addStyleValueHandler = function () {
Object.defineProperty(this.parentNode.attributes, 'style', {
get: this.getStyleValue.bind(this),
set: this.setStyleValue.bind(this),
enumerable: true,
configurable: true,
});
};
CSSStyleDeclaration.prototype.getStyleValue = function () {
return this.getCssText();
};
CSSStyleDeclaration.prototype.setStyleValue = function (newValue) {
this.properties.clear(); // reset all existing properties
this.styleValue = newValue;
this.hasSynced = false; // raw css changed
};
CSSStyleDeclaration.prototype._loadCssText = function () {
if (this.hasSynced) {
return;
}
this.hasSynced = true; // must be set here to prevent loop in setProperty(...)
if (!this.styleValue || this.styleValue.length === 0) {
return;
}
var inlineCssStr = this.styleValue;
var declarations = {};
try {
declarations = csstree.parse(inlineCssStr, {
context: 'declarationList',
parseValue: false,
});
} catch (parseError) {
this.parseError = parseError;
return;
}
this.parseError = false;
var self = this;
declarations.children.each(function (declaration) {
try {
var styleDeclaration = csstools.csstreeToStyleDeclaration(declaration);
self.setProperty(
styleDeclaration.name,
styleDeclaration.value,
styleDeclaration.priority
);
} catch (styleError) {
if (styleError.message !== 'Unknown node type: undefined') {
self.parseError = styleError;
}
}
});
};
// only reads from properties
/**
* Get the textual representation of the declaration block (equivalent to .cssText attribute).
*
* @return {string} Textual representation of the declaration block (empty string for no properties)
*/
CSSStyleDeclaration.prototype.getCssText = function () {
var properties = this.getProperties();
if (this.parseError) {
// in case of a parse error, pass through original styles
return this.styleValue;
}
var cssText = [];
properties.forEach(function (property, propertyName) {
var strImportant = property.priority === 'important' ? '!important' : '';
cssText.push(
propertyName.trim() + ':' + property.value.trim() + strImportant
);
});
return cssText.join(';');
};
CSSStyleDeclaration.prototype._handleParseError = function () {
if (this.parseError) {
console.warn(
"Warning: Parse error when parsing inline styles, style properties of this element cannot be used. The raw styles can still be get/set using .attr('style').value. Error details: " +
this.parseError
);
}
};
CSSStyleDeclaration.prototype._getProperty = function (propertyName) {
if (typeof propertyName === 'undefined') {
throw Error('1 argument required, but only 0 present.');
}
var properties = this.getProperties();
this._handleParseError();
var property = properties.get(propertyName.trim());
return property;
};
/**
* Return the optional priority, "important".
*
* @param {string} propertyName representing the property name to be checked.
* @return {string} priority that represents the priority (e.g. "important") if one exists. If none exists, returns the empty string.
*/
CSSStyleDeclaration.prototype.getPropertyPriority = function (propertyName) {
var property = this._getProperty(propertyName);
return property ? property.priority : '';
};
/**
* Return the property value given a property name.
*
* @param {string} propertyName representing the property name to be checked.
* @return {string} value containing the value of the property. If not set, returns the empty string.
*/
CSSStyleDeclaration.prototype.getPropertyValue = function (propertyName) {
var property = this._getProperty(propertyName);
return property ? property.value : null;
};
/**
* Return a property name.
*
* @param {number} index of the node to be fetched. The index is zero-based.
* @return {string} propertyName that is the name of the CSS property at the specified index.
*/
CSSStyleDeclaration.prototype.item = function (index) {
if (typeof index === 'undefined') {
throw Error('1 argument required, but only 0 present.');
}
var properties = this.getProperties();
this._handleParseError();
return Array.from(properties.keys())[index];
};
/**
* Return all properties of the node.
*
* @return {Map} properties that is a Map with propertyName as key and property (propertyValue + propertyPriority) as value.
*/
CSSStyleDeclaration.prototype.getProperties = function () {
this._loadCssText();
return this.properties;
};
// writes to properties
/**
* Remove a property from the CSS declaration block.
*
* @param {string} propertyName representing the property name to be removed.
* @return {string} oldValue equal to the value of the CSS property before it was removed.
*/
CSSStyleDeclaration.prototype.removeProperty = function (propertyName) {
if (typeof propertyName === 'undefined') {
throw Error('1 argument required, but only 0 present.');
}
this.addStyleValueHandler();
var properties = this.getProperties();
this._handleParseError();
var oldValue = this.getPropertyValue(propertyName);
properties.delete(propertyName.trim());
return oldValue;
};
/**
* Modify an existing CSS property or creates a new CSS property in the declaration block.
*
* @param {string} propertyName representing the CSS property name to be modified.
* @param {string} value containing the new property value. If not specified, treated as the empty string. value must not contain "!important" -- that should be set using the priority parameter.
* @param {string} priority allowing the "important" CSS priority to be set. If not specified, treated as the empty string.
* @return {{value: string, priority: string}}
*/
CSSStyleDeclaration.prototype.setProperty = function (
propertyName,
value,
priority
) {
if (typeof propertyName === 'undefined') {
throw Error('propertyName argument required, but only not present.');
}
this.addStyleValueHandler();
var properties = this.getProperties();
this._handleParseError();
var property = {
value: value.trim(),
priority: priority.trim(),
};
properties.set(propertyName.trim(), property);
return property;
};
module.exports = CSSStyleDeclaration;

2
node_modules/svgo/lib/svgo/jsAPI.d.ts generated vendored Normal file
View File

@@ -0,0 +1,2 @@
declare let obj: any;
export = obj;

443
node_modules/svgo/lib/svgo/jsAPI.js generated vendored Normal file
View File

@@ -0,0 +1,443 @@
'use strict';
const { selectAll, selectOne, is } = require('css-select');
const svgoCssSelectAdapter = require('./css-select-adapter');
const CSSClassList = require('./css-class-list');
const CSSStyleDeclaration = require('./css-style-declaration');
/**
* @type {(name: string) => { prefix: string, local: string }}
*/
const parseName = (name) => {
if (name == null) {
return {
prefix: '',
local: '',
};
}
if (name === 'xmlns') {
return {
prefix: 'xmlns',
local: '',
};
}
const chunks = name.split(':');
if (chunks.length === 1) {
return {
prefix: '',
local: chunks[0],
};
}
return {
prefix: chunks[0],
local: chunks[1],
};
};
var cssSelectOpts = {
xmlMode: true,
adapter: svgoCssSelectAdapter,
};
const attrsHandler = {
get: (attributes, name) => {
// eslint-disable-next-line no-prototype-builtins
if (attributes.hasOwnProperty(name)) {
return {
name,
get value() {
return attributes[name];
},
set value(value) {
attributes[name] = value;
},
};
}
},
set: (attributes, name, attr) => {
attributes[name] = attr.value;
return true;
},
};
var JSAPI = function (data, parentNode) {
Object.assign(this, data);
if (this.type === 'element') {
if (this.attributes == null) {
this.attributes = {};
}
if (this.children == null) {
this.children = [];
}
Object.defineProperty(this, 'class', {
writable: true,
configurable: true,
value: new CSSClassList(this),
});
Object.defineProperty(this, 'style', {
writable: true,
configurable: true,
value: new CSSStyleDeclaration(this),
});
Object.defineProperty(this, 'parentNode', {
writable: true,
value: parentNode,
});
// temporary attrs polyfill
// TODO remove after migration
const element = this;
Object.defineProperty(this, 'attrs', {
configurable: true,
get() {
return new Proxy(element.attributes, attrsHandler);
},
set(value) {
const newAttributes = {};
for (const attr of Object.values(value)) {
newAttributes[attr.name] = attr.value;
}
element.attributes = newAttributes;
},
});
}
};
module.exports = JSAPI;
/**
* Perform a deep clone of this node.
*
* @return {Object} element
*/
JSAPI.prototype.clone = function () {
const { children, ...nodeData } = this;
// Deep-clone node data.
const clonedNode = new JSAPI(JSON.parse(JSON.stringify(nodeData)), null);
if (children) {
clonedNode.children = children.map((child) => {
const clonedChild = child.clone();
clonedChild.parentNode = clonedNode;
return clonedChild;
});
}
return clonedNode;
};
/**
* Determine if item is an element
* (any, with a specific name or in a names array).
*
* @param {String|Array} [param] element name or names arrays
* @return {Boolean}
*/
JSAPI.prototype.isElem = function (param) {
if (this.type !== 'element') {
return false;
}
if (param == null) {
return true;
}
if (Array.isArray(param)) {
return param.includes(this.name);
}
return this.name === param;
};
/**
* Renames an element
*
* @param {String} name new element name
* @return {Object} element
*/
JSAPI.prototype.renameElem = function (name) {
if (name && typeof name === 'string') this.name = name;
return this;
};
/**
* Determine if element is empty.
*
* @return {Boolean}
*/
JSAPI.prototype.isEmpty = function () {
return !this.children || !this.children.length;
};
/**
* Find the closest ancestor of the current element.
* @param elemName
*
* @return {?Object}
*/
JSAPI.prototype.closestElem = function (elemName) {
var elem = this;
while ((elem = elem.parentNode) && !elem.isElem(elemName));
return elem;
};
/**
* Changes children by removing elements and/or adding new elements.
*
* @param {Number} start Index at which to start changing the children.
* @param {Number} n Number of elements to remove.
* @param {Array|Object} [insertion] Elements to add to the children.
* @return {Array} Removed elements.
*/
JSAPI.prototype.spliceContent = function (start, n, insertion) {
if (arguments.length < 2) return [];
if (!Array.isArray(insertion))
insertion = Array.apply(null, arguments).slice(2);
insertion.forEach(function (inner) {
inner.parentNode = this;
}, this);
return this.children.splice.apply(
this.children,
[start, n].concat(insertion)
);
};
/**
* Determine if element has an attribute
* (any, or by name or by name + value).
*
* @param {String} [name] attribute name
* @param {String} [val] attribute value (will be toString()'ed)
* @return {Boolean}
*/
JSAPI.prototype.hasAttr = function (name, val) {
if (this.type !== 'element') {
return false;
}
if (Object.keys(this.attributes).length === 0) {
return false;
}
if (name == null) {
return true;
}
// eslint-disable-next-line no-prototype-builtins
if (this.attributes.hasOwnProperty(name) === false) {
return false;
}
if (val !== undefined) {
return this.attributes[name] === val.toString();
}
return true;
};
/**
* Determine if element has an attribute by local name
* (any, or by name or by name + value).
*
* @param {String} [localName] local attribute name
* @param {Number|String|RegExp|Function} [val] attribute value (will be toString()'ed or executed, otherwise ignored)
* @return {Boolean}
*/
JSAPI.prototype.hasAttrLocal = function (localName, val) {
if (!this.attrs || !Object.keys(this.attrs).length) return false;
if (!arguments.length) return !!this.attrs;
var callback;
switch (val != null && val.constructor && val.constructor.name) {
case 'Number': // same as String
case 'String':
callback = stringValueTest;
break;
case 'RegExp':
callback = regexpValueTest;
break;
case 'Function':
callback = funcValueTest;
break;
default:
callback = nameTest;
}
return this.someAttr(callback);
function nameTest(attr) {
const { local } = parseName(attr.name);
return local === localName;
}
function stringValueTest(attr) {
const { local } = parseName(attr.name);
return local === localName && val == attr.value;
}
function regexpValueTest(attr) {
const { local } = parseName(attr.name);
return local === localName && val.test(attr.value);
}
function funcValueTest(attr) {
const { local } = parseName(attr.name);
return local === localName && val(attr.value);
}
};
/**
* Get a specific attribute from an element
* (by name or name + value).
*
* @param {String} name attribute name
* @param {String} [val] attribute value (will be toString()'ed)
* @return {Object|Undefined}
*/
JSAPI.prototype.attr = function (name, val) {
if (this.hasAttr(name, val)) {
return this.attrs[name];
}
};
/**
* Get computed attribute value from an element
*
* @param {String} name attribute name
* @return {Object|Undefined}
*/
JSAPI.prototype.computedAttr = function (name, val) {
if (!arguments.length) return;
for (
var elem = this;
elem && (!elem.hasAttr(name) || !elem.attributes[name]);
elem = elem.parentNode
);
if (val != null) {
return elem ? elem.hasAttr(name, val) : false;
} else if (elem && elem.hasAttr(name)) {
return elem.attributes[name];
}
};
/**
* Remove a specific attribute.
*
* @param {String|Array} name attribute name
* @param {String} [val] attribute value
* @return {Boolean}
*/
JSAPI.prototype.removeAttr = function (name, val) {
if (this.type !== 'element') {
return false;
}
if (arguments.length === 0) {
return false;
}
if (Array.isArray(name)) {
for (const nameItem of name) {
this.removeAttr(nameItem, val);
}
return false;
}
if (this.hasAttr(name, val) === false) {
return false;
}
delete this.attributes[name];
return true;
};
/**
* Add attribute.
*
* @param {Object} [attr={}] attribute object
* @return {Object|Boolean} created attribute or false if no attr was passed in
*/
JSAPI.prototype.addAttr = function (attr) {
attr = attr || {};
if (attr.name === undefined) return false;
this.attributes[attr.name] = attr.value;
if (attr.name === 'class') {
// newly added class attribute
this.class.addClassValueHandler();
}
if (attr.name === 'style') {
// newly added style attribute
this.style.addStyleValueHandler();
}
return this.attrs[attr.name];
};
/**
* Iterates over all attributes.
*
* @param {Function} callback callback
* @param {Object} [context] callback context
* @return {Boolean} false if there are no any attributes
*/
JSAPI.prototype.eachAttr = function (callback, context) {
if (this.type !== 'element') {
return false;
}
if (callback == null) {
return false;
}
for (const attr of Object.values(this.attrs)) {
callback.call(context, attr);
}
return true;
};
/**
* Tests whether some attribute passes the test.
*
* @param {Function} callback callback
* @param {Object} [context] callback context
* @return {Boolean} false if there are no any attributes
*/
JSAPI.prototype.someAttr = function (callback, context) {
if (this.type !== 'element') {
return false;
}
for (const attr of Object.values(this.attrs)) {
if (callback.call(context, attr)) return true;
}
return false;
};
/**
* Evaluate a string of CSS selectors against the element and returns matched elements.
*
* @param {String} selectors CSS selector(s) string
* @return {Array} null if no elements matched
*/
JSAPI.prototype.querySelectorAll = function (selectors) {
var matchedEls = selectAll(selectors, this, cssSelectOpts);
return matchedEls.length > 0 ? matchedEls : null;
};
/**
* Evaluate a string of CSS selectors against the element and returns only the first matched element.
*
* @param {String} selectors CSS selector(s) string
* @return {Array} null if no element matched
*/
JSAPI.prototype.querySelector = function (selectors) {
return selectOne(selectors, this, cssSelectOpts);
};
/**
* Test if a selector matches a given element.
*
* @param {String} selector CSS selector string
* @return {Boolean} true if element would be selected by selector string, false if it does not
*/
JSAPI.prototype.matches = function (selector) {
return is(this, selector, cssSelectOpts);
};

109
node_modules/svgo/lib/svgo/plugins.js generated vendored Normal file
View File

@@ -0,0 +1,109 @@
'use strict';
const { visit } = require('../xast.js');
/**
* Plugins engine.
*
* @module plugins
*
* @param {Object} ast input ast
* @param {Object} info extra information
* @param {Array} plugins plugins object from config
* @return {Object} output ast
*/
const invokePlugins = (ast, info, plugins, overrides, globalOverrides) => {
for (const plugin of plugins) {
const override = overrides == null ? null : overrides[plugin.name];
if (override === false) {
continue;
}
const params = { ...plugin.params, ...globalOverrides, ...override };
if (plugin.type === 'perItem') {
ast = perItem(ast, info, plugin, params);
}
if (plugin.type === 'perItemReverse') {
ast = perItem(ast, info, plugin, params, true);
}
if (plugin.type === 'full') {
if (plugin.active) {
ast = plugin.fn(ast, params, info);
}
}
if (plugin.type === 'visitor') {
if (plugin.active) {
const visitor = plugin.fn(ast, params, info);
if (visitor != null) {
visit(ast, visitor);
}
}
}
}
return ast;
};
exports.invokePlugins = invokePlugins;
/**
* Direct or reverse per-item loop.
*
* @param {Object} data input data
* @param {Object} info extra information
* @param {Array} plugins plugins list to process
* @param {boolean} [reverse] reverse pass?
* @return {Object} output data
*/
function perItem(data, info, plugin, params, reverse) {
function monkeys(items) {
items.children = items.children.filter(function (item) {
// reverse pass
if (reverse && item.children) {
monkeys(item);
}
// main filter
let kept = true;
if (plugin.active) {
kept = plugin.fn(item, params, info) !== false;
}
// direct pass
if (!reverse && item.children) {
monkeys(item);
}
return kept;
});
return items;
}
return monkeys(data);
}
const createPreset = ({ name, plugins }) => {
return {
name,
type: 'full',
fn: (ast, params, info) => {
const { floatPrecision, overrides } = params;
const globalOverrides = {};
if (floatPrecision != null) {
globalOverrides.floatPrecision = floatPrecision;
}
if (overrides) {
for (const [pluginName, override] of Object.entries(overrides)) {
if (override === true) {
console.warn(
`You are trying to enable ${pluginName} which is not part of preset.\n` +
`Try to put it before or after preset, for example\n\n` +
`plugins: [\n` +
` {\n` +
` name: 'preset-default',\n` +
` },\n` +
` 'cleanupListOfValues'\n` +
`]\n`
);
}
}
}
return invokePlugins(ast, info, plugins, overrides, globalOverrides);
},
};
};
exports.createPreset = createPreset;

137
node_modules/svgo/lib/svgo/tools.js generated vendored Normal file
View File

@@ -0,0 +1,137 @@
'use strict';
/**
* @typedef {import('../types').PathDataCommand} PathDataCommand
*/
/**
* Encode plain SVG data string into Data URI string.
*
* @type {(str: string, type?: 'base64' | 'enc' | 'unenc') => string}
*/
exports.encodeSVGDatauri = (str, type) => {
var prefix = 'data:image/svg+xml';
if (!type || type === 'base64') {
// base64
prefix += ';base64,';
str = prefix + Buffer.from(str).toString('base64');
} else if (type === 'enc') {
// URI encoded
str = prefix + ',' + encodeURIComponent(str);
} else if (type === 'unenc') {
// unencoded
str = prefix + ',' + str;
}
return str;
};
/**
* Decode SVG Data URI string into plain SVG string.
*
* @type {(str: string) => string}
*/
exports.decodeSVGDatauri = (str) => {
var regexp = /data:image\/svg\+xml(;charset=[^;,]*)?(;base64)?,(.*)/;
var match = regexp.exec(str);
// plain string
if (!match) return str;
var data = match[3];
if (match[2]) {
// base64
str = Buffer.from(data, 'base64').toString('utf8');
} else if (data.charAt(0) === '%') {
// URI encoded
str = decodeURIComponent(data);
} else if (data.charAt(0) === '<') {
// unencoded
str = data;
}
return str;
};
/**
* @typedef {{
* noSpaceAfterFlags?: boolean,
* leadingZero?: boolean,
* negativeExtraSpace?: boolean
* }} CleanupOutDataParams
*/
/**
* Convert a row of numbers to an optimized string view.
*
* @example
* [0, -1, .5, .5] → "0-1 .5.5"
*
* @type {(data: Array<number>, params: CleanupOutDataParams, command?: PathDataCommand) => string}
*/
exports.cleanupOutData = (data, params, command) => {
let str = '';
let delimiter;
/**
* @type {number}
*/
let prev;
data.forEach((item, i) => {
// space delimiter by default
delimiter = ' ';
// no extra space in front of first number
if (i == 0) delimiter = '';
// no extra space after 'arcto' command flags(large-arc and sweep flags)
// a20 60 45 0 1 30 20 → a20 60 45 0130 20
if (params.noSpaceAfterFlags && (command == 'A' || command == 'a')) {
var pos = i % 7;
if (pos == 4 || pos == 5) delimiter = '';
}
// remove floating-point numbers leading zeros
// 0.5 → .5
// -0.5 → -.5
const itemStr = params.leadingZero
? removeLeadingZero(item)
: item.toString();
// no extra space in front of negative number or
// in front of a floating number if a previous number is floating too
if (
params.negativeExtraSpace &&
delimiter != '' &&
(item < 0 || (itemStr.charAt(0) === '.' && prev % 1 !== 0))
) {
delimiter = '';
}
// save prev item value
prev = item;
str += delimiter + itemStr;
});
return str;
};
/**
* Remove floating-point numbers leading zero.
*
* @example
* 0.5 → .5
*
* @example
* -0.5 → -.5
*
* @type {(num: number) => string}
*/
const removeLeadingZero = (num) => {
var strNum = num.toString();
if (0 < num && num < 1 && strNum.charAt(0) === '0') {
strNum = strNum.slice(1);
} else if (-1 < num && num < 0 && strNum.charAt(1) === '0') {
strNum = strNum.charAt(0) + strNum.slice(2);
}
return strNum;
};
exports.removeLeadingZero = removeLeadingZero;