first commit
This commit is contained in:
239
app_vue/node_modules/svgo/lib/css-tools.js
generated
vendored
Normal file
239
app_vue/node_modules/svgo/lib/css-tools.js
generated
vendored
Normal file
@ -0,0 +1,239 @@
|
||||
'use strict';
|
||||
|
||||
var csstree = require('css-tree'),
|
||||
List = csstree.List,
|
||||
stable = require('stable'),
|
||||
specificity = require('csso/lib/restructure/prepare/specificity');
|
||||
|
||||
/**
|
||||
* Flatten a CSS AST to a selectors list.
|
||||
*
|
||||
* @param {import('css-tree').CssNode} cssAst css-tree AST to flatten
|
||||
* @return {Array} selectors
|
||||
*/
|
||||
function flattenToSelectors(cssAst) {
|
||||
var selectors = [];
|
||||
|
||||
csstree.walk(cssAst, {
|
||||
visit: 'Rule',
|
||||
enter: function (node) {
|
||||
if (node.type !== 'Rule') {
|
||||
return;
|
||||
}
|
||||
|
||||
var atrule = this.atrule;
|
||||
var rule = node;
|
||||
|
||||
node.prelude.children.each(function (selectorNode, selectorItem) {
|
||||
var selector = {
|
||||
item: selectorItem,
|
||||
atrule: atrule,
|
||||
rule: rule,
|
||||
pseudos: /** @type {{item: any; list: any[]}[]} */ ([]),
|
||||
};
|
||||
|
||||
selectorNode.children.each(function (
|
||||
selectorChildNode,
|
||||
selectorChildItem,
|
||||
selectorChildList
|
||||
) {
|
||||
if (
|
||||
selectorChildNode.type === 'PseudoClassSelector' ||
|
||||
selectorChildNode.type === 'PseudoElementSelector'
|
||||
) {
|
||||
selector.pseudos.push({
|
||||
item: selectorChildItem,
|
||||
list: selectorChildList,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
selectors.push(selector);
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
return selectors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter selectors by Media Query.
|
||||
*
|
||||
* @param {Array} selectors to filter
|
||||
* @param {Array} useMqs Array with strings of media queries that should pass (<name> <expression>)
|
||||
* @return {Array} Filtered selectors that match the passed media queries
|
||||
*/
|
||||
function filterByMqs(selectors, useMqs) {
|
||||
return selectors.filter(function (selector) {
|
||||
if (selector.atrule === null) {
|
||||
return ~useMqs.indexOf('');
|
||||
}
|
||||
|
||||
var mqName = selector.atrule.name;
|
||||
var mqStr = mqName;
|
||||
if (
|
||||
selector.atrule.expression &&
|
||||
selector.atrule.expression.children.first().type === 'MediaQueryList'
|
||||
) {
|
||||
var mqExpr = csstree.generate(selector.atrule.expression);
|
||||
mqStr = [mqName, mqExpr].join(' ');
|
||||
}
|
||||
|
||||
return ~useMqs.indexOf(mqStr);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter selectors by the pseudo-elements and/or -classes they contain.
|
||||
*
|
||||
* @param {Array} selectors to filter
|
||||
* @param {Array} usePseudos Array with strings of single or sequence of pseudo-elements and/or -classes that should pass
|
||||
* @return {Array} Filtered selectors that match the passed pseudo-elements and/or -classes
|
||||
*/
|
||||
function filterByPseudos(selectors, usePseudos) {
|
||||
return selectors.filter(function (selector) {
|
||||
var pseudoSelectorsStr = csstree.generate({
|
||||
type: 'Selector',
|
||||
children: new List().fromArray(
|
||||
selector.pseudos.map(function (pseudo) {
|
||||
return pseudo.item.data;
|
||||
})
|
||||
),
|
||||
});
|
||||
return ~usePseudos.indexOf(pseudoSelectorsStr);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove pseudo-elements and/or -classes from the selectors for proper matching.
|
||||
*
|
||||
* @param {Array} selectors to clean
|
||||
* @return {void}
|
||||
*/
|
||||
function cleanPseudos(selectors) {
|
||||
selectors.forEach(function (selector) {
|
||||
selector.pseudos.forEach(function (pseudo) {
|
||||
pseudo.list.remove(pseudo.item);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two selector specificities.
|
||||
* extracted from https://github.com/keeganstreet/specificity/blob/master/specificity.js#L211
|
||||
*
|
||||
* @param {Array} aSpecificity Specificity of selector A
|
||||
* @param {Array} bSpecificity Specificity of selector B
|
||||
* @return {number} Score of selector specificity A compared to selector specificity B
|
||||
*/
|
||||
function compareSpecificity(aSpecificity, bSpecificity) {
|
||||
for (var i = 0; i < 4; i += 1) {
|
||||
if (aSpecificity[i] < bSpecificity[i]) {
|
||||
return -1;
|
||||
} else if (aSpecificity[i] > bSpecificity[i]) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare two simple selectors.
|
||||
*
|
||||
* @param {Object} aSimpleSelectorNode Simple selector A
|
||||
* @param {Object} bSimpleSelectorNode Simple selector B
|
||||
* @return {number} Score of selector A compared to selector B
|
||||
*/
|
||||
function compareSimpleSelectorNode(aSimpleSelectorNode, bSimpleSelectorNode) {
|
||||
var aSpecificity = specificity(aSimpleSelectorNode),
|
||||
bSpecificity = specificity(bSimpleSelectorNode);
|
||||
return compareSpecificity(aSpecificity, bSpecificity);
|
||||
}
|
||||
|
||||
function _bySelectorSpecificity(selectorA, selectorB) {
|
||||
return compareSimpleSelectorNode(selectorA.item.data, selectorB.item.data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort selectors stably by their specificity.
|
||||
*
|
||||
* @param {Array} selectors to be sorted
|
||||
* @return {Array} Stable sorted selectors
|
||||
*/
|
||||
function sortSelectors(selectors) {
|
||||
return stable(selectors, _bySelectorSpecificity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a css-tree AST style declaration to CSSStyleDeclaration property.
|
||||
*
|
||||
* @param {import('css-tree').CssNode} declaration css-tree style declaration
|
||||
* @return {Object} CSSStyleDeclaration property
|
||||
*/
|
||||
function csstreeToStyleDeclaration(declaration) {
|
||||
var propertyName = declaration.property,
|
||||
propertyValue = csstree.generate(declaration.value),
|
||||
propertyPriority = declaration.important ? 'important' : '';
|
||||
return {
|
||||
name: propertyName,
|
||||
value: propertyValue,
|
||||
priority: propertyPriority,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the CSS string of a style element
|
||||
*
|
||||
* @param {Object} elem style element
|
||||
* @return {string} CSS string or empty array if no styles are set
|
||||
*/
|
||||
function getCssStr(elem) {
|
||||
if (
|
||||
elem.children.length > 0 &&
|
||||
(elem.children[0].type === 'text' || elem.children[0].type === 'cdata')
|
||||
) {
|
||||
return elem.children[0].value;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the CSS string of a style element
|
||||
*
|
||||
* @param {Object} elem style element
|
||||
* @param {string} css string to be set
|
||||
* @return {string} reference to field with CSS
|
||||
*/
|
||||
function setCssStr(elem, css) {
|
||||
if (elem.children.length === 0) {
|
||||
elem.children.push({
|
||||
type: 'text',
|
||||
value: '',
|
||||
});
|
||||
}
|
||||
|
||||
if (elem.children[0].type !== 'text' && elem.children[0].type !== 'cdata') {
|
||||
return css;
|
||||
}
|
||||
|
||||
elem.children[0].value = css;
|
||||
|
||||
return css;
|
||||
}
|
||||
|
||||
module.exports.flattenToSelectors = flattenToSelectors;
|
||||
|
||||
module.exports.filterByMqs = filterByMqs;
|
||||
module.exports.filterByPseudos = filterByPseudos;
|
||||
module.exports.cleanPseudos = cleanPseudos;
|
||||
|
||||
module.exports.compareSpecificity = compareSpecificity;
|
||||
module.exports.compareSimpleSelectorNode = compareSimpleSelectorNode;
|
||||
|
||||
module.exports.sortSelectors = sortSelectors;
|
||||
|
||||
module.exports.csstreeToStyleDeclaration = csstreeToStyleDeclaration;
|
||||
|
||||
module.exports.getCssStr = getCssStr;
|
||||
module.exports.setCssStr = setCssStr;
|
259
app_vue/node_modules/svgo/lib/parser.js
generated
vendored
Normal file
259
app_vue/node_modules/svgo/lib/parser.js
generated
vendored
Normal file
@ -0,0 +1,259 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @typedef {import('./types').XastNode} XastNode
|
||||
* @typedef {import('./types').XastInstruction} XastInstruction
|
||||
* @typedef {import('./types').XastDoctype} XastDoctype
|
||||
* @typedef {import('./types').XastComment} XastComment
|
||||
* @typedef {import('./types').XastRoot} XastRoot
|
||||
* @typedef {import('./types').XastElement} XastElement
|
||||
* @typedef {import('./types').XastCdata} XastCdata
|
||||
* @typedef {import('./types').XastText} XastText
|
||||
* @typedef {import('./types').XastParent} XastParent
|
||||
*/
|
||||
|
||||
// @ts-ignore sax will be replaced with something else later
|
||||
const SAX = require('@trysound/sax');
|
||||
const JSAPI = require('./svgo/jsAPI.js');
|
||||
const { textElems } = require('../plugins/_collections.js');
|
||||
|
||||
class SvgoParserError extends Error {
|
||||
/**
|
||||
* @param message {string}
|
||||
* @param line {number}
|
||||
* @param column {number}
|
||||
* @param source {string}
|
||||
* @param file {void | string}
|
||||
*/
|
||||
constructor(message, line, column, source, file) {
|
||||
super(message);
|
||||
this.name = 'SvgoParserError';
|
||||
this.message = `${file || '<input>'}:${line}:${column}: ${message}`;
|
||||
this.reason = message;
|
||||
this.line = line;
|
||||
this.column = column;
|
||||
this.source = source;
|
||||
if (Error.captureStackTrace) {
|
||||
Error.captureStackTrace(this, SvgoParserError);
|
||||
}
|
||||
}
|
||||
toString() {
|
||||
const lines = this.source.split(/\r?\n/);
|
||||
const startLine = Math.max(this.line - 3, 0);
|
||||
const endLine = Math.min(this.line + 2, lines.length);
|
||||
const lineNumberWidth = String(endLine).length;
|
||||
const startColumn = Math.max(this.column - 54, 0);
|
||||
const endColumn = Math.max(this.column + 20, 80);
|
||||
const code = lines
|
||||
.slice(startLine, endLine)
|
||||
.map((line, index) => {
|
||||
const lineSlice = line.slice(startColumn, endColumn);
|
||||
let ellipsisPrefix = '';
|
||||
let ellipsisSuffix = '';
|
||||
if (startColumn !== 0) {
|
||||
ellipsisPrefix = startColumn > line.length - 1 ? ' ' : '…';
|
||||
}
|
||||
if (endColumn < line.length - 1) {
|
||||
ellipsisSuffix = '…';
|
||||
}
|
||||
const number = startLine + 1 + index;
|
||||
const gutter = ` ${number.toString().padStart(lineNumberWidth)} | `;
|
||||
if (number === this.line) {
|
||||
const gutterSpacing = gutter.replace(/[^|]/g, ' ');
|
||||
const lineSpacing = (
|
||||
ellipsisPrefix + line.slice(startColumn, this.column - 1)
|
||||
).replace(/[^\t]/g, ' ');
|
||||
const spacing = gutterSpacing + lineSpacing;
|
||||
return `>${gutter}${ellipsisPrefix}${lineSlice}${ellipsisSuffix}\n ${spacing}^`;
|
||||
}
|
||||
return ` ${gutter}${ellipsisPrefix}${lineSlice}${ellipsisSuffix}`;
|
||||
})
|
||||
.join('\n');
|
||||
return `${this.name}: ${this.message}\n\n${code}\n`;
|
||||
}
|
||||
}
|
||||
|
||||
const entityDeclaration = /<!ENTITY\s+(\S+)\s+(?:'([^']+)'|"([^"]+)")\s*>/g;
|
||||
|
||||
const config = {
|
||||
strict: true,
|
||||
trim: false,
|
||||
normalize: false,
|
||||
lowercase: true,
|
||||
xmlns: true,
|
||||
position: true,
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert SVG (XML) string to SVG-as-JS object.
|
||||
*
|
||||
* @type {(data: string, from?: string) => XastRoot}
|
||||
*/
|
||||
const parseSvg = (data, from) => {
|
||||
const sax = SAX.parser(config.strict, config);
|
||||
/**
|
||||
* @type {XastRoot}
|
||||
*/
|
||||
const root = new JSAPI({ type: 'root', children: [] });
|
||||
/**
|
||||
* @type {XastParent}
|
||||
*/
|
||||
let current = root;
|
||||
/**
|
||||
* @type {Array<XastParent>}
|
||||
*/
|
||||
const stack = [root];
|
||||
|
||||
/**
|
||||
* @type {<T extends XastNode>(node: T) => T}
|
||||
*/
|
||||
const pushToContent = (node) => {
|
||||
const wrapped = new JSAPI(node, current);
|
||||
current.children.push(wrapped);
|
||||
return wrapped;
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {(doctype: string) => void}
|
||||
*/
|
||||
sax.ondoctype = (doctype) => {
|
||||
/**
|
||||
* @type {XastDoctype}
|
||||
*/
|
||||
const node = {
|
||||
type: 'doctype',
|
||||
// TODO parse doctype for name, public and system to match xast
|
||||
name: 'svg',
|
||||
data: {
|
||||
doctype,
|
||||
},
|
||||
};
|
||||
pushToContent(node);
|
||||
const subsetStart = doctype.indexOf('[');
|
||||
if (subsetStart >= 0) {
|
||||
entityDeclaration.lastIndex = subsetStart;
|
||||
let entityMatch = entityDeclaration.exec(data);
|
||||
while (entityMatch != null) {
|
||||
sax.ENTITIES[entityMatch[1]] = entityMatch[2] || entityMatch[3];
|
||||
entityMatch = entityDeclaration.exec(data);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {(data: { name: string, body: string }) => void}
|
||||
*/
|
||||
sax.onprocessinginstruction = (data) => {
|
||||
/**
|
||||
* @type {XastInstruction}
|
||||
*/
|
||||
const node = {
|
||||
type: 'instruction',
|
||||
name: data.name,
|
||||
value: data.body,
|
||||
};
|
||||
pushToContent(node);
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {(comment: string) => void}
|
||||
*/
|
||||
sax.oncomment = (comment) => {
|
||||
/**
|
||||
* @type {XastComment}
|
||||
*/
|
||||
const node = {
|
||||
type: 'comment',
|
||||
value: comment.trim(),
|
||||
};
|
||||
pushToContent(node);
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {(cdata: string) => void}
|
||||
*/
|
||||
sax.oncdata = (cdata) => {
|
||||
/**
|
||||
* @type {XastCdata}
|
||||
*/
|
||||
const node = {
|
||||
type: 'cdata',
|
||||
value: cdata,
|
||||
};
|
||||
pushToContent(node);
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {(data: { name: string, attributes: Record<string, { value: string }>}) => void}
|
||||
*/
|
||||
sax.onopentag = (data) => {
|
||||
/**
|
||||
* @type {XastElement}
|
||||
*/
|
||||
let element = {
|
||||
type: 'element',
|
||||
name: data.name,
|
||||
attributes: {},
|
||||
children: [],
|
||||
};
|
||||
for (const [name, attr] of Object.entries(data.attributes)) {
|
||||
element.attributes[name] = attr.value;
|
||||
}
|
||||
element = pushToContent(element);
|
||||
current = element;
|
||||
stack.push(element);
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {(text: string) => void}
|
||||
*/
|
||||
sax.ontext = (text) => {
|
||||
if (current.type === 'element') {
|
||||
// prevent trimming of meaningful whitespace inside textual tags
|
||||
if (textElems.includes(current.name)) {
|
||||
/**
|
||||
* @type {XastText}
|
||||
*/
|
||||
const node = {
|
||||
type: 'text',
|
||||
value: text,
|
||||
};
|
||||
pushToContent(node);
|
||||
} else if (/\S/.test(text)) {
|
||||
/**
|
||||
* @type {XastText}
|
||||
*/
|
||||
const node = {
|
||||
type: 'text',
|
||||
value: text.trim(),
|
||||
};
|
||||
pushToContent(node);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
sax.onclosetag = () => {
|
||||
stack.pop();
|
||||
current = stack[stack.length - 1];
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {(e: any) => void}
|
||||
*/
|
||||
sax.onerror = (e) => {
|
||||
const error = new SvgoParserError(
|
||||
e.reason,
|
||||
e.line + 1,
|
||||
e.column,
|
||||
data,
|
||||
from
|
||||
);
|
||||
if (e.message.indexOf('Unexpected end') === -1) {
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
sax.write(data).close();
|
||||
return root;
|
||||
};
|
||||
exports.parseSvg = parseSvg;
|
347
app_vue/node_modules/svgo/lib/path.js
generated
vendored
Normal file
347
app_vue/node_modules/svgo/lib/path.js
generated
vendored
Normal file
@ -0,0 +1,347 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @typedef {import('./types').PathDataItem} PathDataItem
|
||||
* @typedef {import('./types').PathDataCommand} PathDataCommand
|
||||
*/
|
||||
|
||||
// Based on https://www.w3.org/TR/SVG11/paths.html#PathDataBNF
|
||||
|
||||
const argsCountPerCommand = {
|
||||
M: 2,
|
||||
m: 2,
|
||||
Z: 0,
|
||||
z: 0,
|
||||
L: 2,
|
||||
l: 2,
|
||||
H: 1,
|
||||
h: 1,
|
||||
V: 1,
|
||||
v: 1,
|
||||
C: 6,
|
||||
c: 6,
|
||||
S: 4,
|
||||
s: 4,
|
||||
Q: 4,
|
||||
q: 4,
|
||||
T: 2,
|
||||
t: 2,
|
||||
A: 7,
|
||||
a: 7,
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {(c: string) => c is PathDataCommand}
|
||||
*/
|
||||
const isCommand = (c) => {
|
||||
return c in argsCountPerCommand;
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {(c: string) => boolean}
|
||||
*/
|
||||
const isWsp = (c) => {
|
||||
const codePoint = c.codePointAt(0);
|
||||
return (
|
||||
codePoint === 0x20 ||
|
||||
codePoint === 0x9 ||
|
||||
codePoint === 0xd ||
|
||||
codePoint === 0xa
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {(c: string) => boolean}
|
||||
*/
|
||||
const isDigit = (c) => {
|
||||
const codePoint = c.codePointAt(0);
|
||||
if (codePoint == null) {
|
||||
return false;
|
||||
}
|
||||
return 48 <= codePoint && codePoint <= 57;
|
||||
};
|
||||
|
||||
/**
|
||||
* @typedef {'none' | 'sign' | 'whole' | 'decimal_point' | 'decimal' | 'e' | 'exponent_sign' | 'exponent'} ReadNumberState
|
||||
*/
|
||||
|
||||
/**
|
||||
* @type {(string: string, cursor: number) => [number, number | null]}
|
||||
*/
|
||||
const readNumber = (string, cursor) => {
|
||||
let i = cursor;
|
||||
let value = '';
|
||||
let state = /** @type {ReadNumberState} */ ('none');
|
||||
for (; i < string.length; i += 1) {
|
||||
const c = string[i];
|
||||
if (c === '+' || c === '-') {
|
||||
if (state === 'none') {
|
||||
state = 'sign';
|
||||
value += c;
|
||||
continue;
|
||||
}
|
||||
if (state === 'e') {
|
||||
state = 'exponent_sign';
|
||||
value += c;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (isDigit(c)) {
|
||||
if (state === 'none' || state === 'sign' || state === 'whole') {
|
||||
state = 'whole';
|
||||
value += c;
|
||||
continue;
|
||||
}
|
||||
if (state === 'decimal_point' || state === 'decimal') {
|
||||
state = 'decimal';
|
||||
value += c;
|
||||
continue;
|
||||
}
|
||||
if (state === 'e' || state === 'exponent_sign' || state === 'exponent') {
|
||||
state = 'exponent';
|
||||
value += c;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (c === '.') {
|
||||
if (state === 'none' || state === 'sign' || state === 'whole') {
|
||||
state = 'decimal_point';
|
||||
value += c;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (c === 'E' || c == 'e') {
|
||||
if (
|
||||
state === 'whole' ||
|
||||
state === 'decimal_point' ||
|
||||
state === 'decimal'
|
||||
) {
|
||||
state = 'e';
|
||||
value += c;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
const number = Number.parseFloat(value);
|
||||
if (Number.isNaN(number)) {
|
||||
return [cursor, null];
|
||||
} else {
|
||||
// step back to delegate iteration to parent loop
|
||||
return [i - 1, number];
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {(string: string) => Array<PathDataItem>}
|
||||
*/
|
||||
const parsePathData = (string) => {
|
||||
/**
|
||||
* @type {Array<PathDataItem>}
|
||||
*/
|
||||
const pathData = [];
|
||||
/**
|
||||
* @type {null | PathDataCommand}
|
||||
*/
|
||||
let command = null;
|
||||
let args = /** @type {number[]} */ ([]);
|
||||
let argsCount = 0;
|
||||
let canHaveComma = false;
|
||||
let hadComma = false;
|
||||
for (let i = 0; i < string.length; i += 1) {
|
||||
const c = string.charAt(i);
|
||||
if (isWsp(c)) {
|
||||
continue;
|
||||
}
|
||||
// allow comma only between arguments
|
||||
if (canHaveComma && c === ',') {
|
||||
if (hadComma) {
|
||||
break;
|
||||
}
|
||||
hadComma = true;
|
||||
continue;
|
||||
}
|
||||
if (isCommand(c)) {
|
||||
if (hadComma) {
|
||||
return pathData;
|
||||
}
|
||||
if (command == null) {
|
||||
// moveto should be leading command
|
||||
if (c !== 'M' && c !== 'm') {
|
||||
return pathData;
|
||||
}
|
||||
} else {
|
||||
// stop if previous command arguments are not flushed
|
||||
if (args.length !== 0) {
|
||||
return pathData;
|
||||
}
|
||||
}
|
||||
command = c;
|
||||
args = [];
|
||||
argsCount = argsCountPerCommand[command];
|
||||
canHaveComma = false;
|
||||
// flush command without arguments
|
||||
if (argsCount === 0) {
|
||||
pathData.push({ command, args });
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// avoid parsing arguments if no command detected
|
||||
if (command == null) {
|
||||
return pathData;
|
||||
}
|
||||
// read next argument
|
||||
let newCursor = i;
|
||||
let number = null;
|
||||
if (command === 'A' || command === 'a') {
|
||||
const position = args.length;
|
||||
if (position === 0 || position === 1) {
|
||||
// allow only positive number without sign as first two arguments
|
||||
if (c !== '+' && c !== '-') {
|
||||
[newCursor, number] = readNumber(string, i);
|
||||
}
|
||||
}
|
||||
if (position === 2 || position === 5 || position === 6) {
|
||||
[newCursor, number] = readNumber(string, i);
|
||||
}
|
||||
if (position === 3 || position === 4) {
|
||||
// read flags
|
||||
if (c === '0') {
|
||||
number = 0;
|
||||
}
|
||||
if (c === '1') {
|
||||
number = 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
[newCursor, number] = readNumber(string, i);
|
||||
}
|
||||
if (number == null) {
|
||||
return pathData;
|
||||
}
|
||||
args.push(number);
|
||||
canHaveComma = true;
|
||||
hadComma = false;
|
||||
i = newCursor;
|
||||
// flush arguments when necessary count is reached
|
||||
if (args.length === argsCount) {
|
||||
pathData.push({ command, args });
|
||||
// subsequent moveto coordinates are threated as implicit lineto commands
|
||||
if (command === 'M') {
|
||||
command = 'L';
|
||||
}
|
||||
if (command === 'm') {
|
||||
command = 'l';
|
||||
}
|
||||
args = [];
|
||||
}
|
||||
}
|
||||
return pathData;
|
||||
};
|
||||
exports.parsePathData = parsePathData;
|
||||
|
||||
/**
|
||||
* @type {(number: number, precision?: number) => string}
|
||||
*/
|
||||
const stringifyNumber = (number, precision) => {
|
||||
if (precision != null) {
|
||||
const ratio = 10 ** precision;
|
||||
number = Math.round(number * ratio) / ratio;
|
||||
}
|
||||
// remove zero whole from decimal number
|
||||
return number.toString().replace(/^0\./, '.').replace(/^-0\./, '-.');
|
||||
};
|
||||
|
||||
/**
|
||||
* Elliptical arc large-arc and sweep flags are rendered with spaces
|
||||
* because many non-browser environments are not able to parse such paths
|
||||
*
|
||||
* @type {(
|
||||
* command: string,
|
||||
* args: number[],
|
||||
* precision?: number,
|
||||
* disableSpaceAfterFlags?: boolean
|
||||
* ) => string}
|
||||
*/
|
||||
const stringifyArgs = (command, args, precision, disableSpaceAfterFlags) => {
|
||||
let result = '';
|
||||
let prev = '';
|
||||
for (let i = 0; i < args.length; i += 1) {
|
||||
const number = args[i];
|
||||
const numberString = stringifyNumber(number, precision);
|
||||
if (
|
||||
disableSpaceAfterFlags &&
|
||||
(command === 'A' || command === 'a') &&
|
||||
// consider combined arcs
|
||||
(i % 7 === 4 || i % 7 === 5)
|
||||
) {
|
||||
result += numberString;
|
||||
} else if (i === 0 || numberString.startsWith('-')) {
|
||||
// avoid space before first and negative numbers
|
||||
result += numberString;
|
||||
} else if (prev.includes('.') && numberString.startsWith('.')) {
|
||||
// remove space before decimal with zero whole
|
||||
// only when previous number is also decimal
|
||||
result += numberString;
|
||||
} else {
|
||||
result += ` ${numberString}`;
|
||||
}
|
||||
prev = numberString;
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
/**
|
||||
* @typedef {{
|
||||
* pathData: Array<PathDataItem>;
|
||||
* precision?: number;
|
||||
* disableSpaceAfterFlags?: boolean;
|
||||
* }} StringifyPathDataOptions
|
||||
*/
|
||||
|
||||
/**
|
||||
* @type {(options: StringifyPathDataOptions) => string}
|
||||
*/
|
||||
const stringifyPathData = ({ pathData, precision, disableSpaceAfterFlags }) => {
|
||||
// combine sequence of the same commands
|
||||
let combined = [];
|
||||
for (let i = 0; i < pathData.length; i += 1) {
|
||||
const { command, args } = pathData[i];
|
||||
if (i === 0) {
|
||||
combined.push({ command, args });
|
||||
} else {
|
||||
/**
|
||||
* @type {PathDataItem}
|
||||
*/
|
||||
const last = combined[combined.length - 1];
|
||||
// match leading moveto with following lineto
|
||||
if (i === 1) {
|
||||
if (command === 'L') {
|
||||
last.command = 'M';
|
||||
}
|
||||
if (command === 'l') {
|
||||
last.command = 'm';
|
||||
}
|
||||
}
|
||||
if (
|
||||
(last.command === command &&
|
||||
last.command !== 'M' &&
|
||||
last.command !== 'm') ||
|
||||
// combine matching moveto and lineto sequences
|
||||
(last.command === 'M' && command === 'L') ||
|
||||
(last.command === 'm' && command === 'l')
|
||||
) {
|
||||
last.args = [...last.args, ...args];
|
||||
} else {
|
||||
combined.push({ command, args });
|
||||
}
|
||||
}
|
||||
}
|
||||
let result = '';
|
||||
for (const { command, args } of combined) {
|
||||
result +=
|
||||
command + stringifyArgs(command, args, precision, disableSpaceAfterFlags);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
exports.stringifyPathData = stringifyPathData;
|
326
app_vue/node_modules/svgo/lib/stringifier.js
generated
vendored
Normal file
326
app_vue/node_modules/svgo/lib/stringifier.js
generated
vendored
Normal file
@ -0,0 +1,326 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @typedef {import('./types').XastParent} XastParent
|
||||
* @typedef {import('./types').XastRoot} XastRoot
|
||||
* @typedef {import('./types').XastElement} XastElement
|
||||
* @typedef {import('./types').XastInstruction} XastInstruction
|
||||
* @typedef {import('./types').XastDoctype} XastDoctype
|
||||
* @typedef {import('./types').XastText} XastText
|
||||
* @typedef {import('./types').XastCdata} XastCdata
|
||||
* @typedef {import('./types').XastComment} XastComment
|
||||
* @typedef {import('./types').StringifyOptions} StringifyOptions
|
||||
*/
|
||||
|
||||
const { textElems } = require('../plugins/_collections.js');
|
||||
|
||||
/**
|
||||
* @typedef {{
|
||||
* width: void | string,
|
||||
* height: void | string,
|
||||
* indent: string,
|
||||
* textContext: null | XastElement,
|
||||
* indentLevel: number,
|
||||
* }} State
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Required<StringifyOptions>} Options
|
||||
*/
|
||||
|
||||
/**
|
||||
* @type {(char: string) => string}
|
||||
*/
|
||||
const encodeEntity = (char) => {
|
||||
return entities[char];
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {Options}
|
||||
*/
|
||||
const defaults = {
|
||||
doctypeStart: '<!DOCTYPE',
|
||||
doctypeEnd: '>',
|
||||
procInstStart: '<?',
|
||||
procInstEnd: '?>',
|
||||
tagOpenStart: '<',
|
||||
tagOpenEnd: '>',
|
||||
tagCloseStart: '</',
|
||||
tagCloseEnd: '>',
|
||||
tagShortStart: '<',
|
||||
tagShortEnd: '/>',
|
||||
attrStart: '="',
|
||||
attrEnd: '"',
|
||||
commentStart: '<!--',
|
||||
commentEnd: '-->',
|
||||
cdataStart: '<![CDATA[',
|
||||
cdataEnd: ']]>',
|
||||
textStart: '',
|
||||
textEnd: '',
|
||||
indent: 4,
|
||||
regEntities: /[&'"<>]/g,
|
||||
regValEntities: /[&"<>]/g,
|
||||
encodeEntity: encodeEntity,
|
||||
pretty: false,
|
||||
useShortTags: true,
|
||||
eol: 'lf',
|
||||
finalNewline: false,
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {Record<string, string>}
|
||||
*/
|
||||
const entities = {
|
||||
'&': '&',
|
||||
"'": ''',
|
||||
'"': '"',
|
||||
'>': '>',
|
||||
'<': '<',
|
||||
};
|
||||
|
||||
/**
|
||||
* convert XAST to SVG string
|
||||
*
|
||||
* @type {(data: XastRoot, config: StringifyOptions) => {
|
||||
* data: string,
|
||||
* info: {
|
||||
* width: void | string,
|
||||
* height: void | string
|
||||
* }
|
||||
* }}
|
||||
*/
|
||||
const stringifySvg = (data, userOptions = {}) => {
|
||||
/**
|
||||
* @type {Options}
|
||||
*/
|
||||
const config = { ...defaults, ...userOptions };
|
||||
const indent = config.indent;
|
||||
let newIndent = ' ';
|
||||
if (typeof indent === 'number' && Number.isNaN(indent) === false) {
|
||||
newIndent = indent < 0 ? '\t' : ' '.repeat(indent);
|
||||
} else if (typeof indent === 'string') {
|
||||
newIndent = indent;
|
||||
}
|
||||
/**
|
||||
* @type {State}
|
||||
*/
|
||||
const state = {
|
||||
// TODO remove width and height in v3
|
||||
width: undefined,
|
||||
height: undefined,
|
||||
indent: newIndent,
|
||||
textContext: null,
|
||||
indentLevel: 0,
|
||||
};
|
||||
const eol = config.eol === 'crlf' ? '\r\n' : '\n';
|
||||
if (config.pretty) {
|
||||
config.doctypeEnd += eol;
|
||||
config.procInstEnd += eol;
|
||||
config.commentEnd += eol;
|
||||
config.cdataEnd += eol;
|
||||
config.tagShortEnd += eol;
|
||||
config.tagOpenEnd += eol;
|
||||
config.tagCloseEnd += eol;
|
||||
config.textEnd += eol;
|
||||
}
|
||||
let svg = stringifyNode(data, config, state);
|
||||
if (config.finalNewline && svg.length > 0 && svg[svg.length - 1] !== '\n') {
|
||||
svg += eol;
|
||||
}
|
||||
return {
|
||||
data: svg,
|
||||
info: {
|
||||
width: state.width,
|
||||
height: state.height,
|
||||
},
|
||||
};
|
||||
};
|
||||
exports.stringifySvg = stringifySvg;
|
||||
|
||||
/**
|
||||
* @type {(node: XastParent, config: Options, state: State) => string}
|
||||
*/
|
||||
const stringifyNode = (data, config, state) => {
|
||||
let svg = '';
|
||||
state.indentLevel += 1;
|
||||
for (const item of data.children) {
|
||||
if (item.type === 'element') {
|
||||
svg += stringifyElement(item, config, state);
|
||||
}
|
||||
if (item.type === 'text') {
|
||||
svg += stringifyText(item, config, state);
|
||||
}
|
||||
if (item.type === 'doctype') {
|
||||
svg += stringifyDoctype(item, config);
|
||||
}
|
||||
if (item.type === 'instruction') {
|
||||
svg += stringifyInstruction(item, config);
|
||||
}
|
||||
if (item.type === 'comment') {
|
||||
svg += stringifyComment(item, config);
|
||||
}
|
||||
if (item.type === 'cdata') {
|
||||
svg += stringifyCdata(item, config, state);
|
||||
}
|
||||
}
|
||||
state.indentLevel -= 1;
|
||||
return svg;
|
||||
};
|
||||
|
||||
/**
|
||||
* create indent string in accordance with the current node level.
|
||||
*
|
||||
* @type {(config: Options, state: State) => string}
|
||||
*/
|
||||
const createIndent = (config, state) => {
|
||||
let indent = '';
|
||||
if (config.pretty && state.textContext == null) {
|
||||
indent = state.indent.repeat(state.indentLevel - 1);
|
||||
}
|
||||
return indent;
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {(node: XastDoctype, config: Options) => string}
|
||||
*/
|
||||
const stringifyDoctype = (node, config) => {
|
||||
return config.doctypeStart + node.data.doctype + config.doctypeEnd;
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {(node: XastInstruction, config: Options) => string}
|
||||
*/
|
||||
const stringifyInstruction = (node, config) => {
|
||||
return (
|
||||
config.procInstStart + node.name + ' ' + node.value + config.procInstEnd
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {(node: XastComment, config: Options) => string}
|
||||
*/
|
||||
const stringifyComment = (node, config) => {
|
||||
return config.commentStart + node.value + config.commentEnd;
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {(node: XastCdata, config: Options, state: State) => string}
|
||||
*/
|
||||
const stringifyCdata = (node, config, state) => {
|
||||
return (
|
||||
createIndent(config, state) +
|
||||
config.cdataStart +
|
||||
node.value +
|
||||
config.cdataEnd
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {(node: XastElement, config: Options, state: State) => string}
|
||||
*/
|
||||
const stringifyElement = (node, config, state) => {
|
||||
// beautiful injection for obtaining SVG information :)
|
||||
if (
|
||||
node.name === 'svg' &&
|
||||
node.attributes.width != null &&
|
||||
node.attributes.height != null
|
||||
) {
|
||||
state.width = node.attributes.width;
|
||||
state.height = node.attributes.height;
|
||||
}
|
||||
|
||||
// empty element and short tag
|
||||
if (node.children.length === 0) {
|
||||
if (config.useShortTags) {
|
||||
return (
|
||||
createIndent(config, state) +
|
||||
config.tagShortStart +
|
||||
node.name +
|
||||
stringifyAttributes(node, config) +
|
||||
config.tagShortEnd
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
createIndent(config, state) +
|
||||
config.tagShortStart +
|
||||
node.name +
|
||||
stringifyAttributes(node, config) +
|
||||
config.tagOpenEnd +
|
||||
config.tagCloseStart +
|
||||
node.name +
|
||||
config.tagCloseEnd
|
||||
);
|
||||
}
|
||||
// non-empty element
|
||||
} else {
|
||||
let tagOpenStart = config.tagOpenStart;
|
||||
let tagOpenEnd = config.tagOpenEnd;
|
||||
let tagCloseStart = config.tagCloseStart;
|
||||
let tagCloseEnd = config.tagCloseEnd;
|
||||
let openIndent = createIndent(config, state);
|
||||
let closeIndent = createIndent(config, state);
|
||||
|
||||
if (state.textContext) {
|
||||
tagOpenStart = defaults.tagOpenStart;
|
||||
tagOpenEnd = defaults.tagOpenEnd;
|
||||
tagCloseStart = defaults.tagCloseStart;
|
||||
tagCloseEnd = defaults.tagCloseEnd;
|
||||
openIndent = '';
|
||||
} else if (textElems.includes(node.name)) {
|
||||
tagOpenEnd = defaults.tagOpenEnd;
|
||||
tagCloseStart = defaults.tagCloseStart;
|
||||
closeIndent = '';
|
||||
state.textContext = node;
|
||||
}
|
||||
|
||||
const children = stringifyNode(node, config, state);
|
||||
|
||||
if (state.textContext === node) {
|
||||
state.textContext = null;
|
||||
}
|
||||
|
||||
return (
|
||||
openIndent +
|
||||
tagOpenStart +
|
||||
node.name +
|
||||
stringifyAttributes(node, config) +
|
||||
tagOpenEnd +
|
||||
children +
|
||||
closeIndent +
|
||||
tagCloseStart +
|
||||
node.name +
|
||||
tagCloseEnd
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {(node: XastElement, config: Options) => string}
|
||||
*/
|
||||
const stringifyAttributes = (node, config) => {
|
||||
let attrs = '';
|
||||
for (const [name, value] of Object.entries(node.attributes)) {
|
||||
// TODO remove attributes without values support in v3
|
||||
if (value !== undefined) {
|
||||
const encodedValue = value
|
||||
.toString()
|
||||
.replace(config.regValEntities, config.encodeEntity);
|
||||
attrs += ' ' + name + config.attrStart + encodedValue + config.attrEnd;
|
||||
} else {
|
||||
attrs += ' ' + name;
|
||||
}
|
||||
}
|
||||
return attrs;
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {(node: XastText, config: Options, state: State) => string}
|
||||
*/
|
||||
const stringifyText = (node, config, state) => {
|
||||
return (
|
||||
createIndent(config, state) +
|
||||
config.textStart +
|
||||
node.value.replace(config.regEntities, config.encodeEntity) +
|
||||
(state.textContext ? '' : config.textEnd)
|
||||
);
|
||||
};
|
283
app_vue/node_modules/svgo/lib/style.js
generated
vendored
Normal file
283
app_vue/node_modules/svgo/lib/style.js
generated
vendored
Normal file
@ -0,0 +1,283 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @typedef {import('css-tree').Rule} CsstreeRule
|
||||
* @typedef {import('./types').Specificity} Specificity
|
||||
* @typedef {import('./types').Stylesheet} Stylesheet
|
||||
* @typedef {import('./types').StylesheetRule} StylesheetRule
|
||||
* @typedef {import('./types').StylesheetDeclaration} StylesheetDeclaration
|
||||
* @typedef {import('./types').ComputedStyles} ComputedStyles
|
||||
* @typedef {import('./types').XastRoot} XastRoot
|
||||
* @typedef {import('./types').XastElement} XastElement
|
||||
* @typedef {import('./types').XastParent} XastParent
|
||||
* @typedef {import('./types').XastChild} XastChild
|
||||
*/
|
||||
|
||||
const stable = require('stable');
|
||||
const csstree = require('css-tree');
|
||||
// @ts-ignore not defined in @types/csso
|
||||
const specificity = require('csso/lib/restructure/prepare/specificity');
|
||||
const { visit, matches } = require('./xast.js');
|
||||
const {
|
||||
attrsGroups,
|
||||
inheritableAttrs,
|
||||
presentationNonInheritableGroupAttrs,
|
||||
} = require('../plugins/_collections.js');
|
||||
|
||||
// @ts-ignore not defined in @types/csstree
|
||||
const csstreeWalkSkip = csstree.walk.skip;
|
||||
|
||||
/**
|
||||
* @type {(ruleNode: CsstreeRule, dynamic: boolean) => StylesheetRule}
|
||||
*/
|
||||
const parseRule = (ruleNode, dynamic) => {
|
||||
let selectors;
|
||||
let selectorsSpecificity;
|
||||
/**
|
||||
* @type {Array<StylesheetDeclaration>}
|
||||
*/
|
||||
const declarations = [];
|
||||
csstree.walk(ruleNode, (cssNode) => {
|
||||
if (cssNode.type === 'SelectorList') {
|
||||
// compute specificity from original node to consider pseudo classes
|
||||
selectorsSpecificity = specificity(cssNode);
|
||||
const newSelectorsNode = csstree.clone(cssNode);
|
||||
csstree.walk(newSelectorsNode, (pseudoClassNode, item, list) => {
|
||||
if (pseudoClassNode.type === 'PseudoClassSelector') {
|
||||
dynamic = true;
|
||||
list.remove(item);
|
||||
}
|
||||
});
|
||||
selectors = csstree.generate(newSelectorsNode);
|
||||
return csstreeWalkSkip;
|
||||
}
|
||||
if (cssNode.type === 'Declaration') {
|
||||
declarations.push({
|
||||
name: cssNode.property,
|
||||
value: csstree.generate(cssNode.value),
|
||||
important: cssNode.important === true,
|
||||
});
|
||||
return csstreeWalkSkip;
|
||||
}
|
||||
});
|
||||
if (selectors == null || selectorsSpecificity == null) {
|
||||
throw Error('assert');
|
||||
}
|
||||
return {
|
||||
dynamic,
|
||||
selectors,
|
||||
specificity: selectorsSpecificity,
|
||||
declarations,
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {(css: string, dynamic: boolean) => Array<StylesheetRule>}
|
||||
*/
|
||||
const parseStylesheet = (css, dynamic) => {
|
||||
/**
|
||||
* @type {Array<StylesheetRule>}
|
||||
*/
|
||||
const rules = [];
|
||||
const ast = csstree.parse(css, {
|
||||
parseValue: false,
|
||||
parseAtrulePrelude: false,
|
||||
});
|
||||
csstree.walk(ast, (cssNode) => {
|
||||
if (cssNode.type === 'Rule') {
|
||||
rules.push(parseRule(cssNode, dynamic || false));
|
||||
return csstreeWalkSkip;
|
||||
}
|
||||
if (cssNode.type === 'Atrule') {
|
||||
if (cssNode.name === 'keyframes') {
|
||||
return csstreeWalkSkip;
|
||||
}
|
||||
csstree.walk(cssNode, (ruleNode) => {
|
||||
if (ruleNode.type === 'Rule') {
|
||||
rules.push(parseRule(ruleNode, dynamic || true));
|
||||
return csstreeWalkSkip;
|
||||
}
|
||||
});
|
||||
return csstreeWalkSkip;
|
||||
}
|
||||
});
|
||||
return rules;
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {(css: string) => Array<StylesheetDeclaration>}
|
||||
*/
|
||||
const parseStyleDeclarations = (css) => {
|
||||
/**
|
||||
* @type {Array<StylesheetDeclaration>}
|
||||
*/
|
||||
const declarations = [];
|
||||
const ast = csstree.parse(css, {
|
||||
context: 'declarationList',
|
||||
parseValue: false,
|
||||
});
|
||||
csstree.walk(ast, (cssNode) => {
|
||||
if (cssNode.type === 'Declaration') {
|
||||
declarations.push({
|
||||
name: cssNode.property,
|
||||
value: csstree.generate(cssNode.value),
|
||||
important: cssNode.important === true,
|
||||
});
|
||||
}
|
||||
});
|
||||
return declarations;
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {(stylesheet: Stylesheet, node: XastElement) => ComputedStyles}
|
||||
*/
|
||||
const computeOwnStyle = (stylesheet, node) => {
|
||||
/**
|
||||
* @type {ComputedStyles}
|
||||
*/
|
||||
const computedStyle = {};
|
||||
const importantStyles = new Map();
|
||||
|
||||
// collect attributes
|
||||
for (const [name, value] of Object.entries(node.attributes)) {
|
||||
if (attrsGroups.presentation.includes(name)) {
|
||||
computedStyle[name] = { type: 'static', inherited: false, value };
|
||||
importantStyles.set(name, false);
|
||||
}
|
||||
}
|
||||
|
||||
// collect matching rules
|
||||
for (const { selectors, declarations, dynamic } of stylesheet.rules) {
|
||||
if (matches(node, selectors)) {
|
||||
for (const { name, value, important } of declarations) {
|
||||
const computed = computedStyle[name];
|
||||
if (computed && computed.type === 'dynamic') {
|
||||
continue;
|
||||
}
|
||||
if (dynamic) {
|
||||
computedStyle[name] = { type: 'dynamic', inherited: false };
|
||||
continue;
|
||||
}
|
||||
if (
|
||||
computed == null ||
|
||||
important === true ||
|
||||
importantStyles.get(name) === false
|
||||
) {
|
||||
computedStyle[name] = { type: 'static', inherited: false, value };
|
||||
importantStyles.set(name, important);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// collect inline styles
|
||||
const styleDeclarations =
|
||||
node.attributes.style == null
|
||||
? []
|
||||
: parseStyleDeclarations(node.attributes.style);
|
||||
for (const { name, value, important } of styleDeclarations) {
|
||||
const computed = computedStyle[name];
|
||||
if (computed && computed.type === 'dynamic') {
|
||||
continue;
|
||||
}
|
||||
if (
|
||||
computed == null ||
|
||||
important === true ||
|
||||
importantStyles.get(name) === false
|
||||
) {
|
||||
computedStyle[name] = { type: 'static', inherited: false, value };
|
||||
importantStyles.set(name, important);
|
||||
}
|
||||
}
|
||||
|
||||
return computedStyle;
|
||||
};
|
||||
|
||||
/**
|
||||
* Compares two selector specificities.
|
||||
* extracted from https://github.com/keeganstreet/specificity/blob/master/specificity.js#L211
|
||||
*
|
||||
* @type {(a: Specificity, b: Specificity) => number}
|
||||
*/
|
||||
const compareSpecificity = (a, b) => {
|
||||
for (var i = 0; i < 4; i += 1) {
|
||||
if (a[i] < b[i]) {
|
||||
return -1;
|
||||
} else if (a[i] > b[i]) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {(root: XastRoot) => Stylesheet}
|
||||
*/
|
||||
const collectStylesheet = (root) => {
|
||||
/**
|
||||
* @type {Array<StylesheetRule>}
|
||||
*/
|
||||
const rules = [];
|
||||
/**
|
||||
* @type {Map<XastElement, XastParent>}
|
||||
*/
|
||||
const parents = new Map();
|
||||
visit(root, {
|
||||
element: {
|
||||
enter: (node, parentNode) => {
|
||||
// store parents
|
||||
parents.set(node, parentNode);
|
||||
// find and parse all styles
|
||||
if (node.name === 'style') {
|
||||
const dynamic =
|
||||
node.attributes.media != null && node.attributes.media !== 'all';
|
||||
if (
|
||||
node.attributes.type == null ||
|
||||
node.attributes.type === '' ||
|
||||
node.attributes.type === 'text/css'
|
||||
) {
|
||||
const children = node.children;
|
||||
for (const child of children) {
|
||||
if (child.type === 'text' || child.type === 'cdata') {
|
||||
rules.push(...parseStylesheet(child.value, dynamic));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
// sort by selectors specificity
|
||||
stable.inplace(rules, (a, b) =>
|
||||
compareSpecificity(a.specificity, b.specificity)
|
||||
);
|
||||
return { rules, parents };
|
||||
};
|
||||
exports.collectStylesheet = collectStylesheet;
|
||||
|
||||
/**
|
||||
* @type {(stylesheet: Stylesheet, node: XastElement) => ComputedStyles}
|
||||
*/
|
||||
const computeStyle = (stylesheet, node) => {
|
||||
const { parents } = stylesheet;
|
||||
// collect inherited styles
|
||||
const computedStyles = computeOwnStyle(stylesheet, node);
|
||||
let parent = parents.get(node);
|
||||
while (parent != null && parent.type !== 'root') {
|
||||
const inheritedStyles = computeOwnStyle(stylesheet, parent);
|
||||
for (const [name, computed] of Object.entries(inheritedStyles)) {
|
||||
if (
|
||||
computedStyles[name] == null &&
|
||||
// ignore not inheritable styles
|
||||
inheritableAttrs.includes(name) === true &&
|
||||
presentationNonInheritableGroupAttrs.includes(name) === false
|
||||
) {
|
||||
computedStyles[name] = { ...computed, inherited: true };
|
||||
}
|
||||
}
|
||||
parent = parents.get(parent);
|
||||
}
|
||||
return computedStyles;
|
||||
};
|
||||
exports.computeStyle = computeStyle;
|
106
app_vue/node_modules/svgo/lib/svgo-node.js
generated
vendored
Normal file
106
app_vue/node_modules/svgo/lib/svgo-node.js
generated
vendored
Normal file
@ -0,0 +1,106 @@
|
||||
'use strict';
|
||||
|
||||
const os = require('os');
|
||||
const fs = require('fs');
|
||||
const { pathToFileURL } = require('url');
|
||||
const path = require('path');
|
||||
const {
|
||||
extendDefaultPlugins,
|
||||
optimize: optimizeAgnostic,
|
||||
createContentItem,
|
||||
} = require('./svgo.js');
|
||||
|
||||
exports.extendDefaultPlugins = extendDefaultPlugins;
|
||||
exports.createContentItem = createContentItem;
|
||||
|
||||
const importConfig = async (configFile) => {
|
||||
let config;
|
||||
// at the moment dynamic import may randomly fail with segfault
|
||||
// to workaround this for some users .cjs extension is loaded
|
||||
// exclusively with require
|
||||
if (configFile.endsWith('.cjs')) {
|
||||
config = require(configFile);
|
||||
} else {
|
||||
try {
|
||||
// dynamic import expects file url instead of path and may fail
|
||||
// when windows path is provided
|
||||
const { default: imported } = await import(pathToFileURL(configFile));
|
||||
config = imported;
|
||||
} catch (importError) {
|
||||
// TODO remove require in v3
|
||||
try {
|
||||
config = require(configFile);
|
||||
} catch (requireError) {
|
||||
// throw original error if es module is detected
|
||||
if (requireError.code === 'ERR_REQUIRE_ESM') {
|
||||
throw importError;
|
||||
} else {
|
||||
throw requireError;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (config == null || typeof config !== 'object' || Array.isArray(config)) {
|
||||
throw Error(`Invalid config file "${configFile}"`);
|
||||
}
|
||||
return config;
|
||||
};
|
||||
|
||||
const isFile = async (file) => {
|
||||
try {
|
||||
const stats = await fs.promises.stat(file);
|
||||
return stats.isFile();
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
const loadConfig = async (configFile, cwd = process.cwd()) => {
|
||||
if (configFile != null) {
|
||||
if (path.isAbsolute(configFile)) {
|
||||
return await importConfig(configFile);
|
||||
} else {
|
||||
return await importConfig(path.join(cwd, configFile));
|
||||
}
|
||||
}
|
||||
let dir = cwd;
|
||||
// eslint-disable-next-line no-constant-condition
|
||||
while (true) {
|
||||
const js = path.join(dir, 'svgo.config.js');
|
||||
if (await isFile(js)) {
|
||||
return await importConfig(js);
|
||||
}
|
||||
const mjs = path.join(dir, 'svgo.config.mjs');
|
||||
if (await isFile(mjs)) {
|
||||
return await importConfig(mjs);
|
||||
}
|
||||
const cjs = path.join(dir, 'svgo.config.cjs');
|
||||
if (await isFile(cjs)) {
|
||||
return await importConfig(cjs);
|
||||
}
|
||||
const parent = path.dirname(dir);
|
||||
if (dir === parent) {
|
||||
return null;
|
||||
}
|
||||
dir = parent;
|
||||
}
|
||||
};
|
||||
exports.loadConfig = loadConfig;
|
||||
|
||||
const optimize = (input, config) => {
|
||||
if (config == null) {
|
||||
config = {};
|
||||
}
|
||||
if (typeof config !== 'object') {
|
||||
throw Error('Config should be an object');
|
||||
}
|
||||
return optimizeAgnostic(input, {
|
||||
...config,
|
||||
js2svg: {
|
||||
// platform specific default for end of line
|
||||
eol: os.EOL === '\r\n' ? 'crlf' : 'lf',
|
||||
...config.js2svg,
|
||||
},
|
||||
});
|
||||
};
|
||||
exports.optimize = optimize;
|
83
app_vue/node_modules/svgo/lib/svgo.js
generated
vendored
Normal file
83
app_vue/node_modules/svgo/lib/svgo.js
generated
vendored
Normal file
@ -0,0 +1,83 @@
|
||||
'use strict';
|
||||
|
||||
const {
|
||||
defaultPlugins,
|
||||
resolvePluginConfig,
|
||||
extendDefaultPlugins,
|
||||
} = require('./svgo/config.js');
|
||||
const { parseSvg } = require('./parser.js');
|
||||
const { stringifySvg } = require('./stringifier.js');
|
||||
const { invokePlugins } = require('./svgo/plugins.js');
|
||||
const JSAPI = require('./svgo/jsAPI.js');
|
||||
const { encodeSVGDatauri } = require('./svgo/tools.js');
|
||||
|
||||
exports.extendDefaultPlugins = extendDefaultPlugins;
|
||||
|
||||
const optimize = (input, config) => {
|
||||
if (config == null) {
|
||||
config = {};
|
||||
}
|
||||
if (typeof config !== 'object') {
|
||||
throw Error('Config should be an object');
|
||||
}
|
||||
const maxPassCount = config.multipass ? 10 : 1;
|
||||
let prevResultSize = Number.POSITIVE_INFINITY;
|
||||
let svgjs = null;
|
||||
const info = {};
|
||||
if (config.path != null) {
|
||||
info.path = config.path;
|
||||
}
|
||||
for (let i = 0; i < maxPassCount; i += 1) {
|
||||
info.multipassCount = i;
|
||||
// TODO throw this error in v3
|
||||
try {
|
||||
svgjs = parseSvg(input, config.path);
|
||||
} catch (error) {
|
||||
return { error: error.toString(), modernError: error };
|
||||
}
|
||||
if (svgjs.error != null) {
|
||||
if (config.path != null) {
|
||||
svgjs.path = config.path;
|
||||
}
|
||||
return svgjs;
|
||||
}
|
||||
const plugins = config.plugins || defaultPlugins;
|
||||
if (Array.isArray(plugins) === false) {
|
||||
throw Error(
|
||||
"Invalid plugins list. Provided 'plugins' in config should be an array."
|
||||
);
|
||||
}
|
||||
const resolvedPlugins = plugins.map(resolvePluginConfig);
|
||||
const globalOverrides = {};
|
||||
if (config.floatPrecision != null) {
|
||||
globalOverrides.floatPrecision = config.floatPrecision;
|
||||
}
|
||||
svgjs = invokePlugins(svgjs, info, resolvedPlugins, null, globalOverrides);
|
||||
svgjs = stringifySvg(svgjs, config.js2svg);
|
||||
if (svgjs.data.length < prevResultSize) {
|
||||
input = svgjs.data;
|
||||
prevResultSize = svgjs.data.length;
|
||||
} else {
|
||||
if (config.datauri) {
|
||||
svgjs.data = encodeSVGDatauri(svgjs.data, config.datauri);
|
||||
}
|
||||
if (config.path != null) {
|
||||
svgjs.path = config.path;
|
||||
}
|
||||
return svgjs;
|
||||
}
|
||||
}
|
||||
return svgjs;
|
||||
};
|
||||
exports.optimize = optimize;
|
||||
|
||||
/**
|
||||
* The factory that creates a content item with the helper methods.
|
||||
*
|
||||
* @param {Object} data which is passed to jsAPI constructor
|
||||
* @returns {JSAPI} content item
|
||||
*/
|
||||
const createContentItem = (data) => {
|
||||
return new JSAPI(data);
|
||||
};
|
||||
exports.createContentItem = createContentItem;
|
517
app_vue/node_modules/svgo/lib/svgo/coa.js
generated
vendored
Normal file
517
app_vue/node_modules/svgo/lib/svgo/coa.js
generated
vendored
Normal 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
app_vue/node_modules/svgo/lib/svgo/config.js
generated
vendored
Normal file
138
app_vue/node_modules/svgo/lib/svgo/config.js
generated
vendored
Normal 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
app_vue/node_modules/svgo/lib/svgo/css-class-list.js
generated
vendored
Normal file
72
app_vue/node_modules/svgo/lib/svgo/css-class-list.js
generated
vendored
Normal 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
app_vue/node_modules/svgo/lib/svgo/css-select-adapter.d.ts
generated
vendored
Normal file
2
app_vue/node_modules/svgo/lib/svgo/css-select-adapter.d.ts
generated
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
declare let obj: any;
|
||||
export = obj;
|
120
app_vue/node_modules/svgo/lib/svgo/css-select-adapter.js
generated
vendored
Normal file
120
app_vue/node_modules/svgo/lib/svgo/css-select-adapter.js
generated
vendored
Normal 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
app_vue/node_modules/svgo/lib/svgo/css-style-declaration.js
generated
vendored
Normal file
232
app_vue/node_modules/svgo/lib/svgo/css-style-declaration.js
generated
vendored
Normal 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
app_vue/node_modules/svgo/lib/svgo/jsAPI.d.ts
generated
vendored
Normal file
2
app_vue/node_modules/svgo/lib/svgo/jsAPI.d.ts
generated
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
declare let obj: any;
|
||||
export = obj;
|
443
app_vue/node_modules/svgo/lib/svgo/jsAPI.js
generated
vendored
Normal file
443
app_vue/node_modules/svgo/lib/svgo/jsAPI.js
generated
vendored
Normal 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
app_vue/node_modules/svgo/lib/svgo/plugins.js
generated
vendored
Normal file
109
app_vue/node_modules/svgo/lib/svgo/plugins.js
generated
vendored
Normal 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
app_vue/node_modules/svgo/lib/svgo/tools.js
generated
vendored
Normal file
137
app_vue/node_modules/svgo/lib/svgo/tools.js
generated
vendored
Normal 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;
|
172
app_vue/node_modules/svgo/lib/types.ts
generated
vendored
Normal file
172
app_vue/node_modules/svgo/lib/types.ts
generated
vendored
Normal file
@ -0,0 +1,172 @@
|
||||
export type XastDoctype = {
|
||||
type: 'doctype';
|
||||
name: string;
|
||||
data: {
|
||||
doctype: string;
|
||||
};
|
||||
};
|
||||
|
||||
export type XastInstruction = {
|
||||
type: 'instruction';
|
||||
name: string;
|
||||
value: string;
|
||||
};
|
||||
|
||||
export type XastComment = {
|
||||
type: 'comment';
|
||||
value: string;
|
||||
};
|
||||
|
||||
export type XastCdata = {
|
||||
type: 'cdata';
|
||||
value: string;
|
||||
};
|
||||
|
||||
export type XastText = {
|
||||
type: 'text';
|
||||
value: string;
|
||||
};
|
||||
|
||||
export type XastElement = {
|
||||
type: 'element';
|
||||
name: string;
|
||||
attributes: Record<string, string>;
|
||||
children: Array<XastChild>;
|
||||
};
|
||||
|
||||
export type XastChild =
|
||||
| XastDoctype
|
||||
| XastInstruction
|
||||
| XastComment
|
||||
| XastCdata
|
||||
| XastText
|
||||
| XastElement;
|
||||
|
||||
export type XastRoot = {
|
||||
type: 'root';
|
||||
children: Array<XastChild>;
|
||||
};
|
||||
|
||||
export type XastParent = XastRoot | XastElement;
|
||||
|
||||
export type XastNode = XastRoot | XastChild;
|
||||
|
||||
export type StringifyOptions = {
|
||||
doctypeStart?: string;
|
||||
doctypeEnd?: string;
|
||||
procInstStart?: string;
|
||||
procInstEnd?: string;
|
||||
tagOpenStart?: string;
|
||||
tagOpenEnd?: string;
|
||||
tagCloseStart?: string;
|
||||
tagCloseEnd?: string;
|
||||
tagShortStart?: string;
|
||||
tagShortEnd?: string;
|
||||
attrStart?: string;
|
||||
attrEnd?: string;
|
||||
commentStart?: string;
|
||||
commentEnd?: string;
|
||||
cdataStart?: string;
|
||||
cdataEnd?: string;
|
||||
textStart?: string;
|
||||
textEnd?: string;
|
||||
indent?: number | string;
|
||||
regEntities?: RegExp;
|
||||
regValEntities?: RegExp;
|
||||
encodeEntity?: (char: string) => string;
|
||||
pretty?: boolean;
|
||||
useShortTags?: boolean;
|
||||
eol?: 'lf' | 'crlf';
|
||||
finalNewline?: boolean;
|
||||
};
|
||||
|
||||
type VisitorNode<Node> = {
|
||||
enter?: (node: Node, parentNode: XastParent) => void | symbol;
|
||||
exit?: (node: Node, parentNode: XastParent) => void;
|
||||
};
|
||||
|
||||
type VisitorRoot = {
|
||||
enter?: (node: XastRoot, parentNode: null) => void;
|
||||
exit?: (node: XastRoot, parentNode: null) => void;
|
||||
};
|
||||
|
||||
export type Visitor = {
|
||||
doctype?: VisitorNode<XastDoctype>;
|
||||
instruction?: VisitorNode<XastInstruction>;
|
||||
comment?: VisitorNode<XastComment>;
|
||||
cdata?: VisitorNode<XastCdata>;
|
||||
text?: VisitorNode<XastText>;
|
||||
element?: VisitorNode<XastElement>;
|
||||
root?: VisitorRoot;
|
||||
};
|
||||
|
||||
export type PluginInfo = {
|
||||
path?: string;
|
||||
multipassCount: number;
|
||||
};
|
||||
|
||||
export type Plugin<Params> = (
|
||||
root: XastRoot,
|
||||
params: Params,
|
||||
info: PluginInfo
|
||||
) => null | Visitor;
|
||||
|
||||
export type Specificity = [number, number, number, number];
|
||||
|
||||
export type StylesheetDeclaration = {
|
||||
name: string;
|
||||
value: string;
|
||||
important: boolean;
|
||||
};
|
||||
|
||||
export type StylesheetRule = {
|
||||
dynamic: boolean;
|
||||
selectors: string;
|
||||
specificity: Specificity;
|
||||
declarations: Array<StylesheetDeclaration>;
|
||||
};
|
||||
|
||||
export type Stylesheet = {
|
||||
rules: Array<StylesheetRule>;
|
||||
parents: Map<XastElement, XastParent>;
|
||||
};
|
||||
|
||||
type StaticStyle = {
|
||||
type: 'static';
|
||||
inherited: boolean;
|
||||
value: string;
|
||||
};
|
||||
|
||||
type DynamicStyle = {
|
||||
type: 'dynamic';
|
||||
inherited: boolean;
|
||||
};
|
||||
|
||||
export type ComputedStyles = Record<string, StaticStyle | DynamicStyle>;
|
||||
|
||||
export type PathDataCommand =
|
||||
| 'M'
|
||||
| 'm'
|
||||
| 'Z'
|
||||
| 'z'
|
||||
| 'L'
|
||||
| 'l'
|
||||
| 'H'
|
||||
| 'h'
|
||||
| 'V'
|
||||
| 'v'
|
||||
| 'C'
|
||||
| 'c'
|
||||
| 'S'
|
||||
| 's'
|
||||
| 'Q'
|
||||
| 'q'
|
||||
| 'T'
|
||||
| 't'
|
||||
| 'A'
|
||||
| 'a';
|
||||
|
||||
export type PathDataItem = {
|
||||
command: PathDataCommand;
|
||||
args: Array<number>;
|
||||
};
|
102
app_vue/node_modules/svgo/lib/xast.js
generated
vendored
Normal file
102
app_vue/node_modules/svgo/lib/xast.js
generated
vendored
Normal file
@ -0,0 +1,102 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @typedef {import('./types').XastNode} XastNode
|
||||
* @typedef {import('./types').XastChild} XastChild
|
||||
* @typedef {import('./types').XastParent} XastParent
|
||||
* @typedef {import('./types').Visitor} Visitor
|
||||
*/
|
||||
|
||||
const { selectAll, selectOne, is } = require('css-select');
|
||||
const xastAdaptor = require('./svgo/css-select-adapter.js');
|
||||
|
||||
const cssSelectOptions = {
|
||||
xmlMode: true,
|
||||
adapter: xastAdaptor,
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {(node: XastNode, selector: string) => Array<XastChild>}
|
||||
*/
|
||||
const querySelectorAll = (node, selector) => {
|
||||
return selectAll(selector, node, cssSelectOptions);
|
||||
};
|
||||
exports.querySelectorAll = querySelectorAll;
|
||||
|
||||
/**
|
||||
* @type {(node: XastNode, selector: string) => null | XastChild}
|
||||
*/
|
||||
const querySelector = (node, selector) => {
|
||||
return selectOne(selector, node, cssSelectOptions);
|
||||
};
|
||||
exports.querySelector = querySelector;
|
||||
|
||||
/**
|
||||
* @type {(node: XastChild, selector: string) => boolean}
|
||||
*/
|
||||
const matches = (node, selector) => {
|
||||
return is(node, selector, cssSelectOptions);
|
||||
};
|
||||
exports.matches = matches;
|
||||
|
||||
/**
|
||||
* @type {(node: XastChild, name: string) => null | XastChild}
|
||||
*/
|
||||
const closestByName = (node, name) => {
|
||||
let currentNode = node;
|
||||
while (currentNode) {
|
||||
if (currentNode.type === 'element' && currentNode.name === name) {
|
||||
return currentNode;
|
||||
}
|
||||
// @ts-ignore parentNode is hidden from public usage
|
||||
currentNode = currentNode.parentNode;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
exports.closestByName = closestByName;
|
||||
|
||||
const visitSkip = Symbol();
|
||||
exports.visitSkip = visitSkip;
|
||||
|
||||
/**
|
||||
* @type {(node: XastNode, visitor: Visitor, parentNode?: any) => void}
|
||||
*/
|
||||
const visit = (node, visitor, parentNode) => {
|
||||
const callbacks = visitor[node.type];
|
||||
if (callbacks && callbacks.enter) {
|
||||
// @ts-ignore hard to infer
|
||||
const symbol = callbacks.enter(node, parentNode);
|
||||
if (symbol === visitSkip) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
// visit root children
|
||||
if (node.type === 'root') {
|
||||
// copy children array to not loose cursor when children is spliced
|
||||
for (const child of node.children) {
|
||||
visit(child, visitor, node);
|
||||
}
|
||||
}
|
||||
// visit element children if still attached to parent
|
||||
if (node.type === 'element') {
|
||||
if (parentNode.children.includes(node)) {
|
||||
for (const child of node.children) {
|
||||
visit(child, visitor, node);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (callbacks && callbacks.exit) {
|
||||
// @ts-ignore hard to infer
|
||||
callbacks.exit(node, parentNode);
|
||||
}
|
||||
};
|
||||
exports.visit = visit;
|
||||
|
||||
/**
|
||||
* @type {(node: XastChild, parentNode: XastParent) => void}
|
||||
*/
|
||||
const detachNodeFromParent = (node, parentNode) => {
|
||||
// avoid splice to not break for loops
|
||||
parentNode.children = parentNode.children.filter((child) => child !== node);
|
||||
};
|
||||
exports.detachNodeFromParent = detachNodeFromParent;
|
Reference in New Issue
Block a user