mirror of
https://github.com/svg/svgo.git
synced 2025-07-31 07:44:22 +03:00
chore: apply more eslint rules (#2116)
This commit is contained in:
@ -34,6 +34,8 @@ export default [
|
|||||||
{
|
{
|
||||||
files: ['**/*.js', '**/*.mjs'],
|
files: ['**/*.js', '**/*.mjs'],
|
||||||
rules: {
|
rules: {
|
||||||
|
'one-var': ['error', 'never'],
|
||||||
|
curly: 'error',
|
||||||
strict: 'error',
|
strict: 'error',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -158,7 +158,7 @@ export const parseSvg = (data, from) => {
|
|||||||
|
|
||||||
sax.onopentag = (data) => {
|
sax.onopentag = (data) => {
|
||||||
/** @type {XastElement} */
|
/** @type {XastElement} */
|
||||||
let element = {
|
const element = {
|
||||||
type: 'element',
|
type: 'element',
|
||||||
name: data.name,
|
name: data.name,
|
||||||
attributes: {},
|
attributes: {},
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import * as csstree from 'css-tree';
|
import * as csstree from 'css-tree';
|
||||||
import * as csswhat from 'css-what';
|
import * as csswhat from 'css-what';
|
||||||
import { syntax } from 'csso';
|
import { syntax } from 'csso';
|
||||||
import { visit, matches } from './xast.js';
|
import { matches, visit } from './xast.js';
|
||||||
import {
|
import {
|
||||||
attrsGroups,
|
attrsGroups,
|
||||||
inheritableAttrs,
|
inheritableAttrs,
|
||||||
|
@ -3,12 +3,12 @@ import fs from 'fs/promises';
|
|||||||
import path from 'path';
|
import path from 'path';
|
||||||
import {
|
import {
|
||||||
VERSION,
|
VERSION,
|
||||||
optimize as optimizeAgnostic,
|
_collections,
|
||||||
builtinPlugins,
|
builtinPlugins,
|
||||||
mapNodesToParents,
|
mapNodesToParents,
|
||||||
|
optimize as optimizeAgnostic,
|
||||||
querySelector,
|
querySelector,
|
||||||
querySelectorAll,
|
querySelectorAll,
|
||||||
_collections,
|
|
||||||
} from './svgo.js';
|
} from './svgo.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import os from 'os';
|
import os from 'os';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import { optimize, loadConfig } from './svgo-node.js';
|
import { loadConfig, optimize } from './svgo-node.js';
|
||||||
|
|
||||||
const describeLF = os.EOL === '\r\n' ? describe.skip : describe;
|
const describeLF = os.EOL === '\r\n' ? describe.skip : describe;
|
||||||
const describeCRLF = os.EOL === '\r\n' ? describe : describe.skip;
|
const describeCRLF = os.EOL === '\r\n' ? describe : describe.skip;
|
||||||
|
@ -2,7 +2,7 @@ import fs from 'fs';
|
|||||||
import path from 'path';
|
import path from 'path';
|
||||||
import colors from 'picocolors';
|
import colors from 'picocolors';
|
||||||
import { fileURLToPath } from 'url';
|
import { fileURLToPath } from 'url';
|
||||||
import { encodeSVGDatauri, decodeSVGDatauri } from './tools.js';
|
import { decodeSVGDatauri, encodeSVGDatauri } from './tools.js';
|
||||||
import { loadConfig, optimize } from '../svgo-node.js';
|
import { loadConfig, optimize } from '../svgo-node.js';
|
||||||
import { builtin } from '../builtin.js';
|
import { builtin } from '../builtin.js';
|
||||||
import { SvgoParserError } from '../parser.js';
|
import { SvgoParserError } from '../parser.js';
|
||||||
@ -151,7 +151,7 @@ async function action(args, opts, command) {
|
|||||||
|
|
||||||
if (process?.versions?.node && PKG.engines.node) {
|
if (process?.versions?.node && PKG.engines.node) {
|
||||||
// @ts-expect-error We control this and ensure it is never null.
|
// @ts-expect-error We control this and ensure it is never null.
|
||||||
var nodeVersion = String(PKG.engines.node).match(/\d*(\.\d+)*/)[0];
|
const nodeVersion = String(PKG.engines.node).match(/\d*(\.\d+)*/)[0];
|
||||||
if (parseFloat(process.versions.node) < parseFloat(nodeVersion)) {
|
if (parseFloat(process.versions.node) < parseFloat(nodeVersion)) {
|
||||||
throw Error(
|
throw Error(
|
||||||
`${PKG.name} requires Node.js version ${nodeVersion} or higher.`,
|
`${PKG.name} requires Node.js version ${nodeVersion} or higher.`,
|
||||||
@ -224,7 +224,7 @@ async function action(args, opts, command) {
|
|||||||
if (input.length && input[0] != '-') {
|
if (input.length && input[0] != '-') {
|
||||||
if (output.length == 1 && checkIsDir(output[0])) {
|
if (output.length == 1 && checkIsDir(output[0])) {
|
||||||
const dir = output[0];
|
const dir = output[0];
|
||||||
for (var i = 0; i < input.length; i++) {
|
for (let i = 0; i < input.length; i++) {
|
||||||
output[i] = checkIsDir(input[i])
|
output[i] = checkIsDir(input[i])
|
||||||
? input[i]
|
? input[i]
|
||||||
: path.resolve(dir, path.basename(input[i]));
|
: path.resolve(dir, path.basename(input[i]));
|
||||||
@ -245,7 +245,7 @@ async function action(args, opts, command) {
|
|||||||
|
|
||||||
// --folder
|
// --folder
|
||||||
if (opts.folder) {
|
if (opts.folder) {
|
||||||
var outputFolder = (output && output[0]) || opts.folder;
|
const outputFolder = (output && output[0]) || opts.folder;
|
||||||
await optimizeFolder(config, opts.folder, outputFolder);
|
await optimizeFolder(config, opts.folder, outputFolder);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -254,8 +254,8 @@ async function action(args, opts, command) {
|
|||||||
// STDIN
|
// STDIN
|
||||||
if (input[0] === '-') {
|
if (input[0] === '-') {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
var data = '',
|
let data = '';
|
||||||
file = output[0];
|
const file = output[0];
|
||||||
|
|
||||||
process.stdin
|
process.stdin
|
||||||
.on('data', (chunk) => (data += chunk))
|
.on('data', (chunk) => (data += chunk))
|
||||||
@ -274,7 +274,7 @@ async function action(args, opts, command) {
|
|||||||
|
|
||||||
// --string
|
// --string
|
||||||
} else if (opts.string) {
|
} else if (opts.string) {
|
||||||
var data = decodeSVGDatauri(opts.string);
|
const data = decodeSVGDatauri(opts.string);
|
||||||
|
|
||||||
return processSVGData(config, null, data, output[0]);
|
return processSVGData(config, null, data, output[0]);
|
||||||
}
|
}
|
||||||
@ -308,7 +308,7 @@ function optimizeFolder(config, dir, output) {
|
|||||||
*/
|
*/
|
||||||
function processDirectory(config, dir, files, output) {
|
function processDirectory(config, dir, files, output) {
|
||||||
// take only *.svg files, recursively if necessary
|
// take only *.svg files, recursively if necessary
|
||||||
var svgFilesDescriptions = getFilesDescriptions(config, dir, files, output);
|
const svgFilesDescriptions = getFilesDescriptions(config, dir, files, output);
|
||||||
|
|
||||||
return svgFilesDescriptions.length
|
return svgFilesDescriptions.length
|
||||||
? Promise.all(
|
? Promise.all(
|
||||||
@ -396,8 +396,8 @@ function optimizeFile(config, file, output) {
|
|||||||
* @return {Promise<any>}
|
* @return {Promise<any>}
|
||||||
*/
|
*/
|
||||||
function processSVGData(config, info, data, output, input = undefined) {
|
function processSVGData(config, info, data, output, input = undefined) {
|
||||||
var startTime = Date.now(),
|
const startTime = Date.now();
|
||||||
prevFileSize = Buffer.byteLength(data, 'utf8');
|
const prevFileSize = Buffer.byteLength(data, 'utf8');
|
||||||
|
|
||||||
let result;
|
let result;
|
||||||
try {
|
try {
|
||||||
@ -413,8 +413,8 @@ function processSVGData(config, info, data, output, input = undefined) {
|
|||||||
if (config.datauri) {
|
if (config.datauri) {
|
||||||
result.data = encodeSVGDatauri(result.data, config.datauri);
|
result.data = encodeSVGDatauri(result.data, config.datauri);
|
||||||
}
|
}
|
||||||
var resultFileSize = Buffer.byteLength(result.data, 'utf8'),
|
const resultFileSize = Buffer.byteLength(result.data, 'utf8');
|
||||||
processingTime = Date.now() - startTime;
|
const processingTime = Date.now() - startTime;
|
||||||
|
|
||||||
return writeOutput(input, output, result.data).then(
|
return writeOutput(input, output, result.data).then(
|
||||||
function () {
|
function () {
|
||||||
|
@ -23,7 +23,7 @@ const regReferencesBegin = /(\w+)\.[a-zA-Z]/;
|
|||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
export const encodeSVGDatauri = (str, type) => {
|
export const encodeSVGDatauri = (str, type) => {
|
||||||
var prefix = 'data:image/svg+xml';
|
let prefix = 'data:image/svg+xml';
|
||||||
if (!type || type === 'base64') {
|
if (!type || type === 'base64') {
|
||||||
// base64
|
// base64
|
||||||
prefix += ';base64,';
|
prefix += ';base64,';
|
||||||
@ -45,13 +45,15 @@ export const encodeSVGDatauri = (str, type) => {
|
|||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
export const decodeSVGDatauri = (str) => {
|
export const decodeSVGDatauri = (str) => {
|
||||||
var regexp = /data:image\/svg\+xml(;charset=[^;,]*)?(;base64)?,(.*)/;
|
const regexp = /data:image\/svg\+xml(;charset=[^;,]*)?(;base64)?,(.*)/;
|
||||||
var match = regexp.exec(str);
|
const match = regexp.exec(str);
|
||||||
|
|
||||||
// plain string
|
// plain string
|
||||||
if (!match) return str;
|
if (!match) {
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
var data = match[3];
|
const data = match[3];
|
||||||
|
|
||||||
if (match[2]) {
|
if (match[2]) {
|
||||||
// base64
|
// base64
|
||||||
@ -88,13 +90,17 @@ export const cleanupOutData = (data, params, command) => {
|
|||||||
delimiter = ' ';
|
delimiter = ' ';
|
||||||
|
|
||||||
// no extra space in front of first number
|
// no extra space in front of first number
|
||||||
if (i == 0) delimiter = '';
|
if (i == 0) {
|
||||||
|
delimiter = '';
|
||||||
|
}
|
||||||
|
|
||||||
// no extra space after arc command flags (large-arc and sweep flags)
|
// no extra space after arc command flags (large-arc and sweep flags)
|
||||||
// a20 60 45 0 1 30 20 → a20 60 45 0130 20
|
// a20 60 45 0 1 30 20 → a20 60 45 0130 20
|
||||||
if (params.noSpaceAfterFlags && (command == 'A' || command == 'a')) {
|
if (params.noSpaceAfterFlags && (command == 'A' || command == 'a')) {
|
||||||
var pos = i % 7;
|
const pos = i % 7;
|
||||||
if (pos == 4 || pos == 5) delimiter = '';
|
if (pos == 4 || pos == 5) {
|
||||||
|
delimiter = '';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove floating-point numbers leading zeros
|
// remove floating-point numbers leading zeros
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
import { selectAll, selectOne, is } from 'css-select';
|
import { is, selectAll, selectOne } from 'css-select';
|
||||||
import { createAdapter } from './svgo/css-select-adapter.js';
|
import { createAdapter } from './svgo/css-select-adapter.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {import('css-select').Options<XastNode & { children?: any }, XastElement>} Options
|
* @typedef {import('css-select').Options<XastNode & { children?: any }, XastElement>} Options
|
||||||
|
* @typedef {import('./types.js').Visitor} Visitor
|
||||||
|
* @typedef {import('./types.js').XastChild} XastChild
|
||||||
* @typedef {import('./types.js').XastElement} XastElement
|
* @typedef {import('./types.js').XastElement} XastElement
|
||||||
* @typedef {import('./types.js').XastNode} XastNode
|
* @typedef {import('./types.js').XastNode} XastNode
|
||||||
* @typedef {import('./types.js').XastChild} XastChild
|
|
||||||
* @typedef {import('./types.js').XastParent} XastParent
|
* @typedef {import('./types.js').XastParent} XastParent
|
||||||
* @typedef {import('./types.js').Visitor} Visitor
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
|
import { detachNodeFromParent, visit, visitSkip } from './xast.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {import('./types.js').XastElement} XastElement
|
* @typedef {import('./types.js').XastElement} XastElement
|
||||||
* @typedef {import('./types.js').XastRoot} XastRoot
|
* @typedef {import('./types.js').XastRoot} XastRoot
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { visit, visitSkip, detachNodeFromParent } from './xast.js';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {XastElement[]} children
|
* @param {XastElement[]} children
|
||||||
* @returns {XastRoot}
|
* @returns {XastRoot}
|
||||||
|
@ -133,7 +133,7 @@
|
|||||||
"pixelmatch": "^7.1.0",
|
"pixelmatch": "^7.1.0",
|
||||||
"playwright": "^1.51.1",
|
"playwright": "^1.51.1",
|
||||||
"pngjs": "^7.0.0",
|
"pngjs": "^7.0.0",
|
||||||
"prettier": "^3.2.5",
|
"prettier": "^3.5.3",
|
||||||
"rimraf": "^5.0.7",
|
"rimraf": "^5.0.7",
|
||||||
"rollup": "^4.22.4",
|
"rollup": "^4.22.4",
|
||||||
"tar-stream": "^3.1.7",
|
"tar-stream": "^3.1.7",
|
||||||
|
166
plugins/_path.js
166
plugins/_path.js
@ -24,7 +24,7 @@ import { parsePathData, stringifyPathData } from '../lib/path.js';
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/** @type {[number, number]} */
|
/** @type {[number, number]} */
|
||||||
var prevCtrlPoint;
|
let prevCtrlPoint;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert path string to JS representation.
|
* Convert path string to JS representation.
|
||||||
@ -34,7 +34,10 @@ var prevCtrlPoint;
|
|||||||
*/
|
*/
|
||||||
export const path2js = (path) => {
|
export const path2js = (path) => {
|
||||||
// @ts-expect-error legacy
|
// @ts-expect-error legacy
|
||||||
if (path.pathJS) return path.pathJS;
|
if (path.pathJS) {
|
||||||
|
// @ts-expect-error legacy
|
||||||
|
return path.pathJS;
|
||||||
|
}
|
||||||
/** @type {PathDataItem[]} */
|
/** @type {PathDataItem[]} */
|
||||||
const pathData = []; // JS representation of the path data
|
const pathData = []; // JS representation of the path data
|
||||||
const newPathData = parsePathData(path.attributes.d);
|
const newPathData = parsePathData(path.attributes.d);
|
||||||
@ -59,8 +62,8 @@ export const path2js = (path) => {
|
|||||||
const convertRelativeToAbsolute = (data) => {
|
const convertRelativeToAbsolute = (data) => {
|
||||||
/** @type {PathDataItem[]} */
|
/** @type {PathDataItem[]} */
|
||||||
const newData = [];
|
const newData = [];
|
||||||
let start = [0, 0];
|
const start = [0, 0];
|
||||||
let cursor = [0, 0];
|
const cursor = [0, 0];
|
||||||
|
|
||||||
for (let { command, args } of data) {
|
for (let { command, args } of data) {
|
||||||
args = args.slice();
|
args = args.slice();
|
||||||
@ -259,8 +262,9 @@ export const intersects = function (path1, path2) {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
)
|
) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Get a convex hull from points of each subpath. Has the most complexity O(n·log n).
|
// Get a convex hull from points of each subpath. Has the most complexity O(n·log n).
|
||||||
const hullNest1 = points1.list.map(convexHull);
|
const hullNest1 = points1.list.map(convexHull);
|
||||||
@ -268,15 +272,19 @@ export const intersects = function (path1, path2) {
|
|||||||
|
|
||||||
// Check intersection of every subpath of the first path with every subpath of the second.
|
// Check intersection of every subpath of the first path with every subpath of the second.
|
||||||
return hullNest1.some(function (hull1) {
|
return hullNest1.some(function (hull1) {
|
||||||
if (hull1.list.length < 3) return false;
|
if (hull1.list.length < 3) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return hullNest2.some(function (hull2) {
|
return hullNest2.some(function (hull2) {
|
||||||
if (hull2.list.length < 3) return false;
|
if (hull2.list.length < 3) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
var simplex = [getSupport(hull1, hull2, [1, 0])], // create the initial simplex
|
const simplex = [getSupport(hull1, hull2, [1, 0])]; // create the initial simplex
|
||||||
direction = minus(simplex[0]); // set the direction to point towards the origin
|
const direction = minus(simplex[0]); // set the direction to point towards the origin
|
||||||
|
|
||||||
var iterations = 1e4; // infinite loop protection, 10 000 iterations is more than enough
|
let iterations = 1e4; // infinite loop protection, 10 000 iterations is more than enough
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
if (iterations-- == 0) {
|
if (iterations-- == 0) {
|
||||||
@ -288,9 +296,13 @@ export const intersects = function (path1, path2) {
|
|||||||
// add a new point
|
// add a new point
|
||||||
simplex.push(getSupport(hull1, hull2, direction));
|
simplex.push(getSupport(hull1, hull2, direction));
|
||||||
// see if the new point was on the correct side of the origin
|
// see if the new point was on the correct side of the origin
|
||||||
if (dot(direction, simplex[simplex.length - 1]) <= 0) return false;
|
if (dot(direction, simplex[simplex.length - 1]) <= 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
// process the simplex
|
// process the simplex
|
||||||
if (processSimplex(simplex, direction)) return true;
|
if (processSimplex(simplex, direction)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -316,16 +328,16 @@ export const intersects = function (path1, path2) {
|
|||||||
* @returns {number[]}
|
* @returns {number[]}
|
||||||
*/
|
*/
|
||||||
function supportPoint(polygon, direction) {
|
function supportPoint(polygon, direction) {
|
||||||
var index =
|
let index =
|
||||||
direction[1] >= 0
|
direction[1] >= 0
|
||||||
? direction[0] < 0
|
? direction[0] < 0
|
||||||
? polygon.maxY
|
? polygon.maxY
|
||||||
: polygon.maxX
|
: polygon.maxX
|
||||||
: direction[0] < 0
|
: direction[0] < 0
|
||||||
? polygon.minX
|
? polygon.minX
|
||||||
: polygon.minY,
|
: polygon.minY;
|
||||||
max = -Infinity,
|
let max = -Infinity;
|
||||||
value;
|
let value;
|
||||||
while ((value = dot(polygon.list[index], direction)) > max) {
|
while ((value = dot(polygon.list[index], direction)) > max) {
|
||||||
max = value;
|
max = value;
|
||||||
index = ++index % polygon.list.length;
|
index = ++index % polygon.list.length;
|
||||||
@ -343,10 +355,10 @@ function processSimplex(simplex, direction) {
|
|||||||
// we only need to handle to 1-simplex and 2-simplex
|
// we only need to handle to 1-simplex and 2-simplex
|
||||||
if (simplex.length == 2) {
|
if (simplex.length == 2) {
|
||||||
// 1-simplex
|
// 1-simplex
|
||||||
let a = simplex[1],
|
const a = simplex[1];
|
||||||
b = simplex[0],
|
const b = simplex[0];
|
||||||
AO = minus(simplex[1]),
|
const AO = minus(simplex[1]);
|
||||||
AB = sub(b, a);
|
const AB = sub(b, a);
|
||||||
// AO is in the same direction as AB
|
// AO is in the same direction as AB
|
||||||
if (dot(AO, AB) > 0) {
|
if (dot(AO, AB) > 0) {
|
||||||
// get the vector perpendicular to AB facing O
|
// get the vector perpendicular to AB facing O
|
||||||
@ -358,14 +370,14 @@ function processSimplex(simplex, direction) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 2-simplex
|
// 2-simplex
|
||||||
let a = simplex[2], // [a, b, c] = simplex
|
const a = simplex[2]; // [a, b, c] = simplex
|
||||||
b = simplex[1],
|
const b = simplex[1];
|
||||||
c = simplex[0],
|
const c = simplex[0];
|
||||||
AB = sub(b, a),
|
const AB = sub(b, a);
|
||||||
AC = sub(c, a),
|
const AC = sub(c, a);
|
||||||
AO = minus(a),
|
const AO = minus(a);
|
||||||
ACB = orth(AB, AC), // the vector perpendicular to AB facing away from C
|
const ACB = orth(AB, AC); // the vector perpendicular to AB facing away from C
|
||||||
ABC = orth(AC, AB); // the vector perpendicular to AC facing away from B
|
const ABC = orth(AC, AB); // the vector perpendicular to AC facing away from B
|
||||||
|
|
||||||
if (dot(ACB, AO) > 0) {
|
if (dot(ACB, AO) > 0) {
|
||||||
if (dot(AB, AO) > 0) {
|
if (dot(AB, AO) > 0) {
|
||||||
@ -388,7 +400,9 @@ function processSimplex(simplex, direction) {
|
|||||||
simplex.splice(0, 2); // simplex = [a]
|
simplex.splice(0, 2); // simplex = [a]
|
||||||
}
|
}
|
||||||
} // region 7
|
} // region 7
|
||||||
else return true;
|
else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -425,7 +439,7 @@ function dot(v1, v2) {
|
|||||||
* @returns {number[]}
|
* @returns {number[]}
|
||||||
*/
|
*/
|
||||||
function orth(v, from) {
|
function orth(v, from) {
|
||||||
var o = [-v[1], v[0]];
|
const o = [-v[1], v[0]];
|
||||||
return dot(o, minus(from)) < 0 ? minus(o) : o;
|
return dot(o, minus(from)) < 0 ? minus(o) : o;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -477,10 +491,10 @@ function gatherPoints(pathData) {
|
|||||||
points.list.length === 0
|
points.list.length === 0
|
||||||
? { list: [], minX: 0, minY: 0, maxX: 0, maxY: 0 }
|
? { list: [], minX: 0, minY: 0, maxX: 0, maxY: 0 }
|
||||||
: points.list[points.list.length - 1];
|
: points.list[points.list.length - 1];
|
||||||
let prev = i === 0 ? null : pathData[i - 1];
|
const prev = i === 0 ? null : pathData[i - 1];
|
||||||
let basePoint =
|
let basePoint =
|
||||||
subPath.list.length === 0 ? null : subPath.list[subPath.list.length - 1];
|
subPath.list.length === 0 ? null : subPath.list[subPath.list.length - 1];
|
||||||
let data = pathDataItem.args;
|
const data = pathDataItem.args;
|
||||||
let ctrlPoint = basePoint;
|
let ctrlPoint = basePoint;
|
||||||
|
|
||||||
// TODO fix null hack
|
// TODO fix null hack
|
||||||
@ -580,7 +594,7 @@ function gatherPoints(pathData) {
|
|||||||
if (basePoint != null) {
|
if (basePoint != null) {
|
||||||
// Convert the arc to Bézier curves and use the same approximation
|
// Convert the arc to Bézier curves and use the same approximation
|
||||||
// @ts-expect-error no idea what's going on here
|
// @ts-expect-error no idea what's going on here
|
||||||
var curves = a2c.apply(0, basePoint.concat(data));
|
const curves = a2c.apply(0, basePoint.concat(data));
|
||||||
for (
|
for (
|
||||||
var cData;
|
var cData;
|
||||||
(cData = curves.splice(0, 6).map(toAbsolute)).length;
|
(cData = curves.splice(0, 6).map(toAbsolute)).length;
|
||||||
@ -600,14 +614,18 @@ function gatherPoints(pathData) {
|
|||||||
0.5 * (cData[2] + cData[4]),
|
0.5 * (cData[2] + cData[4]),
|
||||||
0.5 * (cData[3] + cData[5]),
|
0.5 * (cData[3] + cData[5]),
|
||||||
]);
|
]);
|
||||||
if (curves.length) addPoint(subPath, (basePoint = cData.slice(-2)));
|
if (curves.length) {
|
||||||
|
addPoint(subPath, (basePoint = cData.slice(-2)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save final command coordinates
|
// Save final command coordinates
|
||||||
if (data.length >= 2) addPoint(subPath, data.slice(-2));
|
if (data.length >= 2) {
|
||||||
|
addPoint(subPath, data.slice(-2));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return points;
|
return points;
|
||||||
@ -626,9 +644,9 @@ function convexHull(points) {
|
|||||||
return a[0] == b[0] ? a[1] - b[1] : a[0] - b[0];
|
return a[0] == b[0] ? a[1] - b[1] : a[0] - b[0];
|
||||||
});
|
});
|
||||||
|
|
||||||
var lower = [],
|
const lower = [];
|
||||||
minY = 0,
|
let minY = 0;
|
||||||
bottom = 0;
|
let bottom = 0;
|
||||||
for (let i = 0; i < points.list.length; i++) {
|
for (let i = 0; i < points.list.length; i++) {
|
||||||
while (
|
while (
|
||||||
lower.length >= 2 &&
|
lower.length >= 2 &&
|
||||||
@ -644,9 +662,9 @@ function convexHull(points) {
|
|||||||
lower.push(points.list[i]);
|
lower.push(points.list[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
var upper = [],
|
const upper = [];
|
||||||
maxY = points.list.length - 1,
|
let maxY = points.list.length - 1;
|
||||||
top = 0;
|
let top = 0;
|
||||||
for (let i = points.list.length; i--; ) {
|
for (let i = points.list.length; i--; ) {
|
||||||
while (
|
while (
|
||||||
upper.length >= 2 &&
|
upper.length >= 2 &&
|
||||||
@ -748,17 +766,17 @@ const a2c = (
|
|||||||
y1 = rotateY(x1, y1, -rad);
|
y1 = rotateY(x1, y1, -rad);
|
||||||
x2 = rotateX(x2, y2, -rad);
|
x2 = rotateX(x2, y2, -rad);
|
||||||
y2 = rotateY(x2, y2, -rad);
|
y2 = rotateY(x2, y2, -rad);
|
||||||
var x = (x1 - x2) / 2,
|
const x = (x1 - x2) / 2;
|
||||||
y = (y1 - y2) / 2;
|
const y = (y1 - y2) / 2;
|
||||||
var h = (x * x) / (rx * rx) + (y * y) / (ry * ry);
|
let h = (x * x) / (rx * rx) + (y * y) / (ry * ry);
|
||||||
if (h > 1) {
|
if (h > 1) {
|
||||||
h = Math.sqrt(h);
|
h = Math.sqrt(h);
|
||||||
rx = h * rx;
|
rx = h * rx;
|
||||||
ry = h * ry;
|
ry = h * ry;
|
||||||
}
|
}
|
||||||
var rx2 = rx * rx;
|
const rx2 = rx * rx;
|
||||||
var ry2 = ry * ry;
|
const ry2 = ry * ry;
|
||||||
var k =
|
const k =
|
||||||
(large_arc_flag == sweep_flag ? -1 : 1) *
|
(large_arc_flag == sweep_flag ? -1 : 1) *
|
||||||
Math.sqrt(
|
Math.sqrt(
|
||||||
Math.abs(
|
Math.abs(
|
||||||
@ -786,11 +804,11 @@ const a2c = (
|
|||||||
cx = recursive[2];
|
cx = recursive[2];
|
||||||
cy = recursive[3];
|
cy = recursive[3];
|
||||||
}
|
}
|
||||||
var df = f2 - f1;
|
let df = f2 - f1;
|
||||||
if (Math.abs(df) > _120) {
|
if (Math.abs(df) > _120) {
|
||||||
var f2old = f2,
|
const f2old = f2;
|
||||||
x2old = x2,
|
const x2old = x2;
|
||||||
y2old = y2;
|
const y2old = y2;
|
||||||
f2 = f1 + _120 * (sweep_flag && f2 > f1 ? 1 : -1);
|
f2 = f1 + _120 * (sweep_flag && f2 > f1 ? 1 : -1);
|
||||||
x2 = cx + rx * Math.cos(f2);
|
x2 = cx + rx * Math.cos(f2);
|
||||||
y2 = cy + ry * Math.sin(f2);
|
y2 = cy + ry * Math.sin(f2);
|
||||||
@ -802,27 +820,27 @@ const a2c = (
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
df = f2 - f1;
|
df = f2 - f1;
|
||||||
var c1 = Math.cos(f1),
|
const c1 = Math.cos(f1);
|
||||||
s1 = Math.sin(f1),
|
const s1 = Math.sin(f1);
|
||||||
c2 = Math.cos(f2),
|
const c2 = Math.cos(f2);
|
||||||
s2 = Math.sin(f2),
|
const s2 = Math.sin(f2);
|
||||||
t = Math.tan(df / 4),
|
const t = Math.tan(df / 4);
|
||||||
hx = (4 / 3) * rx * t,
|
const hx = (4 / 3) * rx * t;
|
||||||
hy = (4 / 3) * ry * t,
|
const hy = (4 / 3) * ry * t;
|
||||||
m = [
|
const m = [
|
||||||
-hx * s1,
|
-hx * s1,
|
||||||
hy * c1,
|
hy * c1,
|
||||||
x2 + hx * s2 - x1,
|
x2 + hx * s2 - x1,
|
||||||
y2 - hy * c2 - y1,
|
y2 - hy * c2 - y1,
|
||||||
x2 - x1,
|
x2 - x1,
|
||||||
y2 - y1,
|
y2 - y1,
|
||||||
];
|
];
|
||||||
if (recursive) {
|
if (recursive) {
|
||||||
return m.concat(res);
|
return m.concat(res);
|
||||||
} else {
|
} else {
|
||||||
res = m.concat(res);
|
res = m.concat(res);
|
||||||
var newres = [];
|
const newres = [];
|
||||||
for (var i = 0, n = res.length; i < n; i++) {
|
for (let i = 0, n = res.length; i < n; i++) {
|
||||||
newres[i] =
|
newres[i] =
|
||||||
i % 2
|
i % 2
|
||||||
? rotateY(res[i - 1], res[i], rad)
|
? rotateY(res[i - 1], res[i], rad)
|
||||||
|
@ -514,10 +514,10 @@ const transformToMatrix = (transform) => {
|
|||||||
];
|
];
|
||||||
case 'rotate':
|
case 'rotate':
|
||||||
// [cos(a), sin(a), -sin(a), cos(a), x, y]
|
// [cos(a), sin(a), -sin(a), cos(a), x, y]
|
||||||
var cos = mth.cos(transform.data[0]),
|
var cos = mth.cos(transform.data[0]);
|
||||||
sin = mth.sin(transform.data[0]),
|
var sin = mth.sin(transform.data[0]);
|
||||||
cx = transform.data[1] || 0,
|
var cx = transform.data[1] || 0;
|
||||||
cy = transform.data[2] || 0;
|
var cy = transform.data[2] || 0;
|
||||||
return [
|
return [
|
||||||
cos,
|
cos,
|
||||||
sin,
|
sin,
|
||||||
@ -719,13 +719,13 @@ const round = (data) => {
|
|||||||
*/
|
*/
|
||||||
const smartRound = (precision, data) => {
|
const smartRound = (precision, data) => {
|
||||||
for (
|
for (
|
||||||
var i = data.length,
|
let i = data.length,
|
||||||
tolerance = +Math.pow(0.1, precision).toFixed(precision);
|
tolerance = +Math.pow(0.1, precision).toFixed(precision);
|
||||||
i--;
|
i--;
|
||||||
|
|
||||||
) {
|
) {
|
||||||
if (toFixed(data[i], precision) !== data[i]) {
|
if (toFixed(data[i], precision) !== data[i]) {
|
||||||
var rounded = +data[i].toFixed(precision - 1);
|
const rounded = +data[i].toFixed(precision - 1);
|
||||||
data[i] =
|
data[i] =
|
||||||
+Math.abs(rounded - data[i]).toFixed(precision + 1) >= tolerance
|
+Math.abs(rounded - data[i]).toFixed(precision + 1) >= tolerance
|
||||||
? +data[i].toFixed(precision)
|
? +data[i].toFixed(precision)
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
export const name = 'addAttributesToSVGElement';
|
export const name = 'addAttributesToSVGElement';
|
||||||
export const description = 'adds attributes to an outer <svg> element';
|
export const description = 'adds attributes to an outer <svg> element';
|
||||||
|
|
||||||
var ENOCLS = `Error in plugin "addAttributesToSVGElement": absent parameters.
|
const ENOCLS = `Error in plugin "addAttributesToSVGElement": absent parameters.
|
||||||
It should have a list of "attributes" or one "attribute".
|
It should have a list of "attributes" or one "attribute".
|
||||||
Config example:
|
Config example:
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
export const name = 'addClassesToSVGElement';
|
export const name = 'addClassesToSVGElement';
|
||||||
export const description = 'adds classnames to an outer <svg> element';
|
export const description = 'adds classnames to an outer <svg> element';
|
||||||
|
|
||||||
var ENOCLS = `Error in plugin "addClassesToSVGElement": absent parameters.
|
const ENOCLS = `Error in plugin "addClassesToSVGElement": absent parameters.
|
||||||
It should have a list of classes in "classNames" or one "className".
|
It should have a list of classes in "classNames" or one "className".
|
||||||
Config example:
|
Config example:
|
||||||
|
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
import { path2js } from './_path.js';
|
import { path2js } from './_path.js';
|
||||||
import {
|
import {
|
||||||
transformsMultiply,
|
|
||||||
transform2js,
|
transform2js,
|
||||||
transformArc,
|
transformArc,
|
||||||
|
transformsMultiply,
|
||||||
} from './_transforms.js';
|
} from './_transforms.js';
|
||||||
import { referencesProps, attrsGroupsDefaults } from './_collections.js';
|
import { attrsGroupsDefaults, referencesProps } from './_collections.js';
|
||||||
import { collectStylesheet, computeStyle } from '../lib/style.js';
|
import { collectStylesheet, computeStyle } from '../lib/style.js';
|
||||||
|
|
||||||
import { removeLeadingZero, includesUrlReference } from '../lib/svgo/tools.js';
|
import { includesUrlReference, removeLeadingZero } from '../lib/svgo/tools.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {import('../lib/types.js').PathDataItem} PathDataItem
|
* @typedef {import('../lib/types.js').PathDataItem} PathDataItem
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { visitSkip } from '../lib/xast.js';
|
import { visitSkip } from '../lib/xast.js';
|
||||||
import { hasScripts, findReferences } from '../lib/svgo/tools.js';
|
import { findReferences, hasScripts } from '../lib/svgo/tools.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {import('../lib/types.js').XastElement} XastElement
|
* @typedef {import('../lib/types.js').XastElement} XastElement
|
||||||
@ -224,7 +224,7 @@ export const fn = (_root, params) => {
|
|||||||
// replace referenced IDs with the minified ones
|
// replace referenced IDs with the minified ones
|
||||||
if (minify && isIdPreserved(id) === false) {
|
if (minify && isIdPreserved(id) === false) {
|
||||||
/** @type {?string} */
|
/** @type {?string} */
|
||||||
let currentIdString = null;
|
let currentIdString;
|
||||||
do {
|
do {
|
||||||
currentId = generateId(currentId);
|
currentId = generateId(currentId);
|
||||||
currentIdString = getIdString(currentId);
|
currentIdString = getIdString(currentId);
|
||||||
|
@ -64,7 +64,7 @@ export const fn = (_root, params) => {
|
|||||||
// round it to the fixed precision
|
// round it to the fixed precision
|
||||||
let num = Number(Number(match[1]).toFixed(floatPrecision));
|
let num = Number(Number(match[1]).toFixed(floatPrecision));
|
||||||
/** @type {any} */
|
/** @type {any} */
|
||||||
let matchedUnit = match[3] || '';
|
const matchedUnit = match[3] || '';
|
||||||
/** @type {'' | keyof typeof absoluteLengths} */
|
/** @type {'' | keyof typeof absoluteLengths} */
|
||||||
let units = matchedUnit;
|
let units = matchedUnit;
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ import { removeLeadingZero } from '../lib/svgo/tools.js';
|
|||||||
|
|
||||||
export const name = 'cleanupNumericValues';
|
export const name = 'cleanupNumericValues';
|
||||||
export const description =
|
export const description =
|
||||||
'rounds numeric values to the fixed precision, removes default ‘px’ units';
|
'rounds numeric values to the fixed precision, removes default "px" units';
|
||||||
|
|
||||||
const regNumericValues =
|
const regNumericValues =
|
||||||
/^([-+]?\d*\.?\d+([eE][-+]?\d+)?)(px|pt|pc|mm|cm|m|in|ft|em|ex|%)?$/;
|
/^([-+]?\d*\.?\d+([eE][-+]?\d+)?)(px|pt|pc|mm|cm|m|in|ft|em|ex|%)?$/;
|
||||||
@ -26,8 +26,7 @@ const absoluteLengths = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Round numeric values to the fixed precision,
|
* Round numeric values to the fixed precision, remove default 'px' units.
|
||||||
* remove default 'px' units.
|
|
||||||
*
|
*
|
||||||
* @author Kir Belevich
|
* @author Kir Belevich
|
||||||
*
|
*
|
||||||
@ -69,7 +68,7 @@ export const fn = (_root, params) => {
|
|||||||
// round it to the fixed precision
|
// round it to the fixed precision
|
||||||
let num = Number(Number(match[1]).toFixed(floatPrecision));
|
let num = Number(Number(match[1]).toFixed(floatPrecision));
|
||||||
/** @type {any} */
|
/** @type {any} */
|
||||||
let matchedUnit = match[3] || '';
|
const matchedUnit = match[3] || '';
|
||||||
/** @type {'' | keyof typeof absoluteLengths} */
|
/** @type {'' | keyof typeof absoluteLengths} */
|
||||||
let units = matchedUnit;
|
let units = matchedUnit;
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { computeStyle, collectStylesheet } from '../lib/style.js';
|
import { collectStylesheet, computeStyle } from '../lib/style.js';
|
||||||
import { inheritableAttrs, elemsGroups } from './_collections.js';
|
import { elemsGroups, inheritableAttrs } from './_collections.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {import('../lib/types.js').Plugin} Plugin
|
* @typedef {import('../lib/types.js').Plugin} Plugin
|
||||||
|
@ -121,9 +121,9 @@ export const fn = (_root, params) => {
|
|||||||
|
|
||||||
// convert rgb() to long hex
|
// convert rgb() to long hex
|
||||||
if (rgb2hex) {
|
if (rgb2hex) {
|
||||||
let match = val.match(regRGB);
|
const match = val.match(regRGB);
|
||||||
if (match != null) {
|
if (match != null) {
|
||||||
let nums = match.slice(1, 4).map((m) => {
|
const nums = match.slice(1, 4).map((m) => {
|
||||||
let n;
|
let n;
|
||||||
if (m.indexOf('%') > -1) {
|
if (m.indexOf('%') > -1) {
|
||||||
n = Math.round(parseFloat(m) * 2.55);
|
n = Math.round(parseFloat(m) * 2.55);
|
||||||
@ -146,7 +146,7 @@ export const fn = (_root, params) => {
|
|||||||
|
|
||||||
// convert long hex to short hex
|
// convert long hex to short hex
|
||||||
if (shorthex) {
|
if (shorthex) {
|
||||||
let match = regHEX.exec(val);
|
const match = regHEX.exec(val);
|
||||||
if (match != null) {
|
if (match != null) {
|
||||||
val = '#' + match[0][1] + match[0][3] + match[0][5];
|
val = '#' + match[0][1] + match[0][3] + match[0][5];
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import { attrsGroupsDefaults, colorsProps } from './_collections.js';
|
import { attrsGroupsDefaults, colorsProps } from './_collections.js';
|
||||||
import {
|
import {
|
||||||
detachNodeFromParent,
|
detachNodeFromParent,
|
||||||
querySelectorAll,
|
|
||||||
querySelector,
|
querySelector,
|
||||||
|
querySelectorAll,
|
||||||
} from '../lib/xast.js';
|
} from '../lib/xast.js';
|
||||||
import { computeStyle, collectStylesheet } from '../lib/style.js';
|
import { collectStylesheet, computeStyle } from '../lib/style.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {import('../lib/types.js').Plugin} Plugin
|
* @typedef {import('../lib/types.js').Plugin} Plugin
|
||||||
@ -64,7 +64,7 @@ export const fn = (root) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const href = node.attributes['xlink:href'] || node.attributes['href'];
|
const href = node.attributes['xlink:href'] || node.attributes['href'];
|
||||||
let effectiveNode =
|
const effectiveNode =
|
||||||
stops.length === 0 && href != null && href.startsWith('#')
|
stops.length === 0 && href != null && href.startsWith('#')
|
||||||
? querySelector(root, href)
|
? querySelector(root, href)
|
||||||
: node;
|
: node;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { path2js, js2path } from './_path.js';
|
import { js2path, path2js } from './_path.js';
|
||||||
import { pathElems } from './_collections.js';
|
import { pathElems } from './_collections.js';
|
||||||
import { applyTransforms } from './applyTransforms.js';
|
import { applyTransforms } from './applyTransforms.js';
|
||||||
import { collectStylesheet, computeStyle } from '../lib/style.js';
|
import { collectStylesheet, computeStyle } from '../lib/style.js';
|
||||||
@ -217,8 +217,8 @@ export const fn = (root, params) => {
|
|||||||
* @returns {PathDataItem[]}
|
* @returns {PathDataItem[]}
|
||||||
*/
|
*/
|
||||||
const convertToRelative = (pathData) => {
|
const convertToRelative = (pathData) => {
|
||||||
let start = [0, 0];
|
const start = [0, 0];
|
||||||
let cursor = [0, 0];
|
const cursor = [0, 0];
|
||||||
let prevCoords = [0, 0];
|
let prevCoords = [0, 0];
|
||||||
|
|
||||||
for (let i = 0; i < pathData.length; i += 1) {
|
for (let i = 0; i < pathData.length; i += 1) {
|
||||||
@ -413,8 +413,8 @@ function filters(
|
|||||||
let next = path[index + 1];
|
let next = path[index + 1];
|
||||||
|
|
||||||
if (command !== 'Z' && command !== 'z') {
|
if (command !== 'Z' && command !== 'z') {
|
||||||
var sdata = data,
|
let sdata = data;
|
||||||
circle;
|
let circle;
|
||||||
|
|
||||||
if (command === 's') {
|
if (command === 's') {
|
||||||
sdata = [0, 0].concat(data);
|
sdata = [0, 0].concat(data);
|
||||||
@ -434,31 +434,31 @@ function filters(
|
|||||||
isConvex(sdata) &&
|
isConvex(sdata) &&
|
||||||
(circle = findCircle(sdata))
|
(circle = findCircle(sdata))
|
||||||
) {
|
) {
|
||||||
var r = roundData([circle.radius])[0],
|
const r = roundData([circle.radius])[0];
|
||||||
angle = findArcAngle(sdata, circle),
|
let angle = findArcAngle(sdata, circle);
|
||||||
sweep = sdata[5] * sdata[0] - sdata[4] * sdata[1] > 0 ? 1 : 0,
|
const sweep = sdata[5] * sdata[0] - sdata[4] * sdata[1] > 0 ? 1 : 0;
|
||||||
/** @type {PathDataItem} */
|
/** @type {PathDataItem} */
|
||||||
arc = {
|
let arc = {
|
||||||
command: 'a',
|
command: 'a',
|
||||||
args: [r, r, 0, 0, sweep, sdata[4], sdata[5]],
|
args: [r, r, 0, 0, sweep, sdata[4], sdata[5]],
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
coords: item.coords.slice(),
|
coords: item.coords.slice(),
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
base: item.base,
|
base: item.base,
|
||||||
},
|
};
|
||||||
/** @type {PathDataItem[]} */
|
/** @type {PathDataItem[]} */
|
||||||
output = [arc],
|
const output = [arc];
|
||||||
// relative coordinates to adjust the found circle
|
// relative coordinates to adjust the found circle
|
||||||
/** @type {Point} */
|
/** @type {Point} */
|
||||||
relCenter = [
|
const relCenter = [
|
||||||
circle.center[0] - sdata[4],
|
circle.center[0] - sdata[4],
|
||||||
circle.center[1] - sdata[5],
|
circle.center[1] - sdata[5],
|
||||||
],
|
];
|
||||||
relCircle = { center: relCenter, radius: circle.radius },
|
const relCircle = { center: relCenter, radius: circle.radius };
|
||||||
arcCurves = [item],
|
const arcCurves = [item];
|
||||||
hasPrev = 0,
|
let hasPrev = 0;
|
||||||
suffix = '',
|
let suffix = '';
|
||||||
nextLonghand;
|
let nextLonghand;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
(prev.command == 'c' &&
|
(prev.command == 'c' &&
|
||||||
@ -473,8 +473,8 @@ function filters(
|
|||||||
arc.args[5] = arc.coords[0] - arc.base[0];
|
arc.args[5] = arc.coords[0] - arc.base[0];
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
arc.args[6] = arc.coords[1] - arc.base[1];
|
arc.args[6] = arc.coords[1] - arc.base[1];
|
||||||
var prevData = prev.command == 'a' ? prev.sdata : prev.args;
|
const prevData = prev.command == 'a' ? prev.sdata : prev.args;
|
||||||
var prevAngle = findArcAngle(prevData, {
|
const prevAngle = findArcAngle(prevData, {
|
||||||
center: [
|
center: [
|
||||||
prevData[4] + circle.center[0],
|
prevData[4] + circle.center[0],
|
||||||
prevData[5] + circle.center[1],
|
prevData[5] + circle.center[1],
|
||||||
@ -482,7 +482,9 @@ function filters(
|
|||||||
radius: circle.radius,
|
radius: circle.radius,
|
||||||
});
|
});
|
||||||
angle += prevAngle;
|
angle += prevAngle;
|
||||||
if (angle > Math.PI) arc.args[3] = 1;
|
if (angle > Math.PI) {
|
||||||
|
arc.args[3] = 1;
|
||||||
|
}
|
||||||
hasPrev = 1;
|
hasPrev = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -492,7 +494,7 @@ function filters(
|
|||||||
(next = path[++j]) && (next.command === 'c' || next.command === 's');
|
(next = path[++j]) && (next.command === 'c' || next.command === 's');
|
||||||
|
|
||||||
) {
|
) {
|
||||||
var nextData = next.args;
|
let nextData = next.args;
|
||||||
if (next.command == 's') {
|
if (next.command == 's') {
|
||||||
nextLonghand = makeLonghand(
|
nextLonghand = makeLonghand(
|
||||||
{ command: 's', args: next.args.slice() },
|
{ command: 's', args: next.args.slice() },
|
||||||
@ -504,8 +506,12 @@ function filters(
|
|||||||
}
|
}
|
||||||
if (isConvex(nextData) && isArc(nextData, relCircle)) {
|
if (isConvex(nextData) && isArc(nextData, relCircle)) {
|
||||||
angle += findArcAngle(nextData, relCircle);
|
angle += findArcAngle(nextData, relCircle);
|
||||||
if (angle - 2 * Math.PI > 1e-3) break; // more than 360°
|
if (angle - 2 * Math.PI > 1e-3) {
|
||||||
if (angle > Math.PI) arc.args[3] = 1;
|
break;
|
||||||
|
} // more than 360°
|
||||||
|
if (angle > Math.PI) {
|
||||||
|
arc.args[3] = 1;
|
||||||
|
}
|
||||||
arcCurves.push(next);
|
arcCurves.push(next);
|
||||||
if (2 * Math.PI - angle > 1e-3) {
|
if (2 * Math.PI - angle > 1e-3) {
|
||||||
// less than 360°
|
// less than 360°
|
||||||
@ -550,7 +556,9 @@ function filters(
|
|||||||
}
|
}
|
||||||
relCenter[0] -= nextData[4];
|
relCenter[0] -= nextData[4];
|
||||||
relCenter[1] -= nextData[5];
|
relCenter[1] -= nextData[5];
|
||||||
} else break;
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((stringify(output) + suffix).length < stringify(arcCurves).length) {
|
if ((stringify(output) + suffix).length < stringify(arcCurves).length) {
|
||||||
@ -558,7 +566,7 @@ function filters(
|
|||||||
makeLonghand(path[j], path[j - 1].args);
|
makeLonghand(path[j], path[j - 1].args);
|
||||||
}
|
}
|
||||||
if (hasPrev) {
|
if (hasPrev) {
|
||||||
var prevArc = output.shift();
|
const prevArc = output.shift();
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
roundData(prevArc.args);
|
roundData(prevArc.args);
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
@ -580,7 +588,9 @@ function filters(
|
|||||||
// filter out consumed next items
|
// filter out consumed next items
|
||||||
path.splice(index + 1, arcCurves.length - 1 - hasPrev, ...output);
|
path.splice(index + 1, arcCurves.length - 1 - hasPrev, ...output);
|
||||||
}
|
}
|
||||||
if (!arc) return false;
|
if (!arc) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
command = 'a';
|
command = 'a';
|
||||||
data = arc.args;
|
data = arc.args;
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
@ -600,7 +610,7 @@ function filters(
|
|||||||
command === 's' ||
|
command === 's' ||
|
||||||
command === 'c'
|
command === 'c'
|
||||||
) {
|
) {
|
||||||
for (var i = data.length; i--; ) {
|
for (let i = data.length; i--; ) {
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
data[i] += item.base[i % 2] - relSubpoint[i % 2];
|
data[i] += item.base[i % 2] - relSubpoint[i % 2];
|
||||||
}
|
}
|
||||||
@ -618,9 +628,11 @@ function filters(
|
|||||||
}
|
}
|
||||||
roundData(data);
|
roundData(data);
|
||||||
|
|
||||||
if (command == 'h') relSubpoint[0] += data[0];
|
if (command == 'h') {
|
||||||
else if (command == 'v') relSubpoint[1] += data[0];
|
relSubpoint[0] += data[0];
|
||||||
else {
|
} else if (command == 'v') {
|
||||||
|
relSubpoint[1] += data[0];
|
||||||
|
} else {
|
||||||
relSubpoint[0] += data[data.length - 2];
|
relSubpoint[0] += data[data.length - 2];
|
||||||
relSubpoint[1] += data[data.length - 1];
|
relSubpoint[1] += data[data.length - 1];
|
||||||
}
|
}
|
||||||
@ -656,11 +668,15 @@ function filters(
|
|||||||
(command === 'c' && isCurveStraightLine(data)) ||
|
(command === 'c' && isCurveStraightLine(data)) ||
|
||||||
(command === 's' && isCurveStraightLine(sdata))
|
(command === 's' && isCurveStraightLine(sdata))
|
||||||
) {
|
) {
|
||||||
if (next && next.command == 's') makeLonghand(next, data); // fix up next curve
|
if (next && next.command == 's') {
|
||||||
|
makeLonghand(next, data);
|
||||||
|
} // fix up next curve
|
||||||
command = 'l';
|
command = 'l';
|
||||||
data = data.slice(-2);
|
data = data.slice(-2);
|
||||||
} else if (command === 'q' && isCurveStraightLine(data)) {
|
} else if (command === 'q' && isCurveStraightLine(data)) {
|
||||||
if (next && next.command == 't') makeLonghand(next, data); // fix up next curve
|
if (next && next.command == 't') {
|
||||||
|
makeLonghand(next, data);
|
||||||
|
} // fix up next curve
|
||||||
command = 'l';
|
command = 'l';
|
||||||
data = data.slice(-2);
|
data = data.slice(-2);
|
||||||
} else if (
|
} else if (
|
||||||
@ -708,12 +724,14 @@ function filters(
|
|||||||
y1 + y2 - item.base[1],
|
y1 + y2 - item.base[1],
|
||||||
);
|
);
|
||||||
roundData(newData);
|
roundData(newData);
|
||||||
const originalLength = cleanupOutData(data, params).length,
|
const originalLength = cleanupOutData(data, params).length;
|
||||||
newLength = cleanupOutData(newData, params).length;
|
const newLength = cleanupOutData(newData, params).length;
|
||||||
if (newLength < originalLength) {
|
if (newLength < originalLength) {
|
||||||
command = 'q';
|
command = 'q';
|
||||||
data = newData;
|
data = newData;
|
||||||
if (next && next.command == 's') makeLonghand(next, data); // fix up next curve
|
if (next && next.command == 's') {
|
||||||
|
makeLonghand(next, data);
|
||||||
|
} // fix up next curve
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -877,7 +895,9 @@ function filters(
|
|||||||
// z resets coordinates
|
// z resets coordinates
|
||||||
relSubpoint[0] = pathBase[0];
|
relSubpoint[0] = pathBase[0];
|
||||||
relSubpoint[1] = pathBase[1];
|
relSubpoint[1] = pathBase[1];
|
||||||
if (prev.command === 'Z' || prev.command === 'z') return false;
|
if (prev.command === 'Z' || prev.command === 'z') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
(command === 'Z' || command === 'z') &&
|
(command === 'Z' || command === 'z') &&
|
||||||
@ -887,8 +907,9 @@ function filters(
|
|||||||
Math.abs(item.base[0] - item.coords[0]) < error / 10 &&
|
Math.abs(item.base[0] - item.coords[0]) < error / 10 &&
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
Math.abs(item.base[1] - item.coords[1]) < error / 10
|
Math.abs(item.base[1] - item.coords[1]) < error / 10
|
||||||
)
|
) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (command === 'q') {
|
if (command === 'q') {
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
@ -919,19 +940,21 @@ function filters(
|
|||||||
* @returns {PathDataItem[]}
|
* @returns {PathDataItem[]}
|
||||||
*/
|
*/
|
||||||
function convertToMixed(path, params) {
|
function convertToMixed(path, params) {
|
||||||
var prev = path[0];
|
let prev = path[0];
|
||||||
|
|
||||||
path = path.filter(function (item, index) {
|
path = path.filter(function (item, index) {
|
||||||
if (index == 0) return true;
|
if (index == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
if (item.command === 'Z' || item.command === 'z') {
|
if (item.command === 'Z' || item.command === 'z') {
|
||||||
prev = item;
|
prev = item;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
var command = item.command,
|
const command = item.command;
|
||||||
data = item.args,
|
const data = item.args;
|
||||||
adata = data.slice(),
|
const adata = data.slice();
|
||||||
rdata = data.slice();
|
const rdata = data.slice();
|
||||||
|
|
||||||
if (
|
if (
|
||||||
command === 'm' ||
|
command === 'm' ||
|
||||||
@ -941,7 +964,7 @@ function convertToMixed(path, params) {
|
|||||||
command === 's' ||
|
command === 's' ||
|
||||||
command === 'c'
|
command === 'c'
|
||||||
) {
|
) {
|
||||||
for (var i = adata.length; i--; ) {
|
for (let i = adata.length; i--; ) {
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
adata[i] += item.base[i % 2];
|
adata[i] += item.base[i % 2];
|
||||||
}
|
}
|
||||||
@ -961,8 +984,8 @@ function convertToMixed(path, params) {
|
|||||||
roundData(adata);
|
roundData(adata);
|
||||||
roundData(rdata);
|
roundData(rdata);
|
||||||
|
|
||||||
var absoluteDataStr = cleanupOutData(adata, params),
|
const absoluteDataStr = cleanupOutData(adata, params);
|
||||||
relativeDataStr = cleanupOutData(rdata, params);
|
const relativeDataStr = cleanupOutData(rdata, params);
|
||||||
|
|
||||||
// Convert to absolute coordinates if it's shorter or forceAbsolutePath is true.
|
// Convert to absolute coordinates if it's shorter or forceAbsolutePath is true.
|
||||||
// v-20 -> V0
|
// v-20 -> V0
|
||||||
@ -1002,7 +1025,7 @@ function convertToMixed(path, params) {
|
|||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
function isConvex(data) {
|
function isConvex(data) {
|
||||||
var center = getIntersection([
|
const center = getIntersection([
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
data[2],
|
data[2],
|
||||||
@ -1030,19 +1053,21 @@ function isConvex(data) {
|
|||||||
*/
|
*/
|
||||||
function getIntersection(coords) {
|
function getIntersection(coords) {
|
||||||
// Prev line equation parameters.
|
// Prev line equation parameters.
|
||||||
var a1 = coords[1] - coords[3], // y1 - y2
|
const a1 = coords[1] - coords[3]; // y1 - y2
|
||||||
b1 = coords[2] - coords[0], // x2 - x1
|
const b1 = coords[2] - coords[0]; // x2 - x1
|
||||||
c1 = coords[0] * coords[3] - coords[2] * coords[1], // x1 * y2 - x2 * y1
|
const c1 = coords[0] * coords[3] - coords[2] * coords[1]; // x1 * y2 - x2 * y1
|
||||||
// Next line equation parameters
|
// Next line equation parameters
|
||||||
a2 = coords[5] - coords[7], // y1 - y2
|
const a2 = coords[5] - coords[7]; // y1 - y2
|
||||||
b2 = coords[6] - coords[4], // x2 - x1
|
const b2 = coords[6] - coords[4]; // x2 - x1
|
||||||
c2 = coords[4] * coords[7] - coords[5] * coords[6], // x1 * y2 - x2 * y1
|
const c2 = coords[4] * coords[7] - coords[5] * coords[6]; // x1 * y2 - x2 * y1
|
||||||
denom = a1 * b2 - a2 * b1;
|
const denom = a1 * b2 - a2 * b1;
|
||||||
|
|
||||||
if (!denom) return; // parallel lines haven't an intersection
|
if (!denom) {
|
||||||
|
return;
|
||||||
|
} // parallel lines haven't an intersection
|
||||||
|
|
||||||
/** @type {Point} */
|
/** @type {Point} */
|
||||||
var cross = [(b1 * c2 - b2 * c1) / denom, (a1 * c2 - a2 * c1) / -denom];
|
const cross = [(b1 * c2 - b2 * c1) / denom, (a1 * c2 - a2 * c1) / -denom];
|
||||||
if (
|
if (
|
||||||
!isNaN(cross[0]) &&
|
!isNaN(cross[0]) &&
|
||||||
!isNaN(cross[1]) &&
|
!isNaN(cross[1]) &&
|
||||||
@ -1083,7 +1108,7 @@ function strongRound(data) {
|
|||||||
* @returns {number[]}
|
* @returns {number[]}
|
||||||
*/
|
*/
|
||||||
function round(data) {
|
function round(data) {
|
||||||
for (var i = data.length; i-- > 0; ) {
|
for (let i = data.length; i-- > 0; ) {
|
||||||
data[i] = Math.round(data[i]);
|
data[i] = Math.round(data[i]);
|
||||||
}
|
}
|
||||||
return data;
|
return data;
|
||||||
@ -1098,17 +1123,20 @@ function round(data) {
|
|||||||
*/
|
*/
|
||||||
function isCurveStraightLine(data) {
|
function isCurveStraightLine(data) {
|
||||||
// Get line equation a·x + b·y + c = 0 coefficients a, b (c = 0) by start and end points.
|
// Get line equation a·x + b·y + c = 0 coefficients a, b (c = 0) by start and end points.
|
||||||
var i = data.length - 2,
|
let i = data.length - 2;
|
||||||
a = -data[i + 1], // y1 − y2 (y1 = 0)
|
const a = -data[i + 1]; // y1 − y2 (y1 = 0)
|
||||||
b = data[i], // x2 − x1 (x1 = 0)
|
const b = data[i]; // x2 − x1 (x1 = 0)
|
||||||
d = 1 / (a * a + b * b); // same part for all points
|
const d = 1 / (a * a + b * b); // same part for all points
|
||||||
|
|
||||||
if (i <= 1 || !isFinite(d)) return false; // curve that ends at start point isn't the case
|
if (i <= 1 || !isFinite(d)) {
|
||||||
|
return false;
|
||||||
|
} // curve that ends at start point isn't the case
|
||||||
|
|
||||||
// Distance from point (x0, y0) to the line is sqrt((c − a·x0 − b·y0)² / (a² + b²))
|
// Distance from point (x0, y0) to the line is sqrt((c − a·x0 − b·y0)² / (a² + b²))
|
||||||
while ((i -= 2) >= 0) {
|
while ((i -= 2) >= 0) {
|
||||||
if (Math.sqrt(Math.pow(a * data[i] + b * data[i + 1], 2) * d) > error)
|
if (Math.sqrt(Math.pow(a * data[i] + b * data[i + 1], 2) * d) > error) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -1122,11 +1150,17 @@ function isCurveStraightLine(data) {
|
|||||||
* @returns {number | undefined}
|
* @returns {number | undefined}
|
||||||
*/
|
*/
|
||||||
function calculateSagitta(data) {
|
function calculateSagitta(data) {
|
||||||
if (data[3] === 1) return undefined;
|
if (data[3] === 1) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
const [rx, ry] = data;
|
const [rx, ry] = data;
|
||||||
if (Math.abs(rx - ry) > error) return undefined;
|
if (Math.abs(rx - ry) > error) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
const chord = Math.hypot(data[5], data[6]);
|
const chord = Math.hypot(data[5], data[6]);
|
||||||
if (chord > rx * 2) return undefined;
|
if (chord > rx * 2) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
return rx - Math.sqrt(rx ** 2 - 0.25 * chord ** 2);
|
return rx - Math.sqrt(rx ** 2 - 0.25 * chord ** 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1185,10 +1219,10 @@ function reflectPoint(controlPoint, base) {
|
|||||||
* @returns {Point}
|
* @returns {Point}
|
||||||
*/
|
*/
|
||||||
function getCubicBezierPoint(curve, t) {
|
function getCubicBezierPoint(curve, t) {
|
||||||
var sqrT = t * t,
|
const sqrT = t * t;
|
||||||
cubT = sqrT * t,
|
const cubT = sqrT * t;
|
||||||
mt = 1 - t,
|
const mt = 1 - t;
|
||||||
sqrMt = mt * mt;
|
const sqrMt = mt * mt;
|
||||||
|
|
||||||
return [
|
return [
|
||||||
3 * sqrMt * t * curve[0] + 3 * mt * sqrT * curve[2] + cubT * curve[4],
|
3 * sqrMt * t * curve[0] + 3 * mt * sqrT * curve[2] + cubT * curve[4],
|
||||||
@ -1203,22 +1237,25 @@ function getCubicBezierPoint(curve, t) {
|
|||||||
* @returns {Circle | undefined}
|
* @returns {Circle | undefined}
|
||||||
*/
|
*/
|
||||||
function findCircle(curve) {
|
function findCircle(curve) {
|
||||||
var midPoint = getCubicBezierPoint(curve, 1 / 2),
|
const midPoint = getCubicBezierPoint(curve, 1 / 2);
|
||||||
m1 = [midPoint[0] / 2, midPoint[1] / 2],
|
const m1 = [midPoint[0] / 2, midPoint[1] / 2];
|
||||||
m2 = [(midPoint[0] + curve[4]) / 2, (midPoint[1] + curve[5]) / 2],
|
const m2 = [(midPoint[0] + curve[4]) / 2, (midPoint[1] + curve[5]) / 2];
|
||||||
center = getIntersection([
|
const center = getIntersection([
|
||||||
m1[0],
|
m1[0],
|
||||||
m1[1],
|
m1[1],
|
||||||
m1[0] + m1[1],
|
m1[0] + m1[1],
|
||||||
m1[1] - m1[0],
|
m1[1] - m1[0],
|
||||||
m2[0],
|
m2[0],
|
||||||
m2[1],
|
m2[1],
|
||||||
m2[0] + (m2[1] - midPoint[1]),
|
m2[0] + (m2[1] - midPoint[1]),
|
||||||
m2[1] - (m2[0] - midPoint[0]),
|
m2[1] - (m2[0] - midPoint[0]),
|
||||||
]),
|
]);
|
||||||
radius = center && getDistance([0, 0], center),
|
const radius = center && getDistance([0, 0], center);
|
||||||
|
const tolerance = Math.min(
|
||||||
|
arcThreshold * error,
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
tolerance = Math.min(arcThreshold * error, (arcTolerance * radius) / 100);
|
(arcTolerance * radius) / 100,
|
||||||
|
);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
center &&
|
center &&
|
||||||
@ -1232,9 +1269,10 @@ function findCircle(curve) {
|
|||||||
) <= tolerance
|
) <= tolerance
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
)
|
) {
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
return { center: center, radius: radius };
|
return { center: center, radius: radius };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1245,7 +1283,7 @@ function findCircle(curve) {
|
|||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
function isArc(curve, circle) {
|
function isArc(curve, circle) {
|
||||||
var tolerance = Math.min(
|
const tolerance = Math.min(
|
||||||
arcThreshold * error,
|
arcThreshold * error,
|
||||||
(arcTolerance * circle.radius) / 100,
|
(arcTolerance * circle.radius) / 100,
|
||||||
);
|
);
|
||||||
@ -1282,10 +1320,10 @@ function isArcPrev(curve, circle) {
|
|||||||
* @returns {number}
|
* @returns {number}
|
||||||
*/
|
*/
|
||||||
function findArcAngle(curve, relCircle) {
|
function findArcAngle(curve, relCircle) {
|
||||||
var x1 = -relCircle.center[0],
|
const x1 = -relCircle.center[0];
|
||||||
y1 = -relCircle.center[1],
|
const y1 = -relCircle.center[1];
|
||||||
x2 = curve[4] - relCircle.center[0],
|
const x2 = curve[4] - relCircle.center[0];
|
||||||
y2 = curve[5] - relCircle.center[1];
|
const y2 = curve[5] - relCircle.center[1];
|
||||||
|
|
||||||
return Math.acos(
|
return Math.acos(
|
||||||
(x1 * x2 + y1 * y2) / Math.sqrt((x1 * x1 + y1 * y1) * (x2 * x2 + y2 * y2)),
|
(x1 * x2 + y1 * y2) / Math.sqrt((x1 * x1 + y1 * y1) * (x2 * x2 + y2 * y2)),
|
||||||
@ -1301,7 +1339,7 @@ function findArcAngle(curve, relCircle) {
|
|||||||
*/
|
*/
|
||||||
function data2Path(params, pathData) {
|
function data2Path(params, pathData) {
|
||||||
return pathData.reduce(function (pathString, item) {
|
return pathData.reduce(function (pathString, item) {
|
||||||
var strData = '';
|
let strData = '';
|
||||||
if (item.args) {
|
if (item.args) {
|
||||||
strData = cleanupOutData(roundData(item.args.slice()), params);
|
strData = cleanupOutData(roundData(item.args.slice()), params);
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,9 @@ export const fn = (root, params) => {
|
|||||||
// Values like '100%' compute to NaN, thus running after
|
// Values like '100%' compute to NaN, thus running after
|
||||||
// cleanupNumericValues when 'px' units has already been removed.
|
// cleanupNumericValues when 'px' units has already been removed.
|
||||||
// TODO: Calculate sizes from % and non-px units if possible.
|
// TODO: Calculate sizes from % and non-px units if possible.
|
||||||
if (Number.isNaN(x - y + width - height)) return;
|
if (Number.isNaN(x - y + width - height)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
/** @type {PathDataItem[]} */
|
/** @type {PathDataItem[]} */
|
||||||
const pathData = [
|
const pathData = [
|
||||||
{ command: 'M', args: [x, y] },
|
{ command: 'M', args: [x, y] },
|
||||||
@ -69,7 +71,9 @@ export const fn = (root, params) => {
|
|||||||
const y1 = Number(node.attributes.y1 || '0');
|
const y1 = Number(node.attributes.y1 || '0');
|
||||||
const x2 = Number(node.attributes.x2 || '0');
|
const x2 = Number(node.attributes.x2 || '0');
|
||||||
const y2 = Number(node.attributes.y2 || '0');
|
const y2 = Number(node.attributes.y2 || '0');
|
||||||
if (Number.isNaN(x1 - y1 + x2 - y2)) return;
|
if (Number.isNaN(x1 - y1 + x2 - y2)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
/** @type {PathDataItem[]} */
|
/** @type {PathDataItem[]} */
|
||||||
const pathData = [
|
const pathData = [
|
||||||
{ command: 'M', args: [x1, y1] },
|
{ command: 'M', args: [x1, y1] },
|
||||||
|
@ -111,8 +111,8 @@ export const fn = (_root, params) => {
|
|||||||
if (styles.length) {
|
if (styles.length) {
|
||||||
styles = styles.filter(function (style) {
|
styles = styles.filter(function (style) {
|
||||||
if (style[0]) {
|
if (style[0]) {
|
||||||
var prop = style[0].toLowerCase(),
|
const prop = style[0].toLowerCase();
|
||||||
val = style[1];
|
let val = style[1];
|
||||||
|
|
||||||
if (rQuotedString.test(val)) {
|
if (rQuotedString.test(val)) {
|
||||||
val = val.slice(1, -1);
|
val = val.slice(1, -1);
|
||||||
|
@ -205,12 +205,12 @@ const floatDigits = (n) => {
|
|||||||
* @returns {TransformItem[]}
|
* @returns {TransformItem[]}
|
||||||
*/
|
*/
|
||||||
const convertToShorts = (transforms, params) => {
|
const convertToShorts = (transforms, params) => {
|
||||||
for (var i = 0; i < transforms.length; i++) {
|
for (let i = 0; i < transforms.length; i++) {
|
||||||
let transform = transforms[i];
|
let transform = transforms[i];
|
||||||
|
|
||||||
// convert matrix to the short aliases
|
// convert matrix to the short aliases
|
||||||
if (params.matrixToTransform && transform.name === 'matrix') {
|
if (params.matrixToTransform && transform.name === 'matrix') {
|
||||||
var decomposed = matrixToTransform(transform, params);
|
const decomposed = matrixToTransform(transform, params);
|
||||||
if (
|
if (
|
||||||
js2transform(decomposed, params).length <=
|
js2transform(decomposed, params).length <=
|
||||||
js2transform([transform], params).length
|
js2transform([transform], params).length
|
||||||
|
@ -2,9 +2,9 @@ import * as csstree from 'css-tree';
|
|||||||
import { syntax } from 'csso';
|
import { syntax } from 'csso';
|
||||||
import { attrsGroups, pseudoClasses } from './_collections.js';
|
import { attrsGroups, pseudoClasses } from './_collections.js';
|
||||||
import {
|
import {
|
||||||
visitSkip,
|
|
||||||
querySelectorAll,
|
|
||||||
detachNodeFromParent,
|
detachNodeFromParent,
|
||||||
|
querySelectorAll,
|
||||||
|
visitSkip,
|
||||||
} from '../lib/xast.js';
|
} from '../lib/xast.js';
|
||||||
import { compareSpecificity, includesAttrSelector } from '../lib/style.js';
|
import { compareSpecificity, includesAttrSelector } from '../lib/style.js';
|
||||||
|
|
||||||
@ -72,7 +72,7 @@ export const fn = (root, params) => {
|
|||||||
* matchedElements?: XastElement[]
|
* matchedElements?: XastElement[]
|
||||||
* }[]}
|
* }[]}
|
||||||
*/
|
*/
|
||||||
let selectors = [];
|
const selectors = [];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
element: {
|
element: {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { collectStylesheet, computeStyle } from '../lib/style.js';
|
import { collectStylesheet, computeStyle } from '../lib/style.js';
|
||||||
import { path2js, js2path, intersects } from './_path.js';
|
import { intersects, js2path, path2js } from './_path.js';
|
||||||
import { includesUrlReference } from '../lib/svgo/tools.js';
|
import { includesUrlReference } from '../lib/svgo/tools.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { visitSkip, detachNodeFromParent } from '../lib/xast.js';
|
import { detachNodeFromParent, visitSkip } from '../lib/xast.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {import('../lib/types.js').Plugin} Plugin
|
* @typedef {import('../lib/types.js').Plugin} Plugin
|
||||||
|
@ -164,7 +164,7 @@ export const fn = (_root, params, info) => {
|
|||||||
|
|
||||||
const cssText = child.value;
|
const cssText = child.value;
|
||||||
/** @type {?csstree.CssNode} */
|
/** @type {?csstree.CssNode} */
|
||||||
let cssAst = null;
|
let cssAst;
|
||||||
try {
|
try {
|
||||||
cssAst = csstree.parse(cssText, {
|
cssAst = csstree.parse(cssText, {
|
||||||
parseValue: true,
|
parseValue: true,
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
import { elemsGroups } from './_collections.js';
|
import { elemsGroups } from './_collections.js';
|
||||||
import {
|
import {
|
||||||
|
detachNodeFromParent,
|
||||||
|
querySelector,
|
||||||
visit,
|
visit,
|
||||||
visitSkip,
|
visitSkip,
|
||||||
querySelector,
|
|
||||||
detachNodeFromParent,
|
|
||||||
} from '../lib/xast.js';
|
} from '../lib/xast.js';
|
||||||
import { collectStylesheet, computeStyle } from '../lib/style.js';
|
import { collectStylesheet, computeStyle } from '../lib/style.js';
|
||||||
import { parsePathData } from '../lib/path.js';
|
import { parsePathData } from '../lib/path.js';
|
||||||
import { hasScripts, findReferences } from '../lib/svgo/tools.js';
|
import { findReferences, hasScripts } from '../lib/svgo/tools.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {import('../lib/types.js').XastChild} XastChild
|
* @typedef {import('../lib/types.js').XastChild} XastChild
|
||||||
@ -183,7 +183,9 @@ export const fn = (root, params) => {
|
|||||||
|
|
||||||
if (node.name === 'use') {
|
if (node.name === 'use') {
|
||||||
for (const attr of Object.keys(node.attributes)) {
|
for (const attr of Object.keys(node.attributes)) {
|
||||||
if (attr !== 'href' && !attr.endsWith(':href')) continue;
|
if (attr !== 'href' && !attr.endsWith(':href')) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
const value = node.attributes[attr];
|
const value = node.attributes[attr];
|
||||||
const id = value.slice(1);
|
const id = value.slice(1);
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import {
|
import {
|
||||||
inheritableAttrs,
|
|
||||||
attrsGroups,
|
attrsGroups,
|
||||||
|
inheritableAttrs,
|
||||||
presentationNonInheritableGroupAttrs,
|
presentationNonInheritableGroupAttrs,
|
||||||
} from './_collections.js';
|
} from './_collections.js';
|
||||||
|
|
||||||
@ -10,7 +10,7 @@ import {
|
|||||||
|
|
||||||
export const name = 'removeNonInheritableGroupAttrs';
|
export const name = 'removeNonInheritableGroupAttrs';
|
||||||
export const description =
|
export const description =
|
||||||
'removes non-inheritable group’s presentational attributes';
|
"removes non-inheritable group's presentational attributes";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove non-inheritable group's "presentation" attributes.
|
* Remove non-inheritable group's "presentation" attributes.
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { visitSkip, detachNodeFromParent } from '../lib/xast.js';
|
import { detachNodeFromParent, visitSkip } from '../lib/xast.js';
|
||||||
import { parsePathData } from '../lib/path.js';
|
import { parsePathData } from '../lib/path.js';
|
||||||
import { intersects } from './_path.js';
|
import { intersects } from './_path.js';
|
||||||
|
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
import {
|
import {
|
||||||
elems,
|
|
||||||
attrsGroups,
|
attrsGroups,
|
||||||
elemsGroups,
|
|
||||||
attrsGroupsDefaults,
|
attrsGroupsDefaults,
|
||||||
|
elems,
|
||||||
|
elemsGroups,
|
||||||
presentationNonInheritableGroupAttrs,
|
presentationNonInheritableGroupAttrs,
|
||||||
} from './_collections.js';
|
} from './_collections.js';
|
||||||
import { visitSkip, detachNodeFromParent } from '../lib/xast.js';
|
import { detachNodeFromParent, visitSkip } from '../lib/xast.js';
|
||||||
import { collectStylesheet, computeStyle } from '../lib/style.js';
|
import { collectStylesheet, computeStyle } from '../lib/style.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { visit, visitSkip, detachNodeFromParent } from '../lib/xast.js';
|
import { detachNodeFromParent, visit, visitSkip } from '../lib/xast.js';
|
||||||
import { collectStylesheet, computeStyle } from '../lib/style.js';
|
import { collectStylesheet, computeStyle } from '../lib/style.js';
|
||||||
import { hasScripts } from '../lib/svgo/tools.js';
|
import { hasScripts } from '../lib/svgo/tools.js';
|
||||||
import { elemsGroups } from './_collections.js';
|
import { elemsGroups } from './_collections.js';
|
||||||
|
@ -110,7 +110,7 @@ describe('coa', function () {
|
|||||||
tempFolder,
|
tempFolder,
|
||||||
'--quiet',
|
'--quiet',
|
||||||
]);
|
]);
|
||||||
let optimizedWeight = calcFolderSvgWeight(svgFolderPath);
|
const optimizedWeight = calcFolderSvgWeight(svgFolderPath);
|
||||||
expect(optimizedWeight).toBeLessThanOrEqual(initWeight);
|
expect(optimizedWeight).toBeLessThanOrEqual(initWeight);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ import fs from 'node:fs/promises';
|
|||||||
import path from 'path';
|
import path from 'path';
|
||||||
import { EOL } from 'os';
|
import { EOL } from 'os';
|
||||||
import { fileURLToPath } from 'url';
|
import { fileURLToPath } from 'url';
|
||||||
import { VERSION, optimize, builtinPlugins } from '../../lib/svgo.js';
|
import { VERSION, builtinPlugins, optimize } from '../../lib/svgo.js';
|
||||||
|
|
||||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||||
|
|
||||||
|
10
yarn.lock
10
yarn.lock
@ -3952,12 +3952,12 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"prettier@npm:^3.2.5":
|
"prettier@npm:^3.5.3":
|
||||||
version: 3.2.5
|
version: 3.5.3
|
||||||
resolution: "prettier@npm:3.2.5"
|
resolution: "prettier@npm:3.5.3"
|
||||||
bin:
|
bin:
|
||||||
prettier: bin/prettier.cjs
|
prettier: bin/prettier.cjs
|
||||||
checksum: 2ee4e1417572372afb7a13bb446b34f20f1bf1747db77cf6ccaf57a9be005f2f15c40f903d41a6b79eec3f57fff14d32a20fb6dee1f126da48908926fe43c311
|
checksum: 61e97bb8e71a95d8f9c71f1fd5229c9aaa9d1e184dedb12399f76aa802fb6fdc8954ecac9df25a7f82ee7311cf8ddbd06baf5507388fc98e5b44036cc6a88a1b
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
@ -4546,7 +4546,7 @@ __metadata:
|
|||||||
pixelmatch: ^7.1.0
|
pixelmatch: ^7.1.0
|
||||||
playwright: ^1.51.1
|
playwright: ^1.51.1
|
||||||
pngjs: ^7.0.0
|
pngjs: ^7.0.0
|
||||||
prettier: ^3.2.5
|
prettier: ^3.5.3
|
||||||
rimraf: ^5.0.7
|
rimraf: ^5.0.7
|
||||||
rollup: ^4.22.4
|
rollup: ^4.22.4
|
||||||
sax: ^1.4.1
|
sax: ^1.4.1
|
||||||
|
Reference in New Issue
Block a user