penambahan web socket
This commit is contained in:
117
examples/nuxt3-websocket-client/node_modules/svgo/lib/builtin.js
generated
vendored
Normal file
117
examples/nuxt3-websocket-client/node_modules/svgo/lib/builtin.js
generated
vendored
Normal file
@@ -0,0 +1,117 @@
|
||||
import presetDefault from '../plugins/preset-default.js';
|
||||
import * as addAttributesToSVGElement from '../plugins/addAttributesToSVGElement.js';
|
||||
import * as addClassesToSVGElement from '../plugins/addClassesToSVGElement.js';
|
||||
import * as cleanupAttrs from '../plugins/cleanupAttrs.js';
|
||||
import * as cleanupEnableBackground from '../plugins/cleanupEnableBackground.js';
|
||||
import * as cleanupIds from '../plugins/cleanupIds.js';
|
||||
import * as cleanupListOfValues from '../plugins/cleanupListOfValues.js';
|
||||
import * as cleanupNumericValues from '../plugins/cleanupNumericValues.js';
|
||||
import * as collapseGroups from '../plugins/collapseGroups.js';
|
||||
import * as convertColors from '../plugins/convertColors.js';
|
||||
import * as convertEllipseToCircle from '../plugins/convertEllipseToCircle.js';
|
||||
import * as convertOneStopGradients from '../plugins/convertOneStopGradients.js';
|
||||
import * as convertPathData from '../plugins/convertPathData.js';
|
||||
import * as convertShapeToPath from '../plugins/convertShapeToPath.js';
|
||||
import * as convertStyleToAttrs from '../plugins/convertStyleToAttrs.js';
|
||||
import * as convertTransform from '../plugins/convertTransform.js';
|
||||
import * as mergeStyles from '../plugins/mergeStyles.js';
|
||||
import * as inlineStyles from '../plugins/inlineStyles.js';
|
||||
import * as mergePaths from '../plugins/mergePaths.js';
|
||||
import * as minifyStyles from '../plugins/minifyStyles.js';
|
||||
import * as moveElemsAttrsToGroup from '../plugins/moveElemsAttrsToGroup.js';
|
||||
import * as moveGroupAttrsToElems from '../plugins/moveGroupAttrsToElems.js';
|
||||
import * as prefixIds from '../plugins/prefixIds.js';
|
||||
import * as removeAttributesBySelector from '../plugins/removeAttributesBySelector.js';
|
||||
import * as removeAttrs from '../plugins/removeAttrs.js';
|
||||
import * as removeComments from '../plugins/removeComments.js';
|
||||
import * as removeDeprecatedAttrs from '../plugins/removeDeprecatedAttrs.js';
|
||||
import * as removeDesc from '../plugins/removeDesc.js';
|
||||
import * as removeDimensions from '../plugins/removeDimensions.js';
|
||||
import * as removeDoctype from '../plugins/removeDoctype.js';
|
||||
import * as removeEditorsNSData from '../plugins/removeEditorsNSData.js';
|
||||
import * as removeElementsByAttr from '../plugins/removeElementsByAttr.js';
|
||||
import * as removeEmptyAttrs from '../plugins/removeEmptyAttrs.js';
|
||||
import * as removeEmptyContainers from '../plugins/removeEmptyContainers.js';
|
||||
import * as removeEmptyText from '../plugins/removeEmptyText.js';
|
||||
import * as removeHiddenElems from '../plugins/removeHiddenElems.js';
|
||||
import * as removeMetadata from '../plugins/removeMetadata.js';
|
||||
import * as removeNonInheritableGroupAttrs from '../plugins/removeNonInheritableGroupAttrs.js';
|
||||
import * as removeOffCanvasPaths from '../plugins/removeOffCanvasPaths.js';
|
||||
import * as removeRasterImages from '../plugins/removeRasterImages.js';
|
||||
import * as removeScripts from '../plugins/removeScripts.js';
|
||||
import * as removeStyleElement from '../plugins/removeStyleElement.js';
|
||||
import * as removeTitle from '../plugins/removeTitle.js';
|
||||
import * as removeUnknownsAndDefaults from '../plugins/removeUnknownsAndDefaults.js';
|
||||
import * as removeUnusedNS from '../plugins/removeUnusedNS.js';
|
||||
import * as removeUselessDefs from '../plugins/removeUselessDefs.js';
|
||||
import * as removeUselessStrokeAndFill from '../plugins/removeUselessStrokeAndFill.js';
|
||||
import * as removeViewBox from '../plugins/removeViewBox.js';
|
||||
import * as removeXlink from '../plugins/removeXlink.js';
|
||||
import * as removeXMLNS from '../plugins/removeXMLNS.js';
|
||||
import * as removeXMLProcInst from '../plugins/removeXMLProcInst.js';
|
||||
import * as reusePaths from '../plugins/reusePaths.js';
|
||||
import * as sortAttrs from '../plugins/sortAttrs.js';
|
||||
import * as sortDefsChildren from '../plugins/sortDefsChildren.js';
|
||||
|
||||
/**
|
||||
* Plugins that are bundled with SVGO. This includes plugin presets, and plugins
|
||||
* that are not enabled by default.
|
||||
*
|
||||
* @type {ReadonlyArray<{[Name in keyof import('./types.js').PluginsParams]: import('./types.js').BuiltinPluginOrPreset<Name, import('./types.js').PluginsParams[Name]>;}[keyof import('./types.js').PluginsParams]>}
|
||||
*/
|
||||
export const builtinPlugins = Object.freeze([
|
||||
presetDefault,
|
||||
addAttributesToSVGElement,
|
||||
addClassesToSVGElement,
|
||||
cleanupAttrs,
|
||||
cleanupEnableBackground,
|
||||
cleanupIds,
|
||||
cleanupListOfValues,
|
||||
cleanupNumericValues,
|
||||
collapseGroups,
|
||||
convertColors,
|
||||
convertEllipseToCircle,
|
||||
convertOneStopGradients,
|
||||
convertPathData,
|
||||
convertShapeToPath,
|
||||
convertStyleToAttrs,
|
||||
convertTransform,
|
||||
inlineStyles,
|
||||
mergePaths,
|
||||
mergeStyles,
|
||||
minifyStyles,
|
||||
moveElemsAttrsToGroup,
|
||||
moveGroupAttrsToElems,
|
||||
prefixIds,
|
||||
removeAttributesBySelector,
|
||||
removeAttrs,
|
||||
removeComments,
|
||||
removeDeprecatedAttrs,
|
||||
removeDesc,
|
||||
removeDimensions,
|
||||
removeDoctype,
|
||||
removeEditorsNSData,
|
||||
removeElementsByAttr,
|
||||
removeEmptyAttrs,
|
||||
removeEmptyContainers,
|
||||
removeEmptyText,
|
||||
removeHiddenElems,
|
||||
removeMetadata,
|
||||
removeNonInheritableGroupAttrs,
|
||||
removeOffCanvasPaths,
|
||||
removeRasterImages,
|
||||
removeScripts,
|
||||
removeStyleElement,
|
||||
removeTitle,
|
||||
removeUnknownsAndDefaults,
|
||||
removeUnusedNS,
|
||||
removeUselessDefs,
|
||||
removeUselessStrokeAndFill,
|
||||
removeViewBox,
|
||||
removeXlink,
|
||||
removeXMLNS,
|
||||
removeXMLProcInst,
|
||||
reusePaths,
|
||||
sortAttrs,
|
||||
sortDefsChildren,
|
||||
]);
|
||||
208
examples/nuxt3-websocket-client/node_modules/svgo/lib/parser.js
generated
vendored
Normal file
208
examples/nuxt3-websocket-client/node_modules/svgo/lib/parser.js
generated
vendored
Normal file
@@ -0,0 +1,208 @@
|
||||
import SAX from 'sax';
|
||||
import { textElems } from '../plugins/_collections.js';
|
||||
|
||||
export class SvgoParserError extends Error {
|
||||
/**
|
||||
* @param {string} message
|
||||
* @param {number} line
|
||||
* @param {number} column
|
||||
* @param {string} source
|
||||
* @param {string=} file
|
||||
*/
|
||||
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,
|
||||
unparsedEntities: true,
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert SVG (XML) string to SVG-as-JS object.
|
||||
*
|
||||
* @param {string} data
|
||||
* @param {string=} from
|
||||
* @returns {import('./types.js').XastRoot}
|
||||
*/
|
||||
export const parseSvg = (data, from) => {
|
||||
const sax = SAX.parser(config.strict, config);
|
||||
/** @type {import('./types.js').XastRoot} */
|
||||
const root = { type: 'root', children: [] };
|
||||
/** @type {import('./types.js').XastParent} */
|
||||
let current = root;
|
||||
/** @type {import('./types.js').XastParent[]} */
|
||||
const stack = [root];
|
||||
|
||||
/**
|
||||
* @param {import('./types.js').XastChild} node
|
||||
*/
|
||||
const pushToContent = (node) => {
|
||||
current.children.push(node);
|
||||
};
|
||||
|
||||
sax.ondoctype = (doctype) => {
|
||||
/** @type {import('./types.js').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);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
sax.onprocessinginstruction = (data) => {
|
||||
/** @type {import('./types.js').XastInstruction} */
|
||||
const node = {
|
||||
type: 'instruction',
|
||||
name: data.name,
|
||||
value: data.body,
|
||||
};
|
||||
pushToContent(node);
|
||||
};
|
||||
|
||||
sax.oncomment = (comment) => {
|
||||
/** @type {import('./types.js').XastComment} */
|
||||
const node = {
|
||||
type: 'comment',
|
||||
value: comment.trim(),
|
||||
};
|
||||
pushToContent(node);
|
||||
};
|
||||
|
||||
sax.oncdata = (cdata) => {
|
||||
/** @type {import('./types.js').XastCdata} */
|
||||
const node = {
|
||||
type: 'cdata',
|
||||
value: cdata,
|
||||
};
|
||||
pushToContent(node);
|
||||
};
|
||||
|
||||
sax.onopentag = (data) => {
|
||||
/** @type {import('./types.js').XastElement} */
|
||||
const element = {
|
||||
type: 'element',
|
||||
name: data.name,
|
||||
attributes: {},
|
||||
children: [],
|
||||
};
|
||||
for (const [name, attr] of Object.entries(data.attributes)) {
|
||||
element.attributes[name] = attr.value;
|
||||
}
|
||||
pushToContent(element);
|
||||
current = element;
|
||||
stack.push(element);
|
||||
};
|
||||
|
||||
sax.ontext = (text) => {
|
||||
if (current.type === 'element') {
|
||||
// prevent trimming of meaningful whitespace inside textual tags
|
||||
if (textElems.has(current.name)) {
|
||||
/** @type {import('./types.js').XastText} */
|
||||
const node = {
|
||||
type: 'text',
|
||||
value: text,
|
||||
};
|
||||
pushToContent(node);
|
||||
} else {
|
||||
const value = text.trim();
|
||||
|
||||
if (value !== '') {
|
||||
/** @type {import('./types.js').XastText} */
|
||||
const node = {
|
||||
type: 'text',
|
||||
value,
|
||||
};
|
||||
pushToContent(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
sax.onclosetag = () => {
|
||||
stack.pop();
|
||||
current = stack[stack.length - 1];
|
||||
};
|
||||
|
||||
sax.onerror = (e) => {
|
||||
const reason = e.message.split('\n')[0];
|
||||
const error = new SvgoParserError(
|
||||
reason,
|
||||
sax.line + 1,
|
||||
sax.column,
|
||||
data,
|
||||
from,
|
||||
);
|
||||
if (e.message.indexOf('Unexpected end') === -1) {
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
sax.write(data).close();
|
||||
return root;
|
||||
};
|
||||
362
examples/nuxt3-websocket-client/node_modules/svgo/lib/path.js
generated
vendored
Normal file
362
examples/nuxt3-websocket-client/node_modules/svgo/lib/path.js
generated
vendored
Normal file
@@ -0,0 +1,362 @@
|
||||
/**
|
||||
* @fileoverview Based on https://www.w3.org/TR/SVG11/paths.html#PathDataBNF.
|
||||
*/
|
||||
|
||||
import { removeLeadingZero, toFixed } from './svgo/tools.js';
|
||||
|
||||
/**
|
||||
* @typedef {'none' | 'sign' | 'whole' | 'decimal_point' | 'decimal' | 'e' | 'exponent_sign' | 'exponent'} ReadNumberState
|
||||
*
|
||||
* @typedef StringifyPathDataOptions
|
||||
* @property {ReadonlyArray<import('./types.js').PathDataItem>} pathData
|
||||
* @property {number=} precision
|
||||
* @property {boolean=} disableSpaceAfterFlags
|
||||
*/
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} c
|
||||
* @returns {c is import('./types.js').PathDataCommand}
|
||||
*/
|
||||
const isCommand = (c) => {
|
||||
return c in argsCountPerCommand;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} c
|
||||
* @returns {boolean}
|
||||
*/
|
||||
const isWhiteSpace = (c) => {
|
||||
return c === ' ' || c === '\t' || c === '\r' || c === '\n';
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} c
|
||||
* @returns {boolean}
|
||||
*/
|
||||
const isDigit = (c) => {
|
||||
const codePoint = c.codePointAt(0);
|
||||
if (codePoint == null) {
|
||||
return false;
|
||||
}
|
||||
return 48 <= codePoint && codePoint <= 57;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} string
|
||||
* @param {number} cursor
|
||||
* @returns {[number, ?number]}
|
||||
*/
|
||||
const readNumber = (string, cursor) => {
|
||||
let i = cursor;
|
||||
let value = '';
|
||||
/** @type {ReadNumberState} */
|
||||
let state = '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];
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} string
|
||||
* @returns {import('./types.js').PathDataItem[]}
|
||||
*/
|
||||
export const parsePathData = (string) => {
|
||||
/** @type {import('./types.js').PathDataItem[]} */
|
||||
const pathData = [];
|
||||
/** @type {?import('./types.js').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 (isWhiteSpace(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 if (args.length !== 0) {
|
||||
// stop if previous command arguments are not flushed
|
||||
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 treated as implicit lineto commands
|
||||
if (command === 'M') {
|
||||
command = 'L';
|
||||
}
|
||||
if (command === 'm') {
|
||||
command = 'l';
|
||||
}
|
||||
args = [];
|
||||
}
|
||||
}
|
||||
return pathData;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {number} number
|
||||
* @param {number=} precision
|
||||
* @returns {{ roundedStr: string, rounded: number }}
|
||||
*/
|
||||
const roundAndStringify = (number, precision) => {
|
||||
if (precision != null) {
|
||||
number = toFixed(number, precision);
|
||||
}
|
||||
|
||||
return {
|
||||
roundedStr: removeLeadingZero(number),
|
||||
rounded: number,
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Elliptical arc large-arc and sweep flags are rendered with spaces
|
||||
* because many non-browser environments are not able to parse such paths
|
||||
*
|
||||
* @param {string} command
|
||||
* @param {ReadonlyArray<number>} args
|
||||
* @param {number=} precision
|
||||
* @param {boolean=} disableSpaceAfterFlags
|
||||
* @returns {string}
|
||||
*/
|
||||
const stringifyArgs = (command, args, precision, disableSpaceAfterFlags) => {
|
||||
let result = '';
|
||||
let previous;
|
||||
|
||||
for (let i = 0; i < args.length; i++) {
|
||||
const { roundedStr, rounded } = roundAndStringify(args[i], precision);
|
||||
if (
|
||||
disableSpaceAfterFlags &&
|
||||
(command === 'A' || command === 'a') &&
|
||||
// consider combined arcs
|
||||
(i % 7 === 4 || i % 7 === 5)
|
||||
) {
|
||||
result += roundedStr;
|
||||
} else if (i === 0 || rounded < 0) {
|
||||
// avoid space before first and negative numbers
|
||||
result += roundedStr;
|
||||
} else if (!Number.isInteger(previous) && !isDigit(roundedStr[0])) {
|
||||
// remove space before decimal with zero whole
|
||||
// only when previous number is also decimal
|
||||
result += roundedStr;
|
||||
} else {
|
||||
result += ` ${roundedStr}`;
|
||||
}
|
||||
previous = rounded;
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {StringifyPathDataOptions} options
|
||||
* @returns {string}
|
||||
*/
|
||||
export const stringifyPathData = ({
|
||||
pathData,
|
||||
precision,
|
||||
disableSpaceAfterFlags,
|
||||
}) => {
|
||||
if (pathData.length === 1) {
|
||||
const { command, args } = pathData[0];
|
||||
return (
|
||||
command + stringifyArgs(command, args, precision, disableSpaceAfterFlags)
|
||||
);
|
||||
}
|
||||
|
||||
let result = '';
|
||||
let prev = { ...pathData[0] };
|
||||
|
||||
// match leading moveto with following lineto
|
||||
if (pathData[1].command === 'L') {
|
||||
prev.command = 'M';
|
||||
} else if (pathData[1].command === 'l') {
|
||||
prev.command = 'm';
|
||||
}
|
||||
|
||||
for (let i = 1; i < pathData.length; i++) {
|
||||
const { command, args } = pathData[i];
|
||||
if (
|
||||
(prev.command === command &&
|
||||
prev.command !== 'M' &&
|
||||
prev.command !== 'm') ||
|
||||
// combine matching moveto and lineto sequences
|
||||
(prev.command === 'M' && command === 'L') ||
|
||||
(prev.command === 'm' && command === 'l')
|
||||
) {
|
||||
prev.args = [...prev.args, ...args];
|
||||
if (i === pathData.length - 1) {
|
||||
result +=
|
||||
prev.command +
|
||||
stringifyArgs(
|
||||
prev.command,
|
||||
prev.args,
|
||||
precision,
|
||||
disableSpaceAfterFlags,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
result +=
|
||||
prev.command +
|
||||
stringifyArgs(
|
||||
prev.command,
|
||||
prev.args,
|
||||
precision,
|
||||
disableSpaceAfterFlags,
|
||||
);
|
||||
|
||||
if (i === pathData.length - 1) {
|
||||
result +=
|
||||
command +
|
||||
stringifyArgs(command, args, precision, disableSpaceAfterFlags);
|
||||
} else {
|
||||
prev = { command, args };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
298
examples/nuxt3-websocket-client/node_modules/svgo/lib/stringifier.js
generated
vendored
Normal file
298
examples/nuxt3-websocket-client/node_modules/svgo/lib/stringifier.js
generated
vendored
Normal file
@@ -0,0 +1,298 @@
|
||||
import { textElems } from '../plugins/_collections.js';
|
||||
|
||||
/**
|
||||
* @typedef {Required<import('./types.js').StringifyOptions>} Options
|
||||
*
|
||||
* @typedef State
|
||||
* @property {string} indent
|
||||
* @property {?import('./types.js').XastElement} textContext
|
||||
* @property {number} indentLevel
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {string} char
|
||||
* @returns {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,
|
||||
pretty: false,
|
||||
useShortTags: true,
|
||||
eol: 'lf',
|
||||
finalNewline: false,
|
||||
};
|
||||
|
||||
/** @type {Record<string, string>} */
|
||||
const entities = {
|
||||
'&': '&',
|
||||
"'": ''',
|
||||
'"': '"',
|
||||
'>': '>',
|
||||
'<': '<',
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts XAST to SVG string.
|
||||
*
|
||||
* @param {import('./types.js').XastRoot} data
|
||||
* @param {import('./types.js').StringifyOptions=} userOptions
|
||||
* @returns {string}
|
||||
*/
|
||||
export 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 = {
|
||||
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.endsWith('\n')) {
|
||||
svg += eol;
|
||||
}
|
||||
return svg;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {import('./types.js').XastParent} data
|
||||
* @param {Options} config
|
||||
* @param {State} state
|
||||
* @returns {string}
|
||||
*/
|
||||
const stringifyNode = (data, config, state) => {
|
||||
let svg = '';
|
||||
state.indentLevel++;
|
||||
for (const item of data.children) {
|
||||
switch (item.type) {
|
||||
case 'element':
|
||||
svg += stringifyElement(item, config, state);
|
||||
break;
|
||||
case 'text':
|
||||
svg += stringifyText(item, config, state);
|
||||
break;
|
||||
case 'doctype':
|
||||
svg += stringifyDoctype(item, config);
|
||||
break;
|
||||
case 'instruction':
|
||||
svg += stringifyInstruction(item, config);
|
||||
break;
|
||||
case 'comment':
|
||||
svg += stringifyComment(item, config);
|
||||
break;
|
||||
case 'cdata':
|
||||
svg += stringifyCdata(item, config, state);
|
||||
}
|
||||
}
|
||||
state.indentLevel--;
|
||||
return svg;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create indent string in accordance with the current node level.
|
||||
*
|
||||
* @param {Options} config
|
||||
* @param {State} state
|
||||
* @returns {string}
|
||||
*/
|
||||
const createIndent = (config, state) => {
|
||||
let indent = '';
|
||||
if (config.pretty && state.textContext == null) {
|
||||
indent = state.indent.repeat(state.indentLevel - 1);
|
||||
}
|
||||
return indent;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {import('./types.js').XastDoctype} node
|
||||
* @param {Options} config
|
||||
* @returns {string}
|
||||
*/
|
||||
const stringifyDoctype = (node, config) => {
|
||||
return config.doctypeStart + node.data.doctype + config.doctypeEnd;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {import('./types.js').XastInstruction} node
|
||||
* @param {Options} config
|
||||
* @returns {string}
|
||||
*/
|
||||
const stringifyInstruction = (node, config) => {
|
||||
return (
|
||||
config.procInstStart + node.name + ' ' + node.value + config.procInstEnd
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {import('./types.js').XastComment} node
|
||||
* @param {Options} config
|
||||
* @returns {string}
|
||||
*/
|
||||
const stringifyComment = (node, config) => {
|
||||
return config.commentStart + node.value + config.commentEnd;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {import('./types.js').XastCdata} node
|
||||
* @param {Options} config
|
||||
* @param {State} state
|
||||
* @returns {string}
|
||||
*/
|
||||
const stringifyCdata = (node, config, state) => {
|
||||
return (
|
||||
createIndent(config, state) +
|
||||
config.cdataStart +
|
||||
node.value +
|
||||
config.cdataEnd
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {import('./types.js').XastElement} node
|
||||
* @param {Options} config
|
||||
* @param {State} state
|
||||
* @returns {string}
|
||||
*/
|
||||
const stringifyElement = (node, config, state) => {
|
||||
// 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
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
createIndent(config, state) +
|
||||
config.tagShortStart +
|
||||
node.name +
|
||||
stringifyAttributes(node, config) +
|
||||
config.tagOpenEnd +
|
||||
config.tagCloseStart +
|
||||
node.name +
|
||||
config.tagCloseEnd
|
||||
);
|
||||
}
|
||||
|
||||
// non-empty element
|
||||
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.has(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
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {import('./types.js').XastElement} node
|
||||
* @param {Options} config
|
||||
* @returns {string}
|
||||
*/
|
||||
const stringifyAttributes = (node, config) => {
|
||||
let attrs = '';
|
||||
for (const [name, value] of Object.entries(node.attributes)) {
|
||||
attrs += ' ' + name;
|
||||
|
||||
if (value !== undefined) {
|
||||
const encodedValue = value
|
||||
.toString()
|
||||
.replace(config.regValEntities, config.encodeEntity);
|
||||
attrs += config.attrStart + encodedValue + config.attrEnd;
|
||||
}
|
||||
}
|
||||
return attrs;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {import('./types.js').XastText} node
|
||||
* @param {Options} config
|
||||
* @param {State} state
|
||||
* @returns {string}
|
||||
*/
|
||||
const stringifyText = (node, config, state) => {
|
||||
return (
|
||||
createIndent(config, state) +
|
||||
config.textStart +
|
||||
node.value.replace(config.regEntities, config.encodeEntity) +
|
||||
(state.textContext ? '' : config.textEnd)
|
||||
);
|
||||
};
|
||||
324
examples/nuxt3-websocket-client/node_modules/svgo/lib/style.js
generated
vendored
Normal file
324
examples/nuxt3-websocket-client/node_modules/svgo/lib/style.js
generated
vendored
Normal file
@@ -0,0 +1,324 @@
|
||||
import * as csstree from 'css-tree';
|
||||
import * as csswhat from 'css-what';
|
||||
import { syntax } from 'csso';
|
||||
import { matches } from './xast.js';
|
||||
import { visit } from './util/visit.js';
|
||||
import {
|
||||
attrsGroups,
|
||||
inheritableAttrs,
|
||||
presentationNonInheritableGroupAttrs,
|
||||
} from '../plugins/_collections.js';
|
||||
|
||||
const csstreeWalkSkip = csstree.walk.skip;
|
||||
|
||||
/**
|
||||
* @param {import('css-tree').Rule} ruleNode
|
||||
* @param {boolean} dynamic
|
||||
* @returns {import('./types.js').StylesheetRule[]}
|
||||
*/
|
||||
const parseRule = (ruleNode, dynamic) => {
|
||||
/** @type {import('./types.js').StylesheetDeclaration[]} */
|
||||
const declarations = [];
|
||||
// collect declarations
|
||||
ruleNode.block.children.forEach((cssNode) => {
|
||||
if (cssNode.type === 'Declaration') {
|
||||
declarations.push({
|
||||
name: cssNode.property,
|
||||
value: csstree.generate(cssNode.value),
|
||||
important: cssNode.important === true,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
/** @type {import('./types.js').StylesheetRule[]} */
|
||||
const rules = [];
|
||||
csstree.walk(ruleNode.prelude, (node) => {
|
||||
if (node.type === 'Selector') {
|
||||
const newNode = csstree.clone(node);
|
||||
let hasPseudoClasses = false;
|
||||
csstree.walk(newNode, (pseudoClassNode, item, list) => {
|
||||
if (pseudoClassNode.type === 'PseudoClassSelector') {
|
||||
hasPseudoClasses = true;
|
||||
list.remove(item);
|
||||
}
|
||||
});
|
||||
rules.push({
|
||||
specificity: syntax.specificity(node),
|
||||
dynamic: hasPseudoClasses || dynamic,
|
||||
// compute specificity from original node to consider pseudo classes
|
||||
selector: csstree.generate(newNode),
|
||||
declarations,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return rules;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} css
|
||||
* @param {boolean} dynamic
|
||||
* @returns {import('./types.js').StylesheetRule[]}
|
||||
*/
|
||||
const parseStylesheet = (css, dynamic) => {
|
||||
/** @type {import('./types.js').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 (
|
||||
[
|
||||
'keyframes',
|
||||
'-webkit-keyframes',
|
||||
'-o-keyframes',
|
||||
'-moz-keyframes',
|
||||
].includes(cssNode.name)
|
||||
) {
|
||||
return csstreeWalkSkip;
|
||||
}
|
||||
csstree.walk(cssNode, (ruleNode) => {
|
||||
if (ruleNode.type === 'Rule') {
|
||||
rules.push(...parseRule(ruleNode, dynamic || true));
|
||||
return csstreeWalkSkip;
|
||||
}
|
||||
});
|
||||
return csstreeWalkSkip;
|
||||
}
|
||||
});
|
||||
return rules;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} css
|
||||
* @returns {import('./types.js').StylesheetDeclaration[]}
|
||||
*/
|
||||
const parseStyleDeclarations = (css) => {
|
||||
/** @type {import('./types.js').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;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {import('./types.js').Stylesheet} stylesheet
|
||||
* @param {import('./types.js').XastElement} node
|
||||
* @param {Map<import('./types.js').XastNode, import('./types.js').XastParent>=} parents
|
||||
* @returns {import('./types.js').ComputedStyles}
|
||||
*/
|
||||
const computeOwnStyle = (stylesheet, node, parents) => {
|
||||
/** @type {import('./types.js').ComputedStyles} */
|
||||
const computedStyle = {};
|
||||
const importantStyles = new Map();
|
||||
|
||||
// collect attributes
|
||||
for (const [name, value] of Object.entries(node.attributes)) {
|
||||
if (attrsGroups.presentation.has(name)) {
|
||||
computedStyle[name] = { type: 'static', inherited: false, value };
|
||||
importantStyles.set(name, false);
|
||||
}
|
||||
}
|
||||
|
||||
// collect matching rules
|
||||
for (const { selector, declarations, dynamic } of stylesheet.rules) {
|
||||
if (matches(node, selector, parents)) {
|
||||
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 selector specificities.
|
||||
* Derived from https://github.com/keeganstreet/specificity/blob/8757133ddd2ed0163f120900047ff0f92760b536/specificity.js#L207
|
||||
*
|
||||
* @param {import('./types.js').Specificity} a
|
||||
* @param {import('./types.js').Specificity} b
|
||||
* @returns {number}
|
||||
*/
|
||||
export const compareSpecificity = (a, b) => {
|
||||
for (let i = 0; i < 4; i += 1) {
|
||||
if (a[i] < b[i]) {
|
||||
return -1;
|
||||
} else if (a[i] > b[i]) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {import('./types.js').XastRoot} root
|
||||
* @returns {import('./types.js').Stylesheet}
|
||||
*/
|
||||
export const collectStylesheet = (root) => {
|
||||
/** @type {import('./types.js').StylesheetRule[]} */
|
||||
const rules = [];
|
||||
/** @type {Map<import('./types.js').XastElement, import('./types.js').XastParent>} */
|
||||
const parents = new Map();
|
||||
|
||||
visit(root, {
|
||||
element: {
|
||||
enter: (node, parentNode) => {
|
||||
parents.set(node, parentNode);
|
||||
|
||||
if (node.name !== 'style') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
node.attributes.type == null ||
|
||||
node.attributes.type === '' ||
|
||||
node.attributes.type === 'text/css'
|
||||
) {
|
||||
const dynamic =
|
||||
node.attributes.media != null && node.attributes.media !== 'all';
|
||||
|
||||
for (const child of node.children) {
|
||||
if (child.type === 'text' || child.type === 'cdata') {
|
||||
rules.push(...parseStylesheet(child.value, dynamic));
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
// sort by selectors specificity
|
||||
rules.sort((a, b) => compareSpecificity(a.specificity, b.specificity));
|
||||
return { rules, parents };
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {import('./types.js').Stylesheet} stylesheet
|
||||
* @param {import('./types.js').XastElement} node
|
||||
* @returns {import('./types.js').ComputedStyles}
|
||||
*/
|
||||
export const computeStyle = (stylesheet, node) => {
|
||||
const { parents } = stylesheet;
|
||||
const computedStyles = computeOwnStyle(stylesheet, node, parents);
|
||||
let parent = parents.get(node);
|
||||
while (parent != null && parent.type !== 'root') {
|
||||
const inheritedStyles = computeOwnStyle(stylesheet, parent, parents);
|
||||
for (const [name, computed] of Object.entries(inheritedStyles)) {
|
||||
if (
|
||||
computedStyles[name] == null &&
|
||||
inheritableAttrs.has(name) &&
|
||||
!presentationNonInheritableGroupAttrs.has(name)
|
||||
) {
|
||||
computedStyles[name] = { ...computed, inherited: true };
|
||||
}
|
||||
}
|
||||
parent = parents.get(parent);
|
||||
}
|
||||
return computedStyles;
|
||||
};
|
||||
|
||||
/**
|
||||
* Determines if the CSS selector includes or traverses the given attribute.
|
||||
*
|
||||
* Classes and IDs are generated as attribute selectors, so you can check for if
|
||||
* a `.class` or `#id` is included by passing `name=class` or `name=id`
|
||||
* respectively.
|
||||
*
|
||||
* @param {csstree.ListItem<csstree.CssNode> | string} selector
|
||||
* @param {string} name
|
||||
* @param {?string} value
|
||||
* @param {boolean} traversed
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export const includesAttrSelector = (
|
||||
selector,
|
||||
name,
|
||||
value = null,
|
||||
traversed = false,
|
||||
) => {
|
||||
const selectors =
|
||||
typeof selector === 'string'
|
||||
? csswhat.parse(selector)
|
||||
: csswhat.parse(csstree.generate(selector.data));
|
||||
|
||||
for (const subselector of selectors) {
|
||||
const hasAttrSelector = subselector.some((segment, index) => {
|
||||
if (traversed) {
|
||||
if (index === subselector.length - 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const isNextTraversal = csswhat.isTraversal(subselector[index + 1]);
|
||||
|
||||
if (!isNextTraversal) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (segment.type !== 'attribute' || segment.name !== name) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return value == null ? true : segment.value === value;
|
||||
});
|
||||
|
||||
if (hasAttrSelector) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
98
examples/nuxt3-websocket-client/node_modules/svgo/lib/svgo-node.js
generated
vendored
Normal file
98
examples/nuxt3-websocket-client/node_modules/svgo/lib/svgo-node.js
generated
vendored
Normal file
@@ -0,0 +1,98 @@
|
||||
import os from 'os';
|
||||
import fs from 'fs/promises';
|
||||
import path from 'path';
|
||||
import * as svgo from './svgo.js';
|
||||
import url from 'url';
|
||||
|
||||
/**
|
||||
* @param {string} configFile
|
||||
* @returns {Promise<import('./types.js').Config>}
|
||||
*/
|
||||
const importConfig = async (configFile) => {
|
||||
const resolvedPath = path.resolve(configFile);
|
||||
const imported = await import(url.pathToFileURL(resolvedPath).toString());
|
||||
const config = imported.default;
|
||||
|
||||
if (config == null || typeof config !== 'object' || Array.isArray(config)) {
|
||||
throw Error(`Invalid config file "${configFile}"`);
|
||||
}
|
||||
return config;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} file
|
||||
* @returns {Promise<boolean>}
|
||||
*/
|
||||
const isFile = async (file) => {
|
||||
try {
|
||||
const stats = await fs.stat(file);
|
||||
return stats.isFile();
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
export * from './svgo.js';
|
||||
|
||||
/**
|
||||
* If you write a tool on top of svgo you might need a way to load svgo config.
|
||||
* You can also specify relative or absolute path and customize current working
|
||||
* directory.
|
||||
*
|
||||
* @type {<T extends string | null>(configFile?: T, cwd?: string) => Promise<T extends string ? import('./svgo.js').Config : import('./svgo.js').Config | null>}
|
||||
*/
|
||||
export const loadConfig = async (configFile, cwd = process.cwd()) => {
|
||||
if (configFile != null) {
|
||||
if (path.isAbsolute(configFile)) {
|
||||
return importConfig(configFile);
|
||||
} else {
|
||||
return importConfig(path.join(cwd, configFile));
|
||||
}
|
||||
}
|
||||
let dir = cwd;
|
||||
|
||||
while (true) {
|
||||
const js = path.join(dir, 'svgo.config.js');
|
||||
if (await isFile(js)) {
|
||||
return importConfig(js);
|
||||
}
|
||||
const mjs = path.join(dir, 'svgo.config.mjs');
|
||||
if (await isFile(mjs)) {
|
||||
return importConfig(mjs);
|
||||
}
|
||||
const cjs = path.join(dir, 'svgo.config.cjs');
|
||||
if (await isFile(cjs)) {
|
||||
return importConfig(cjs);
|
||||
}
|
||||
const parent = path.dirname(dir);
|
||||
if (dir === parent) {
|
||||
// @ts-expect-error https://github.com/microsoft/TypeScript/issues/33912
|
||||
return null;
|
||||
}
|
||||
dir = parent;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* The core of SVGO.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {import('./svgo.js').Config=} config
|
||||
* @returns {import('./svgo.js').Output}
|
||||
*/
|
||||
export const optimize = (input, config) => {
|
||||
if (config == null) {
|
||||
config = {};
|
||||
}
|
||||
if (typeof config !== 'object') {
|
||||
throw Error('Config should be an object');
|
||||
}
|
||||
return svgo.optimize(input, {
|
||||
...config,
|
||||
js2svg: {
|
||||
// platform specific default for end of line
|
||||
eol: os.EOL === '\r\n' ? 'crlf' : 'lf',
|
||||
...config.js2svg,
|
||||
},
|
||||
});
|
||||
};
|
||||
143
examples/nuxt3-websocket-client/node_modules/svgo/lib/svgo.js
generated
vendored
Normal file
143
examples/nuxt3-websocket-client/node_modules/svgo/lib/svgo.js
generated
vendored
Normal file
@@ -0,0 +1,143 @@
|
||||
import { builtinPlugins } from './builtin.js';
|
||||
import { encodeSVGDatauri } from './svgo/tools.js';
|
||||
import { invokePlugins } from './svgo/plugins.js';
|
||||
import { querySelector, querySelectorAll } from './xast.js';
|
||||
import { mapNodesToParents } from './util/map-nodes-to-parents.js';
|
||||
import { parseSvg } from './parser.js';
|
||||
import { stringifySvg } from './stringifier.js';
|
||||
import { VERSION } from './version.js';
|
||||
import * as _collections from '../plugins/_collections.js';
|
||||
|
||||
const pluginsMap = new Map();
|
||||
for (const plugin of builtinPlugins) {
|
||||
pluginsMap.set(plugin.name, plugin);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} name
|
||||
* @returns {import('./types.js').BuiltinPluginOrPreset<?, ?>}
|
||||
*/
|
||||
function getPlugin(name) {
|
||||
if (name === 'removeScriptElement') {
|
||||
console.warn(
|
||||
'Warning: removeScriptElement has been renamed to removeScripts, please update your SVGO config',
|
||||
);
|
||||
return pluginsMap.get('removeScripts');
|
||||
}
|
||||
|
||||
return pluginsMap.get(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string | import('./types.js').PluginConfig} plugin
|
||||
* @returns {?import('./types.js').PluginConfig}
|
||||
*/
|
||||
const resolvePluginConfig = (plugin) => {
|
||||
if (typeof plugin === 'string') {
|
||||
// resolve builtin plugin specified as string
|
||||
const builtinPlugin = getPlugin(plugin);
|
||||
if (builtinPlugin == null) {
|
||||
throw Error(`Unknown builtin plugin "${plugin}" specified.`);
|
||||
}
|
||||
return {
|
||||
name: plugin,
|
||||
params: {},
|
||||
fn: builtinPlugin.fn,
|
||||
};
|
||||
}
|
||||
if (typeof plugin === 'object' && plugin != null) {
|
||||
if (plugin.name == null) {
|
||||
throw Error(`Plugin name must be specified`);
|
||||
}
|
||||
// use custom plugin implementation
|
||||
// @ts-expect-error Checking for CustomPlugin with the presence of fn
|
||||
let fn = plugin.fn;
|
||||
if (fn == null) {
|
||||
// resolve builtin plugin implementation
|
||||
const builtinPlugin = getPlugin(plugin.name);
|
||||
if (builtinPlugin == null) {
|
||||
throw Error(`Unknown builtin plugin "${plugin.name}" specified.`);
|
||||
}
|
||||
fn = builtinPlugin.fn;
|
||||
}
|
||||
return {
|
||||
name: plugin.name,
|
||||
params: plugin.params,
|
||||
fn,
|
||||
};
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
export * from './types.js';
|
||||
|
||||
/**
|
||||
* The core of SVGO.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {import('./types.js').Config=} config
|
||||
* @returns {import('./types.js').Output}
|
||||
*/
|
||||
export 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 output = '';
|
||||
const info = {};
|
||||
if (config.path != null) {
|
||||
info.path = config.path;
|
||||
}
|
||||
for (let i = 0; i < maxPassCount; i += 1) {
|
||||
info.multipassCount = i;
|
||||
const ast = parseSvg(input, config.path);
|
||||
const plugins = config.plugins || ['preset-default'];
|
||||
if (!Array.isArray(plugins)) {
|
||||
throw Error(
|
||||
'malformed config, `plugins` property must be an array.\nSee more info here: https://github.com/svg/svgo#configuration',
|
||||
);
|
||||
}
|
||||
const resolvedPlugins = plugins
|
||||
.filter((plugin) => plugin != null)
|
||||
.map(resolvePluginConfig);
|
||||
|
||||
if (resolvedPlugins.length < plugins.length) {
|
||||
console.warn(
|
||||
'Warning: plugins list includes null or undefined elements, these will be ignored.',
|
||||
);
|
||||
}
|
||||
|
||||
/** @type {import('./types.js').Config} */
|
||||
const globalOverrides = {};
|
||||
if (config.floatPrecision != null) {
|
||||
globalOverrides.floatPrecision = config.floatPrecision;
|
||||
}
|
||||
invokePlugins(ast, info, resolvedPlugins, null, globalOverrides);
|
||||
output = stringifySvg(ast, config.js2svg);
|
||||
if (output.length < prevResultSize) {
|
||||
input = output;
|
||||
prevResultSize = output.length;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (config.datauri) {
|
||||
output = encodeSVGDatauri(output, config.datauri);
|
||||
}
|
||||
return {
|
||||
data: output,
|
||||
};
|
||||
};
|
||||
|
||||
export {
|
||||
VERSION,
|
||||
builtinPlugins,
|
||||
mapNodesToParents,
|
||||
querySelector,
|
||||
querySelectorAll,
|
||||
_collections,
|
||||
};
|
||||
533
examples/nuxt3-websocket-client/node_modules/svgo/lib/svgo/coa.js
generated
vendored
Normal file
533
examples/nuxt3-websocket-client/node_modules/svgo/lib/svgo/coa.js
generated
vendored
Normal file
@@ -0,0 +1,533 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import colors from 'picocolors';
|
||||
import { fileURLToPath } from 'url';
|
||||
import { decodeSVGDatauri, encodeSVGDatauri } from './tools.js';
|
||||
import { loadConfig, optimize } from '../svgo-node.js';
|
||||
import { builtinPlugins } from '../builtin.js';
|
||||
import { SvgoParserError } from '../parser.js';
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
const pkgPath = path.join(__dirname, '../../package.json');
|
||||
const PKG = JSON.parse(await fs.promises.readFile(pkgPath, 'utf-8'));
|
||||
|
||||
/**
|
||||
* Synchronously check if path is a directory. Tolerant to errors like ENOENT.
|
||||
*
|
||||
* @param {string} filePath
|
||||
*/
|
||||
export function checkIsDir(filePath) {
|
||||
try {
|
||||
return fs.lstatSync(filePath).isDirectory();
|
||||
} catch {
|
||||
return filePath.endsWith(path.sep);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('commander').Command} program
|
||||
*/
|
||||
export default function makeProgram(program) {
|
||||
program
|
||||
.name(PKG.name)
|
||||
.description(PKG.description)
|
||||
.version(PKG.version, '-v, --version')
|
||||
.argument('[INPUT...]', 'Alias to --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, .mjs, and .cjs 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ReadonlyArray<string>} args
|
||||
* @param {any} opts
|
||||
* @param {import('commander').Command} command
|
||||
* @returns
|
||||
*/
|
||||
async function action(args, opts, command) {
|
||||
const input = opts.input || args;
|
||||
let output = opts.output;
|
||||
/** @type {any} */
|
||||
let config = {};
|
||||
|
||||
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 (process?.versions?.node && PKG.engines.node) {
|
||||
// @ts-expect-error We control this and ensure it is never null.
|
||||
const 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((/** @type {string} */ pattern) => RegExp(pattern))
|
||||
: [];
|
||||
|
||||
// --precision
|
||||
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 {
|
||||
config.floatPrecision = Math.min(Math.max(0, number), 20);
|
||||
}
|
||||
}
|
||||
|
||||
// --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])) {
|
||||
const dir = output[0];
|
||||
for (let 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) {
|
||||
const outputFolder = (output && output[0]) || opts.folder;
|
||||
await optimizeFolder(config, opts.folder, outputFolder);
|
||||
}
|
||||
|
||||
// --input
|
||||
if (input.length !== 0) {
|
||||
// STDIN
|
||||
if (input[0] === '-') {
|
||||
return new Promise((resolve, reject) => {
|
||||
let data = '';
|
||||
const file = output[0];
|
||||
|
||||
process.stdin
|
||||
.on('data', (chunk) => (data += chunk))
|
||||
.once('end', () =>
|
||||
processSVGData(config, null, data, file).then(resolve, reject),
|
||||
);
|
||||
});
|
||||
// file
|
||||
} else {
|
||||
await Promise.all(
|
||||
input.map((/** @type {string} */ file, /** @type {number} */ n) =>
|
||||
optimizeFile(config, file, output[n]),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// --string
|
||||
} else if (opts.string) {
|
||||
const data = decodeSVGDatauri(opts.string);
|
||||
|
||||
return processSVGData(config, null, data, output[0]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Optimize SVG files in a directory.
|
||||
*
|
||||
* @param {any} config options
|
||||
* @param {string} dir input directory
|
||||
* @param {string} output output directory
|
||||
* @return {Promise<any>}
|
||||
*/
|
||||
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 {any} config options
|
||||
* @param {string} dir input directory
|
||||
* @param {ReadonlyArray<string>} files list of file names in the directory
|
||||
* @param {string} output output directory
|
||||
* @return {Promise<any>}
|
||||
*/
|
||||
function processDirectory(config, dir, files, output) {
|
||||
// take only *.svg files, recursively if necessary
|
||||
const 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 {any} config options
|
||||
* @param {string} dir input directory
|
||||
* @param {ReadonlyArray<string>} files list of file names in the directory
|
||||
* @param {string} output output directory
|
||||
* @return {any[]}
|
||||
*/
|
||||
function getFilesDescriptions(config, dir, files, output) {
|
||||
const filesInThisFolder = files
|
||||
.filter(
|
||||
(name) =>
|
||||
name.slice(-4).toLowerCase() === '.svg' &&
|
||||
!config.exclude.some((/** @type {RegExp} */ regExclude) =>
|
||||
regExclude.test(name),
|
||||
),
|
||||
)
|
||||
.map((name) => ({
|
||||
inputPath: path.resolve(dir, name),
|
||||
outputPath: path.resolve(output, name),
|
||||
}));
|
||||
|
||||
if (!config.recursive) {
|
||||
return filesInThisFolder;
|
||||
}
|
||||
|
||||
return filesInThisFolder.concat(
|
||||
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) => a.concat(b), []),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read SVG file and pass to processing.
|
||||
*
|
||||
* @param {any} config options
|
||||
* @param {string} file
|
||||
* @param {string} output
|
||||
* @return {Promise<any>}
|
||||
*/
|
||||
function optimizeFile(config, file, output) {
|
||||
return fs.promises.readFile(file, 'utf8').then(
|
||||
(data) => processSVGData(config, { path: file }, data, output, file),
|
||||
(error) => checkOptimizeFileError(config, file, output, error),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Optimize SVG data.
|
||||
*
|
||||
* @param {any} config options
|
||||
* @param {?{ path: string }} info
|
||||
* @param {string} data SVG content to optimize
|
||||
* @param {string} output where to write optimized file
|
||||
* @param {any=} input input file name (being used if output is a directory)
|
||||
* @return {Promise<any>}
|
||||
*/
|
||||
function processSVGData(config, info, data, output, input) {
|
||||
const startTime = Date.now();
|
||||
const prevFileSize = Buffer.byteLength(data, 'utf8');
|
||||
|
||||
let result;
|
||||
try {
|
||||
result = optimize(data, { ...config, ...info });
|
||||
} catch (error) {
|
||||
if (error instanceof SvgoParserError) {
|
||||
console.error(colors.red(error.toString()));
|
||||
process.exit(1);
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
if (config.datauri) {
|
||||
result.data = encodeSVGDatauri(result.data, config.datauri);
|
||||
}
|
||||
const resultFileSize = Buffer.byteLength(result.data, 'utf8');
|
||||
const 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<void>}
|
||||
*/
|
||||
async function writeOutput(input, output, data) {
|
||||
if (output == '-') {
|
||||
process.stdout.write(data);
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
await fs.promises.mkdir(path.dirname(output), { recursive: true });
|
||||
|
||||
return fs.promises
|
||||
.writeFile(output, data, 'utf8')
|
||||
.catch((error) => checkWriteFileError(input, output, data, error));
|
||||
}
|
||||
|
||||
/**
|
||||
* Write time taken to optimize.
|
||||
*
|
||||
* @param {number} time time in milliseconds.
|
||||
*/
|
||||
function printTimeInfo(time) {
|
||||
console.log(`Done in ${time} ms!`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write optimizing stats in a human-readable format.
|
||||
*
|
||||
* @param {number} inBytes size before optimization.
|
||||
* @param {number} outBytes size after optimization.
|
||||
*/
|
||||
function printProfitInfo(inBytes, outBytes) {
|
||||
const profitPercent = 100 - (outBytes * 100) / inBytes;
|
||||
/** @type {[string, Function]} */
|
||||
const ui = profitPercent < 0 ? ['+', colors.red] : ['-', colors.green];
|
||||
|
||||
console.log(
|
||||
Math.round((inBytes / 1024) * 1000) / 1000 + ' KiB',
|
||||
ui[0],
|
||||
ui[1](Math.abs(Math.round(profitPercent * 10) / 10) + '%'),
|
||||
'=',
|
||||
Math.round((outBytes / 1024) * 1000) / 1000 + ' KiB',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for errors, if it's a dir optimize the dir.
|
||||
*
|
||||
* @param {any} config
|
||||
* @param {string} input
|
||||
* @param {string} output
|
||||
* @param {Error & { code: string, path: string }} error
|
||||
* @return {Promise<void>}
|
||||
*/
|
||||
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 & { code: string }} error
|
||||
* @return {Promise<void>}
|
||||
*/
|
||||
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 = builtinPlugins
|
||||
.map((plugin) => ` [ ${colors.green(plugin.name)} ] ${plugin.description}`)
|
||||
.join('\n');
|
||||
console.log('Currently available plugins:\n' + list);
|
||||
}
|
||||
143
examples/nuxt3-websocket-client/node_modules/svgo/lib/svgo/css-select-adapter.js
generated
vendored
Normal file
143
examples/nuxt3-websocket-client/node_modules/svgo/lib/svgo/css-select-adapter.js
generated
vendored
Normal file
@@ -0,0 +1,143 @@
|
||||
import { mapNodesToParents } from '../util/map-nodes-to-parents.js';
|
||||
|
||||
/** @type {Required<import('css-select').Options<import('../types.js').XastNode & { children?: any }, import('../types.js').XastElement>>['adapter']['isTag']} */
|
||||
const isTag = (node) => {
|
||||
return node.type === 'element';
|
||||
};
|
||||
|
||||
/** @type {Required<import('css-select').Options<import('../types.js').XastNode & { children?: any }, import('../types.js').XastElement>>['adapter']['existsOne']} */
|
||||
const existsOne = (test, elems) => {
|
||||
return elems.some((elem) => {
|
||||
return isTag(elem) && (test(elem) || existsOne(test, getChildren(elem)));
|
||||
});
|
||||
};
|
||||
|
||||
/** @type {Required<import('css-select').Options<import('../types.js').XastNode & { children?: any }, import('../types.js').XastElement>>['adapter']['getAttributeValue']} */
|
||||
const getAttributeValue = (elem, name) => {
|
||||
return elem.attributes[name];
|
||||
};
|
||||
|
||||
/** @type {Required<import('css-select').Options<import('../types.js').XastNode & { children?: any }, import('../types.js').XastElement>>['adapter']['getChildren']} */
|
||||
const getChildren = (node) => {
|
||||
return node.children || [];
|
||||
};
|
||||
|
||||
/** @type {Required<import('css-select').Options<import('../types.js').XastNode & { children?: any }, import('../types.js').XastElement>>['adapter']['getName']} */
|
||||
const getName = (elemAst) => {
|
||||
return elemAst.name;
|
||||
};
|
||||
|
||||
/** @type {Required<import('css-select').Options<import('../types.js').XastNode & { children?: any }, import('../types.js').XastElement>>['adapter']['getText']} */
|
||||
const getText = (node) => {
|
||||
if (node.children[0].type === 'text' || node.children[0].type === 'cdata') {
|
||||
return node.children[0].value;
|
||||
}
|
||||
return '';
|
||||
};
|
||||
|
||||
/** @type {Required<import('css-select').Options<import('../types.js').XastNode & { children?: any }, import('../types.js').XastElement>>['adapter']['hasAttrib']} */
|
||||
const hasAttrib = (elem, name) => {
|
||||
return elem.attributes[name] !== undefined;
|
||||
};
|
||||
|
||||
/** @type {Required<import('css-select').Options<import('../types.js').XastNode & { children?: any }, import('../types.js').XastElement>>['adapter']['findAll']} */
|
||||
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;
|
||||
};
|
||||
|
||||
/** @type {Required<import('css-select').Options<import('../types.js').XastNode & { children?: any }, import('../types.js').XastElement>>['adapter']['findOne']} */
|
||||
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;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {import('../types.js').XastParent} relativeNode
|
||||
* @param {Map<import('../types.js').XastNode, import('../types.js').XastParent>=} parents
|
||||
* @returns {Required<import('css-select').Options<import('../types.js').XastNode & { children?: any }, import('../types.js').XastElement>>['adapter']}
|
||||
*/
|
||||
export function createAdapter(relativeNode, parents) {
|
||||
/** @type {Required<import('css-select').Options<import('../types.js').XastNode & { children?: any }, import('../types.js').XastElement>>['adapter']['getParent']} */
|
||||
const getParent = (node) => {
|
||||
if (!parents) {
|
||||
parents = mapNodesToParents(relativeNode);
|
||||
}
|
||||
|
||||
return parents.get(node) || null;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {any} elem
|
||||
* @returns {any}
|
||||
*/
|
||||
const getSiblings = (elem) => {
|
||||
const parent = getParent(elem);
|
||||
return parent ? getChildren(parent) : [];
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {any} nodes
|
||||
* @returns {any}
|
||||
*/
|
||||
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;
|
||||
};
|
||||
|
||||
return {
|
||||
isTag,
|
||||
existsOne,
|
||||
getAttributeValue,
|
||||
getChildren,
|
||||
getName,
|
||||
getParent,
|
||||
getSiblings,
|
||||
getText,
|
||||
hasAttrib,
|
||||
removeSubsets,
|
||||
findAll,
|
||||
findOne,
|
||||
};
|
||||
}
|
||||
71
examples/nuxt3-websocket-client/node_modules/svgo/lib/svgo/plugins.js
generated
vendored
Normal file
71
examples/nuxt3-websocket-client/node_modules/svgo/lib/svgo/plugins.js
generated
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
import { visit } from '../util/visit.js';
|
||||
|
||||
/**
|
||||
* Plugins engine.
|
||||
*
|
||||
* @module plugins
|
||||
*
|
||||
* @param {import('../types.js').XastNode} ast Input AST.
|
||||
* @param {any} info Extra information.
|
||||
* @param {ReadonlyArray<any>} plugins Plugins property from config.
|
||||
* @param {any} overrides
|
||||
* @param {any} globalOverrides
|
||||
*/
|
||||
export const invokePlugins = (
|
||||
ast,
|
||||
info,
|
||||
plugins,
|
||||
overrides,
|
||||
globalOverrides,
|
||||
) => {
|
||||
for (const plugin of plugins) {
|
||||
const override = overrides?.[plugin.name];
|
||||
if (override === false) {
|
||||
continue;
|
||||
}
|
||||
const params = { ...plugin.params, ...globalOverrides, ...override };
|
||||
|
||||
const visitor = plugin.fn(ast, params, info);
|
||||
if (visitor != null) {
|
||||
visit(ast, visitor);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @template {string} T
|
||||
* @param {{ name: T, plugins: ReadonlyArray<import('../types.js').BuiltinPlugin<string, any>> }} arg0
|
||||
* @returns {import('../types.js').BuiltinPluginOrPreset<T, any>}
|
||||
*/
|
||||
export const createPreset = ({ name, plugins }) => {
|
||||
return {
|
||||
name,
|
||||
isPreset: true,
|
||||
plugins: Object.freeze(plugins),
|
||||
fn: (ast, params, info) => {
|
||||
const { floatPrecision, overrides } = params;
|
||||
const globalOverrides = {};
|
||||
if (floatPrecision != null) {
|
||||
globalOverrides.floatPrecision = floatPrecision;
|
||||
}
|
||||
if (overrides) {
|
||||
const pluginNames = plugins.map(({ name }) => name);
|
||||
for (const pluginName of Object.keys(overrides)) {
|
||||
if (!pluginNames.includes(pluginName)) {
|
||||
console.warn(
|
||||
`You are trying to configure ${pluginName} which is not part of ${name}.\n` +
|
||||
`Try to put it before or after, for example\n\n` +
|
||||
`plugins: [\n` +
|
||||
` {\n` +
|
||||
` name: '${name}',\n` +
|
||||
` },\n` +
|
||||
` '${pluginName}'\n` +
|
||||
`]\n`,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
invokePlugins(ast, info, plugins, overrides, globalOverrides);
|
||||
},
|
||||
};
|
||||
};
|
||||
241
examples/nuxt3-websocket-client/node_modules/svgo/lib/svgo/tools.js
generated
vendored
Normal file
241
examples/nuxt3-websocket-client/node_modules/svgo/lib/svgo/tools.js
generated
vendored
Normal file
@@ -0,0 +1,241 @@
|
||||
import { attrsGroups, referencesProps } from '../../plugins/_collections.js';
|
||||
|
||||
/**
|
||||
* @typedef CleanupOutDataParams
|
||||
* @property {boolean=} noSpaceAfterFlags
|
||||
* @property {boolean=} leadingZero
|
||||
* @property {boolean=} negativeExtraSpace
|
||||
*/
|
||||
|
||||
const regReferencesUrl = /\burl\((["'])?#(.+?)\1\)/g;
|
||||
const regReferencesHref = /^#(.+?)$/;
|
||||
const regReferencesBegin = /(\w+)\.[a-zA-Z]/;
|
||||
|
||||
/**
|
||||
* Encode plain SVG data string into Data URI string.
|
||||
*
|
||||
* @param {string} str
|
||||
* @param {import('../types.js').DataUri=} type
|
||||
* @returns {string}
|
||||
*/
|
||||
export const encodeSVGDatauri = (str, type) => {
|
||||
let 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.
|
||||
*
|
||||
* @param {string} str
|
||||
* @returns {string}
|
||||
*/
|
||||
export const decodeSVGDatauri = (str) => {
|
||||
const regexp = /data:image\/svg\+xml(;charset=[^;,]*)?(;base64)?,(.*)/;
|
||||
const match = regexp.exec(str);
|
||||
|
||||
// plain string
|
||||
if (!match) {
|
||||
return str;
|
||||
}
|
||||
|
||||
const 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;
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert a row of numbers to an optimized string view.
|
||||
*
|
||||
* @example
|
||||
* [0, -1, .5, .5] → "0-1 .5.5"
|
||||
*
|
||||
* @param {ReadonlyArray<number>} data
|
||||
* @param {CleanupOutDataParams} params
|
||||
* @param {import('../types.js').PathDataCommand=} command
|
||||
* @returns {string}
|
||||
*/
|
||||
export const 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 arc 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')) {
|
||||
const 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.
|
||||
*
|
||||
* @param {number} value
|
||||
* @returns {string}
|
||||
* @example
|
||||
* 0.5 → .5
|
||||
* -0.5 → -.5
|
||||
*/
|
||||
export const removeLeadingZero = (value) => {
|
||||
const strValue = value.toString();
|
||||
|
||||
if (0 < value && value < 1 && strValue.startsWith('0')) {
|
||||
return strValue.slice(1);
|
||||
}
|
||||
|
||||
if (-1 < value && value < 0 && strValue[1] === '0') {
|
||||
return strValue[0] + strValue.slice(2);
|
||||
}
|
||||
|
||||
return strValue;
|
||||
};
|
||||
|
||||
/**
|
||||
* If the current node contains any scripts. This does not check parents or
|
||||
* children of the node, only the properties and attributes of the node itself.
|
||||
*
|
||||
* @param {import('../types.js').XastElement} node Current node to check against.
|
||||
* @returns {boolean} If the current node contains scripts.
|
||||
*/
|
||||
export const hasScripts = (node) => {
|
||||
if (node.name === 'script' && node.children.length !== 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (node.name === 'a') {
|
||||
const hasJsLinks = Object.entries(node.attributes).some(
|
||||
([attrKey, attrValue]) =>
|
||||
(attrKey === 'href' || attrKey.endsWith(':href')) &&
|
||||
attrValue != null &&
|
||||
attrValue.trimStart().startsWith('javascript:'),
|
||||
);
|
||||
|
||||
if (hasJsLinks) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
const eventAttrs = [
|
||||
...attrsGroups.animationEvent,
|
||||
...attrsGroups.documentEvent,
|
||||
...attrsGroups.documentElementEvent,
|
||||
...attrsGroups.globalEvent,
|
||||
...attrsGroups.graphicalEvent,
|
||||
];
|
||||
|
||||
return eventAttrs.some((attr) => node.attributes[attr] != null);
|
||||
};
|
||||
|
||||
/**
|
||||
* For example, a string that contains one or more of following would match and
|
||||
* return true:
|
||||
*
|
||||
* * `url(#gradient001)`
|
||||
* * `url('#gradient001')`
|
||||
*
|
||||
* @param {string} body
|
||||
* @returns {boolean} If the given string includes a URL reference.
|
||||
*/
|
||||
export const includesUrlReference = (body) => {
|
||||
return new RegExp(regReferencesUrl).test(body);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} attribute
|
||||
* @param {string} value
|
||||
* @returns {string[]}
|
||||
*/
|
||||
export const findReferences = (attribute, value) => {
|
||||
const results = [];
|
||||
|
||||
if (referencesProps.has(attribute)) {
|
||||
const matches = value.matchAll(regReferencesUrl);
|
||||
for (const match of matches) {
|
||||
results.push(match[2]);
|
||||
}
|
||||
}
|
||||
|
||||
if (attribute === 'href' || attribute.endsWith(':href')) {
|
||||
const match = regReferencesHref.exec(value);
|
||||
if (match != null) {
|
||||
results.push(match[1]);
|
||||
}
|
||||
}
|
||||
|
||||
if (attribute === 'begin') {
|
||||
const match = regReferencesBegin.exec(value);
|
||||
if (match != null) {
|
||||
results.push(match[1]);
|
||||
}
|
||||
}
|
||||
|
||||
return results.map((body) => decodeURI(body));
|
||||
};
|
||||
|
||||
/**
|
||||
* Does the same as {@link Number.toFixed} but without casting
|
||||
* the return value to a string.
|
||||
*
|
||||
* @param {number} num
|
||||
* @param {number} precision
|
||||
* @returns {number}
|
||||
*/
|
||||
export const toFixed = (num, precision) => {
|
||||
const pow = 10 ** precision;
|
||||
return Math.round(num * pow) / pow;
|
||||
};
|
||||
1
examples/nuxt3-websocket-client/node_modules/svgo/lib/types.js
generated
vendored
Normal file
1
examples/nuxt3-websocket-client/node_modules/svgo/lib/types.js
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export default {};
|
||||
350
examples/nuxt3-websocket-client/node_modules/svgo/lib/types.ts
generated
vendored
Normal file
350
examples/nuxt3-websocket-client/node_modules/svgo/lib/types.ts
generated
vendored
Normal file
@@ -0,0 +1,350 @@
|
||||
import { AddAttributesToSVGElementParams } from '../plugins/addAttributesToSVGElement.js';
|
||||
import { AddClassesToSVGElementParams } from '../plugins/addClassesToSVGElement.js';
|
||||
import { CleanupAttrsParams } from '../plugins/cleanupAttrs.js';
|
||||
import { CleanupIdsParams } from '../plugins/cleanupIds.js';
|
||||
import { CleanupListOfValuesParams } from '../plugins/cleanupListOfValues.js';
|
||||
import { CleanupNumericValuesParams } from '../plugins/cleanupNumericValues.js';
|
||||
import { ConvertColorsParams } from '../plugins/convertColors.js';
|
||||
import { ConvertPathDataParams } from '../plugins/convertPathData.js';
|
||||
import { ConvertShapeToPathParams } from '../plugins/convertShapeToPath.js';
|
||||
import { ConvertStyleToAttrsParams } from '../plugins/convertStyleToAttrs.js';
|
||||
import { ConvertTransformParams } from '../plugins/convertTransform.js';
|
||||
import { InlineStylesParams } from '../plugins/inlineStyles.js';
|
||||
import { MergePathsParams } from '../plugins/mergePaths.js';
|
||||
import { MinifyStylesParams } from '../plugins/minifyStyles.js';
|
||||
import { PrefixIdsParams } from '../plugins/prefixIds.js';
|
||||
import { RemoveAttrsParams } from '../plugins/removeAttrs.js';
|
||||
import { RemoveCommentsParams } from '../plugins/removeComments.js';
|
||||
import { RemoveDeprecatedAttrsParams } from '../plugins/removeDeprecatedAttrs.js';
|
||||
import { RemoveDescParams } from '../plugins/removeDesc.js';
|
||||
import { RemoveEditorsNSDataParams } from '../plugins/removeEditorsNSData.js';
|
||||
import { RemoveElementsByAttrParams } from '../plugins/removeElementsByAttr.js';
|
||||
import { RemoveEmptyTextParams } from '../plugins/removeEmptyText.js';
|
||||
import { RemoveHiddenElemsParams } from '../plugins/removeHiddenElems.js';
|
||||
import { RemoveUnknownsAndDefaultsParams } from '../plugins/removeUnknownsAndDefaults.js';
|
||||
import { RemoveUselessStrokeAndFillParams } from '../plugins/removeUselessStrokeAndFill.js';
|
||||
import { RemoveXlinkParams } from '../plugins/removeXlink.js';
|
||||
import { SortAttrsParams } from '../plugins/sortAttrs.js';
|
||||
|
||||
export type DefaultPlugins = {
|
||||
cleanupAttrs: CleanupAttrsParams;
|
||||
cleanupEnableBackground: null;
|
||||
cleanupIds: CleanupIdsParams;
|
||||
cleanupNumericValues: CleanupNumericValuesParams;
|
||||
collapseGroups: null;
|
||||
convertColors: ConvertColorsParams;
|
||||
convertEllipseToCircle: null;
|
||||
convertPathData: ConvertPathDataParams;
|
||||
convertShapeToPath: ConvertShapeToPathParams;
|
||||
convertTransform: ConvertTransformParams;
|
||||
mergeStyles: null;
|
||||
inlineStyles: InlineStylesParams;
|
||||
mergePaths: MergePathsParams;
|
||||
minifyStyles: MinifyStylesParams;
|
||||
moveElemsAttrsToGroup: null;
|
||||
moveGroupAttrsToElems: null;
|
||||
removeComments: RemoveCommentsParams;
|
||||
removeDeprecatedAttrs: RemoveDeprecatedAttrsParams;
|
||||
removeDesc: RemoveDescParams;
|
||||
removeDoctype: null;
|
||||
removeEditorsNSData: RemoveEditorsNSDataParams;
|
||||
removeEmptyAttrs: null;
|
||||
removeEmptyContainers: null;
|
||||
removeEmptyText: RemoveEmptyTextParams;
|
||||
removeHiddenElems: RemoveHiddenElemsParams;
|
||||
removeMetadata: null;
|
||||
removeNonInheritableGroupAttrs: null;
|
||||
removeUnknownsAndDefaults: RemoveUnknownsAndDefaultsParams;
|
||||
removeUnusedNS: null;
|
||||
removeUselessDefs: null;
|
||||
removeUselessStrokeAndFill: RemoveUselessStrokeAndFillParams;
|
||||
removeXMLProcInst: null;
|
||||
sortAttrs: SortAttrsParams;
|
||||
sortDefsChildren: null;
|
||||
};
|
||||
|
||||
export type PresetDefaultOverrides = {
|
||||
[Name in keyof DefaultPlugins]?: DefaultPlugins[Name] | false;
|
||||
};
|
||||
|
||||
export type BuiltinsWithOptionalParams = DefaultPlugins & {
|
||||
'preset-default': {
|
||||
floatPrecision?: number;
|
||||
/**
|
||||
* All default plugins can be customized or disabled here
|
||||
* for example
|
||||
* {
|
||||
* sortAttrs: { xmlnsOrder: "alphabetical" },
|
||||
* cleanupAttrs: false,
|
||||
* }
|
||||
*/
|
||||
overrides?: PresetDefaultOverrides;
|
||||
};
|
||||
cleanupListOfValues: CleanupListOfValuesParams;
|
||||
convertOneStopGradients: null;
|
||||
convertStyleToAttrs: ConvertStyleToAttrsParams;
|
||||
prefixIds: PrefixIdsParams;
|
||||
removeDimensions: null;
|
||||
removeOffCanvasPaths: null;
|
||||
removeRasterImages: null;
|
||||
removeScripts: null;
|
||||
removeStyleElement: null;
|
||||
removeTitle: null;
|
||||
removeViewBox: null;
|
||||
removeXlink: RemoveXlinkParams;
|
||||
removeXMLNS: null;
|
||||
reusePaths: null;
|
||||
};
|
||||
|
||||
export type BuiltinsWithRequiredParams = {
|
||||
addAttributesToSVGElement: AddAttributesToSVGElementParams;
|
||||
addClassesToSVGElement: AddClassesToSVGElementParams;
|
||||
removeAttributesBySelector: any;
|
||||
removeAttrs: RemoveAttrsParams;
|
||||
removeElementsByAttr: RemoveElementsByAttrParams;
|
||||
};
|
||||
|
||||
export type PluginsParams = BuiltinsWithOptionalParams &
|
||||
BuiltinsWithRequiredParams;
|
||||
|
||||
export type CustomPlugin<T = any> = {
|
||||
name: string;
|
||||
fn: Plugin<T>;
|
||||
params?: T;
|
||||
};
|
||||
|
||||
export type PluginConfig =
|
||||
| keyof BuiltinsWithOptionalParams
|
||||
| {
|
||||
[Name in keyof BuiltinsWithOptionalParams]: {
|
||||
name: Name;
|
||||
params?: BuiltinsWithOptionalParams[Name];
|
||||
};
|
||||
}[keyof BuiltinsWithOptionalParams]
|
||||
| {
|
||||
[Name in keyof BuiltinsWithRequiredParams]: {
|
||||
name: Name;
|
||||
params: BuiltinsWithRequiredParams[Name];
|
||||
};
|
||||
}[keyof BuiltinsWithRequiredParams]
|
||||
| CustomPlugin;
|
||||
|
||||
export type BuiltinPlugin<Name extends string, Params> = {
|
||||
/** Name of the plugin, also known as the plugin ID. */
|
||||
name: Name;
|
||||
description?: string;
|
||||
fn: Plugin<Params>;
|
||||
};
|
||||
|
||||
export type BuiltinPluginOrPreset<Name extends string, Params> = BuiltinPlugin<
|
||||
Name,
|
||||
Params
|
||||
> & {
|
||||
/** If the plugin is itself a preset that invokes other plugins. */
|
||||
isPreset?: true;
|
||||
/**
|
||||
* If the plugin is a preset that invokes other plugins, this returns an
|
||||
* array of the plugins in the preset in the order that they are invoked.
|
||||
*/
|
||||
plugins?: ReadonlyArray<BuiltinPlugin<string, Object>>;
|
||||
};
|
||||
|
||||
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: XastChild[];
|
||||
};
|
||||
|
||||
export type XastChild =
|
||||
| XastDoctype
|
||||
| XastInstruction
|
||||
| XastComment
|
||||
| XastCdata
|
||||
| XastText
|
||||
| XastElement;
|
||||
|
||||
export type XastRoot = {
|
||||
type: 'root';
|
||||
children: 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;
|
||||
};
|
||||
|
||||
export type VisitorNode<Node> = {
|
||||
enter?: (node: Node, parentNode: XastParent) => void | symbol;
|
||||
exit?: (node: Node, parentNode: XastParent) => void;
|
||||
};
|
||||
|
||||
export 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<P = null> = (
|
||||
root: XastRoot,
|
||||
params: P,
|
||||
info: PluginInfo,
|
||||
) => Visitor | null | void;
|
||||
|
||||
export type Specificity = [number, number, number];
|
||||
|
||||
export type StylesheetDeclaration = {
|
||||
name: string;
|
||||
value: string;
|
||||
important: boolean;
|
||||
};
|
||||
|
||||
export type StylesheetRule = {
|
||||
dynamic: boolean;
|
||||
selector: string;
|
||||
specificity: Specificity;
|
||||
declarations: StylesheetDeclaration[];
|
||||
};
|
||||
|
||||
export type Stylesheet = {
|
||||
rules: StylesheetRule[];
|
||||
parents: Map<XastElement, XastParent>;
|
||||
};
|
||||
|
||||
export type StaticStyle = {
|
||||
type: 'static';
|
||||
inherited: boolean;
|
||||
value: string;
|
||||
};
|
||||
|
||||
export 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: number[];
|
||||
};
|
||||
|
||||
export type DataUri = 'base64' | 'enc' | 'unenc';
|
||||
|
||||
export type Config = {
|
||||
/** Can be used by plugins, for example prefixIds. */
|
||||
path?: string;
|
||||
/** Pass over SVGs multiple times to ensure all optimizations are applied. */
|
||||
multipass?: boolean;
|
||||
/**
|
||||
* Precision of floating point numbers. Will be passed to each plugin that
|
||||
* supports this param.
|
||||
*/
|
||||
floatPrecision?: number;
|
||||
/**
|
||||
* Plugins configuration. By default SVGO uses `preset-default`, but may
|
||||
* contain builtin or custom plugins.
|
||||
*/
|
||||
plugins?: PluginConfig[];
|
||||
/** Options for rendering optimized SVG from AST. */
|
||||
js2svg?: StringifyOptions;
|
||||
/** Output as Data URI string. */
|
||||
datauri?: DataUri;
|
||||
};
|
||||
|
||||
export type Output = {
|
||||
data: string;
|
||||
};
|
||||
29
examples/nuxt3-websocket-client/node_modules/svgo/lib/util/map-nodes-to-parents.js
generated
vendored
Normal file
29
examples/nuxt3-websocket-client/node_modules/svgo/lib/util/map-nodes-to-parents.js
generated
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
import { visit } from './visit.js';
|
||||
|
||||
/**
|
||||
* Maps all nodes to their parent node recursively.
|
||||
*
|
||||
* @param {import('../types.js').XastParent} node
|
||||
* @returns {Map<import('../types.js').XastNode, import('../types.js').XastParent>}
|
||||
*/
|
||||
export function mapNodesToParents(node) {
|
||||
/** @type {Map<import('../types.js').XastNode, import('../types.js').XastParent>} */
|
||||
const parents = new Map();
|
||||
|
||||
for (const child of node.children) {
|
||||
parents.set(child, node);
|
||||
visit(
|
||||
child,
|
||||
{
|
||||
element: {
|
||||
enter: (child, parent) => {
|
||||
parents.set(child, parent);
|
||||
},
|
||||
},
|
||||
},
|
||||
node,
|
||||
);
|
||||
}
|
||||
|
||||
return parents;
|
||||
}
|
||||
36
examples/nuxt3-websocket-client/node_modules/svgo/lib/util/visit.js
generated
vendored
Normal file
36
examples/nuxt3-websocket-client/node_modules/svgo/lib/util/visit.js
generated
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
export const visitSkip = Symbol();
|
||||
|
||||
/**
|
||||
* @param {import('../types.js').XastNode} node
|
||||
* @param {import('../types.js').Visitor} visitor
|
||||
* @param {any=} parentNode
|
||||
*/
|
||||
export const visit = (node, visitor, parentNode) => {
|
||||
const callbacks = visitor[node.type];
|
||||
if (callbacks?.enter) {
|
||||
// @ts-expect-error 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 lose 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?.exit) {
|
||||
// @ts-expect-error hard to infer
|
||||
callbacks.exit(node, parentNode);
|
||||
}
|
||||
};
|
||||
7
examples/nuxt3-websocket-client/node_modules/svgo/lib/version.js
generated
vendored
Normal file
7
examples/nuxt3-websocket-client/node_modules/svgo/lib/version.js
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* Version of SVGO.
|
||||
*
|
||||
* @type {string}
|
||||
* @since 4.0.0
|
||||
*/
|
||||
export const VERSION = '4.0.0';
|
||||
53
examples/nuxt3-websocket-client/node_modules/svgo/lib/xast.js
generated
vendored
Normal file
53
examples/nuxt3-websocket-client/node_modules/svgo/lib/xast.js
generated
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
import { is, selectAll, selectOne } from 'css-select';
|
||||
import { createAdapter } from './svgo/css-select-adapter.js';
|
||||
|
||||
/**
|
||||
* @param {import('./types.js').XastParent} relativeNode
|
||||
* @param {Map<import('./types.js').XastNode, import('./types.js').XastParent>=} parents
|
||||
* @returns {import('css-select').Options<import('./types.js').XastNode & { children?: any }, import('./types.js').XastElement>}
|
||||
*/
|
||||
function createCssSelectOptions(relativeNode, parents) {
|
||||
return {
|
||||
xmlMode: true,
|
||||
adapter: createAdapter(relativeNode, parents),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('./types.js').XastParent} node Element to query the children of.
|
||||
* @param {string} selector CSS selector string.
|
||||
* @param {Map<import('./types.js').XastNode, import('./types.js').XastParent>=} parents
|
||||
* @returns {import('./types.js').XastChild[]} All matching elements.
|
||||
*/
|
||||
export const querySelectorAll = (node, selector, parents) => {
|
||||
return selectAll(selector, node, createCssSelectOptions(node, parents));
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {import('./types.js').XastParent} node Element to query the children of.
|
||||
* @param {string} selector CSS selector string.
|
||||
* @param {Map<import('./types.js').XastNode, import('./types.js').XastParent>=} parents
|
||||
* @returns {?import('./types.js').XastChild} First match, or null if there was no match.
|
||||
*/
|
||||
export const querySelector = (node, selector, parents) => {
|
||||
return selectOne(selector, node, createCssSelectOptions(node, parents));
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {import('./types.js').XastElement} node
|
||||
* @param {string} selector
|
||||
* @param {Map<import('./types.js').XastNode, import('./types.js').XastParent>=} parents
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export const matches = (node, selector, parents) => {
|
||||
return is(node, selector, createCssSelectOptions(node, parents));
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {import('./types.js').XastChild} node
|
||||
* @param {import('./types.js').XastParent} parentNode
|
||||
*/
|
||||
export const detachNodeFromParent = (node, parentNode) => {
|
||||
// avoid splice to not break for loops
|
||||
parentNode.children = parentNode.children.filter((child) => child !== node);
|
||||
};
|
||||
Reference in New Issue
Block a user