mirror of
https://github.com/svg/svgo.git
synced 2025-08-09 02:22:08 +03:00
Covert removeHiddenElems with types (#1532)
Covered removeHiddenElems plugin and big part of our code - path parser and stringifier - style manager
This commit is contained in:
76
lib/path.js
76
lib/path.js
@@ -1,5 +1,10 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @typedef {import('./types').PathDataItem} PathDataItem
|
||||
* @typedef {import('./types').PathDataCommand} PathDataCommand
|
||||
*/
|
||||
|
||||
// Based on https://www.w3.org/TR/SVG11/paths.html#PathDataBNF
|
||||
|
||||
const argsCountPerCommand = {
|
||||
@@ -26,14 +31,14 @@ const argsCountPerCommand = {
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} c
|
||||
* @type {(c: string) => c is PathDataCommand}
|
||||
*/
|
||||
const isCommand = (c) => {
|
||||
return c in argsCountPerCommand;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} c
|
||||
* @type {(c: string) => boolean}
|
||||
*/
|
||||
const isWsp = (c) => {
|
||||
const codePoint = c.codePointAt(0);
|
||||
@@ -46,7 +51,7 @@ const isWsp = (c) => {
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} c
|
||||
* @type {(c: string) => boolean}
|
||||
*/
|
||||
const isDigit = (c) => {
|
||||
const codePoint = c.codePointAt(0);
|
||||
@@ -61,9 +66,7 @@ const isDigit = (c) => {
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {string} string
|
||||
* @param {number} cursor
|
||||
* @return {[number, number | null]}
|
||||
* @type {(string: string, cursor: number) => [number, number | null]}
|
||||
*/
|
||||
const readNumber = (string, cursor) => {
|
||||
let i = cursor;
|
||||
@@ -130,10 +133,16 @@ const readNumber = (string, cursor) => {
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} string
|
||||
* @type {(string: string) => Array<PathDataItem>}
|
||||
*/
|
||||
const parsePathData = (string) => {
|
||||
/**
|
||||
* @type {Array<PathDataItem>}
|
||||
*/
|
||||
const pathData = [];
|
||||
/**
|
||||
* @type {null | PathDataCommand}
|
||||
*/
|
||||
let command = null;
|
||||
let args = /** @type {number[]} */ ([]);
|
||||
let argsCount = 0;
|
||||
@@ -232,15 +241,9 @@ const parsePathData = (string) => {
|
||||
exports.parsePathData = parsePathData;
|
||||
|
||||
/**
|
||||
* @typedef {{
|
||||
* number: number;
|
||||
* precision?: number;
|
||||
* }} StringifyNumberOptions
|
||||
* @type {(number: number, precision?: number) => string}
|
||||
*/
|
||||
/**
|
||||
* @param {StringifyNumberOptions} param
|
||||
*/
|
||||
const stringifyNumber = ({ number, precision }) => {
|
||||
const stringifyNumber = (number, precision) => {
|
||||
if (precision != null) {
|
||||
const ratio = 10 ** precision;
|
||||
number = Math.round(number * ratio) / ratio;
|
||||
@@ -250,31 +253,22 @@ const stringifyNumber = ({ number, precision }) => {
|
||||
};
|
||||
|
||||
/**
|
||||
* @typedef {{
|
||||
* command: string;
|
||||
* args: number[];
|
||||
* precision?: number;
|
||||
* disableSpaceAfterFlags?: boolean;
|
||||
* }} StringifyArgsOptions
|
||||
*/
|
||||
/**
|
||||
*
|
||||
* Elliptical arc large-arc and sweep flags are rendered with spaces
|
||||
* because many non-browser environments are not able to parse such paths
|
||||
*
|
||||
* @param {StringifyArgsOptions} param
|
||||
* @type {(
|
||||
* command: string,
|
||||
* args: number[],
|
||||
* precision?: number,
|
||||
* disableSpaceAfterFlags?: boolean
|
||||
* ) => string}
|
||||
*/
|
||||
const stringifyArgs = ({
|
||||
command,
|
||||
args,
|
||||
precision,
|
||||
disableSpaceAfterFlags,
|
||||
}) => {
|
||||
const stringifyArgs = (command, args, precision, disableSpaceAfterFlags) => {
|
||||
let result = '';
|
||||
let prev = '';
|
||||
for (let i = 0; i < args.length; i += 1) {
|
||||
const number = args[i];
|
||||
const numberString = stringifyNumber({ number, precision });
|
||||
const numberString = stringifyNumber(number, precision);
|
||||
if (
|
||||
disableSpaceAfterFlags &&
|
||||
(command === 'A' || command === 'a') &&
|
||||
@@ -298,21 +292,15 @@ const stringifyArgs = ({
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @typedef {{
|
||||
* command: string;
|
||||
* args: number[];
|
||||
* }} Command
|
||||
*/
|
||||
/**
|
||||
* @typedef {{
|
||||
* pathData: Command[];
|
||||
* pathData: Array<PathDataItem>;
|
||||
* precision?: number;
|
||||
* disableSpaceAfterFlags?: boolean;
|
||||
* }} StringifyPathDataOptions
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {StringifyPathDataOptions} param
|
||||
* @type {(options: StringifyPathDataOptions) => string}
|
||||
*/
|
||||
const stringifyPathData = ({ pathData, precision, disableSpaceAfterFlags }) => {
|
||||
// combine sequence of the same commands
|
||||
@@ -322,6 +310,9 @@ const stringifyPathData = ({ pathData, precision, disableSpaceAfterFlags }) => {
|
||||
if (i === 0) {
|
||||
combined.push({ command, args });
|
||||
} else {
|
||||
/**
|
||||
* @type {PathDataItem}
|
||||
*/
|
||||
const last = combined[combined.length - 1];
|
||||
// match leading moveto with following lineto
|
||||
if (i === 1) {
|
||||
@@ -349,8 +340,7 @@ const stringifyPathData = ({ pathData, precision, disableSpaceAfterFlags }) => {
|
||||
let result = '';
|
||||
for (const { command, args } of combined) {
|
||||
result +=
|
||||
command +
|
||||
stringifyArgs({ command, args, precision, disableSpaceAfterFlags });
|
||||
command + stringifyArgs(command, args, precision, disableSpaceAfterFlags);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
Reference in New Issue
Block a user