Fix code quality violations and exclude Manifest from checks
Document application modes (development/debug/production) Add global file drop handler, order column normalization, SPA hash fix Serve CDN assets via /_vendor/ URLs instead of merging into bundles Add production minification with license preservation Improve JSON formatting for debugging and production optimization Add CDN asset caching with CSS URL inlining for production builds Add three-mode system (development, debug, production) Update Manifest CLAUDE.md to reflect helper class architecture Refactor Manifest.php into helper classes for better organization Pre-manifest-refactor checkpoint: Add app_mode documentation 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
279
node_modules/svgo/plugins/convertTransform.js
generated
vendored
279
node_modules/svgo/plugins/convertTransform.js
generated
vendored
@@ -1,20 +1,48 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @typedef {import('../lib/types').XastElement} XastElement
|
||||
*/
|
||||
|
||||
const { cleanupOutData } = require('../lib/svgo/tools.js');
|
||||
const {
|
||||
import {
|
||||
js2transform,
|
||||
matrixToTransform,
|
||||
roundTransform,
|
||||
transform2js,
|
||||
transformsMultiply,
|
||||
matrixToTransform,
|
||||
} = require('./_transforms.js');
|
||||
} from './_transforms.js';
|
||||
|
||||
exports.type = 'visitor';
|
||||
exports.name = 'convertTransform';
|
||||
exports.active = true;
|
||||
exports.description = 'collapses multiple transformations and optimizes it';
|
||||
/**
|
||||
* @typedef ConvertTransformParams
|
||||
* @property {boolean=} convertToShorts
|
||||
* @property {number=} degPrecision
|
||||
* @property {number=} floatPrecision
|
||||
* @property {number=} transformPrecision
|
||||
* @property {boolean=} matrixToTransform
|
||||
* @property {boolean=} shortTranslate
|
||||
* @property {boolean=} shortScale
|
||||
* @property {boolean=} shortRotate
|
||||
* @property {boolean=} removeUseless
|
||||
* @property {boolean=} collapseIntoOne
|
||||
* @property {boolean=} leadingZero
|
||||
* @property {boolean=} negativeExtraSpace
|
||||
*
|
||||
* @typedef TransformParams
|
||||
* @property {boolean} convertToShorts
|
||||
* @property {number=} degPrecision
|
||||
* @property {number} floatPrecision
|
||||
* @property {number} transformPrecision
|
||||
* @property {boolean} matrixToTransform
|
||||
* @property {boolean} shortTranslate
|
||||
* @property {boolean} shortScale
|
||||
* @property {boolean} shortRotate
|
||||
* @property {boolean} removeUseless
|
||||
* @property {boolean} collapseIntoOne
|
||||
* @property {boolean} leadingZero
|
||||
* @property {boolean} negativeExtraSpace
|
||||
*
|
||||
* @typedef TransformItem
|
||||
* @property {string} name
|
||||
* @property {number[]} data
|
||||
*/
|
||||
|
||||
export const name = 'convertTransform';
|
||||
export const description =
|
||||
'collapses multiple transformations and optimizes it';
|
||||
|
||||
/**
|
||||
* Convert matrices to the short aliases,
|
||||
@@ -26,22 +54,9 @@ exports.description = 'collapses multiple transformations and optimizes it';
|
||||
*
|
||||
* @author Kir Belevich
|
||||
*
|
||||
* @type {import('../lib/types').Plugin<{
|
||||
* convertToShorts?: boolean,
|
||||
* degPrecision?: number,
|
||||
* floatPrecision?: number,
|
||||
* transformPrecision?: number,
|
||||
* matrixToTransform?: boolean,
|
||||
* shortTranslate?: boolean,
|
||||
* shortScale?: boolean,
|
||||
* shortRotate?: boolean,
|
||||
* removeUseless?: boolean,
|
||||
* collapseIntoOne?: boolean,
|
||||
* leadingZero?: boolean,
|
||||
* negativeExtraSpace?: boolean,
|
||||
* }>}
|
||||
* @type {import('../lib/types.js').Plugin<ConvertTransformParams>}
|
||||
*/
|
||||
exports.fn = (_root, params) => {
|
||||
export const fn = (_root, params) => {
|
||||
const {
|
||||
convertToShorts = true,
|
||||
// degPrecision = 3, // transformPrecision (or matrix precision) - 2 by default
|
||||
@@ -74,15 +89,14 @@ exports.fn = (_root, params) => {
|
||||
return {
|
||||
element: {
|
||||
enter: (node) => {
|
||||
// transform
|
||||
if (node.attributes.transform != null) {
|
||||
convertTransform(node, 'transform', newParams);
|
||||
}
|
||||
// gradientTransform
|
||||
|
||||
if (node.attributes.gradientTransform != null) {
|
||||
convertTransform(node, 'gradientTransform', newParams);
|
||||
}
|
||||
// patternTransform
|
||||
|
||||
if (node.attributes.patternTransform != null) {
|
||||
convertTransform(node, 'patternTransform', newParams);
|
||||
}
|
||||
@@ -92,30 +106,9 @@ exports.fn = (_root, params) => {
|
||||
};
|
||||
|
||||
/**
|
||||
* @typedef {{
|
||||
* convertToShorts: boolean,
|
||||
* degPrecision?: number,
|
||||
* floatPrecision: number,
|
||||
* transformPrecision: number,
|
||||
* matrixToTransform: boolean,
|
||||
* shortTranslate: boolean,
|
||||
* shortScale: boolean,
|
||||
* shortRotate: boolean,
|
||||
* removeUseless: boolean,
|
||||
* collapseIntoOne: boolean,
|
||||
* leadingZero: boolean,
|
||||
* negativeExtraSpace: boolean,
|
||||
* }} TransformParams
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {{ name: string, data: Array<number> }} TransformItem
|
||||
*/
|
||||
|
||||
/**
|
||||
* Main function.
|
||||
*
|
||||
* @type {(item: XastElement, attrName: string, params: TransformParams) => void}
|
||||
* @param {import('../lib/types.js').XastElement} item
|
||||
* @param {string} attrName
|
||||
* @param {TransformParams} params
|
||||
*/
|
||||
const convertTransform = (item, attrName, params) => {
|
||||
let data = transform2js(item.attributes[attrName]);
|
||||
@@ -144,14 +137,17 @@ const convertTransform = (item, attrName, params) => {
|
||||
|
||||
/**
|
||||
* Defines precision to work with certain parts.
|
||||
* transformPrecision - for scale and four first matrix parameters (needs a better precision due to multiplying),
|
||||
* floatPrecision - for translate including two last matrix and rotate parameters,
|
||||
* degPrecision - for rotate and skew. By default it's equal to (rougly)
|
||||
* transformPrecision - 2 or floatPrecision whichever is lower. Can be set in params.
|
||||
*
|
||||
* @type {(data: Array<TransformItem>, params: TransformParams) => TransformParams}
|
||||
* - `transformPrecision` - for scale and four first matrix parameters (needs a better precision due to multiplying).
|
||||
* - `floatPrecision` - for translate including two last matrix and rotate parameters.
|
||||
* - `degPrecision` - for rotate and skew. By default it's equal to (roughly).
|
||||
* - `transformPrecision` - 2 or floatPrecision whichever is lower. Can be set in params.
|
||||
*
|
||||
* clone params so it don't affect other elements transformations.
|
||||
* Clone parameters so that it doesn't affect other element transformations.
|
||||
*
|
||||
* @param {ReadonlyArray<TransformItem>} data
|
||||
* @param {TransformParams} param1
|
||||
* @returns {TransformParams}
|
||||
*/
|
||||
const definePrecision = (data, { ...newParams }) => {
|
||||
const matrixData = [];
|
||||
@@ -160,71 +156,37 @@ const definePrecision = (data, { ...newParams }) => {
|
||||
matrixData.push(...item.data.slice(0, 4));
|
||||
}
|
||||
}
|
||||
let significantDigits = newParams.transformPrecision;
|
||||
let numberOfDigits = newParams.transformPrecision;
|
||||
// Limit transform precision with matrix one. Calculating with larger precision doesn't add any value.
|
||||
if (matrixData.length) {
|
||||
newParams.transformPrecision = Math.min(
|
||||
newParams.transformPrecision,
|
||||
Math.max.apply(Math, matrixData.map(floatDigits)) ||
|
||||
newParams.transformPrecision
|
||||
newParams.transformPrecision,
|
||||
);
|
||||
significantDigits = Math.max.apply(
|
||||
numberOfDigits = Math.max.apply(
|
||||
Math,
|
||||
matrixData.map(
|
||||
(n) => n.toString().replace(/\D+/g, '').length // Number of digits in a number. 123.45 → 5
|
||||
)
|
||||
(n) => n.toString().replace(/\D+/g, '').length, // Number of digits in a number. 123.45 → 5
|
||||
),
|
||||
);
|
||||
}
|
||||
// No sense in angle precision more then number of significant digits in matrix.
|
||||
// No sense in angle precision more than number of significant digits in matrix.
|
||||
if (newParams.degPrecision == null) {
|
||||
newParams.degPrecision = Math.max(
|
||||
0,
|
||||
Math.min(newParams.floatPrecision, significantDigits - 2)
|
||||
Math.min(newParams.floatPrecision, numberOfDigits - 2),
|
||||
);
|
||||
}
|
||||
return newParams;
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {(data: Array<number>, params: TransformParams) => Array<number>}
|
||||
*/
|
||||
const degRound = (data, params) => {
|
||||
if (
|
||||
params.degPrecision != null &&
|
||||
params.degPrecision >= 1 &&
|
||||
params.floatPrecision < 20
|
||||
) {
|
||||
return smartRound(params.degPrecision, data);
|
||||
} else {
|
||||
return round(data);
|
||||
}
|
||||
};
|
||||
/**
|
||||
* @type {(data: Array<number>, params: TransformParams) => Array<number>}
|
||||
*/
|
||||
const floatRound = (data, params) => {
|
||||
if (params.floatPrecision >= 1 && params.floatPrecision < 20) {
|
||||
return smartRound(params.floatPrecision, data);
|
||||
} else {
|
||||
return round(data);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {(data: Array<number>, params: TransformParams) => Array<number>}
|
||||
*/
|
||||
const transformRound = (data, params) => {
|
||||
if (params.transformPrecision >= 1 && params.floatPrecision < 20) {
|
||||
return smartRound(params.transformPrecision, data);
|
||||
} else {
|
||||
return round(data);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns number of digits after the point. 0.125 → 3
|
||||
* Returns number of digits after the point.
|
||||
*
|
||||
* @type {(n: number) => number}
|
||||
* @example 0.125 → 3
|
||||
* @param {number} n
|
||||
* @returns {number}
|
||||
*/
|
||||
const floatDigits = (n) => {
|
||||
const str = n.toString();
|
||||
@@ -234,15 +196,17 @@ const floatDigits = (n) => {
|
||||
/**
|
||||
* Convert transforms to the shorthand alternatives.
|
||||
*
|
||||
* @type {(transforms: Array<TransformItem>, params: TransformParams) => Array<TransformItem>}
|
||||
* @param {TransformItem[]} transforms
|
||||
* @param {TransformParams} params
|
||||
* @returns {TransformItem[]}
|
||||
*/
|
||||
const convertToShorts = (transforms, params) => {
|
||||
for (var i = 0; i < transforms.length; i++) {
|
||||
var transform = transforms[i];
|
||||
for (let i = 0; i < transforms.length; i++) {
|
||||
let transform = transforms[i];
|
||||
|
||||
// convert matrix to the short aliases
|
||||
if (params.matrixToTransform && transform.name === 'matrix') {
|
||||
var decomposed = matrixToTransform(transform, params);
|
||||
const decomposed = matrixToTransform(transform, params);
|
||||
if (
|
||||
js2transform(decomposed, params).length <=
|
||||
js2transform([transform], params).length
|
||||
@@ -282,8 +246,7 @@ const convertToShorts = (transforms, params) => {
|
||||
// translate(cx cy) rotate(a) translate(-cx -cy) → rotate(a cx cy)
|
||||
if (
|
||||
params.shortRotate &&
|
||||
transforms[i - 2] &&
|
||||
transforms[i - 2].name === 'translate' &&
|
||||
transforms[i - 2]?.name === 'translate' &&
|
||||
transforms[i - 1].name === 'rotate' &&
|
||||
transforms[i].name === 'translate' &&
|
||||
transforms[i - 2].data[0] === -transforms[i].data[0] &&
|
||||
@@ -309,7 +272,8 @@ const convertToShorts = (transforms, params) => {
|
||||
/**
|
||||
* Remove useless transforms.
|
||||
*
|
||||
* @type {(trasforms: Array<TransformItem>) => Array<TransformItem>}
|
||||
* @param {ReadonlyArray<TransformItem>} transforms
|
||||
* @returns {TransformItem[]}
|
||||
*/
|
||||
const removeUseless = (transforms) => {
|
||||
return transforms.filter((transform) => {
|
||||
@@ -343,90 +307,3 @@ const removeUseless = (transforms) => {
|
||||
return true;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert transforms JS representation to string.
|
||||
*
|
||||
* @type {(transformJS: Array<TransformItem>, params: TransformParams) => string}
|
||||
*/
|
||||
const js2transform = (transformJS, params) => {
|
||||
var transformString = '';
|
||||
|
||||
// collect output value string
|
||||
transformJS.forEach((transform) => {
|
||||
roundTransform(transform, params);
|
||||
transformString +=
|
||||
(transformString && ' ') +
|
||||
transform.name +
|
||||
'(' +
|
||||
cleanupOutData(transform.data, params) +
|
||||
')';
|
||||
});
|
||||
|
||||
return transformString;
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {(transform: TransformItem, params: TransformParams) => TransformItem}
|
||||
*/
|
||||
const roundTransform = (transform, params) => {
|
||||
switch (transform.name) {
|
||||
case 'translate':
|
||||
transform.data = floatRound(transform.data, params);
|
||||
break;
|
||||
case 'rotate':
|
||||
transform.data = [
|
||||
...degRound(transform.data.slice(0, 1), params),
|
||||
...floatRound(transform.data.slice(1), params),
|
||||
];
|
||||
break;
|
||||
case 'skewX':
|
||||
case 'skewY':
|
||||
transform.data = degRound(transform.data, params);
|
||||
break;
|
||||
case 'scale':
|
||||
transform.data = transformRound(transform.data, params);
|
||||
break;
|
||||
case 'matrix':
|
||||
transform.data = [
|
||||
...transformRound(transform.data.slice(0, 4), params),
|
||||
...floatRound(transform.data.slice(4), params),
|
||||
];
|
||||
break;
|
||||
}
|
||||
return transform;
|
||||
};
|
||||
|
||||
/**
|
||||
* Rounds numbers in array.
|
||||
*
|
||||
* @type {(data: Array<number>) => Array<number>}
|
||||
*/
|
||||
const round = (data) => {
|
||||
return data.map(Math.round);
|
||||
};
|
||||
|
||||
/**
|
||||
* Decrease accuracy of floating-point numbers
|
||||
* in transforms keeping a specified number of decimals.
|
||||
* Smart rounds values like 2.349 to 2.35.
|
||||
*
|
||||
* @type {(precision: number, data: Array<number>) => Array<number>}
|
||||
*/
|
||||
const smartRound = (precision, data) => {
|
||||
for (
|
||||
var i = data.length,
|
||||
tolerance = +Math.pow(0.1, precision).toFixed(precision);
|
||||
i--;
|
||||
|
||||
) {
|
||||
if (Number(data[i].toFixed(precision)) !== data[i]) {
|
||||
var rounded = +data[i].toFixed(precision - 1);
|
||||
data[i] =
|
||||
+Math.abs(rounded - data[i]).toFixed(precision + 1) >= tolerance
|
||||
? +data[i].toFixed(precision)
|
||||
: rounded;
|
||||
}
|
||||
}
|
||||
return data;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user