1
0
mirror of https://github.com/svg/svgo.git synced 2025-07-29 20:21:14 +03:00

Cover with types numeric values plugins (#1541)

- cleanupNumericValues
- cleanupListOfValues
This commit is contained in:
Bogdan Chadkin
2021-08-24 14:57:09 +03:00
committed by GitHub
parent 4082eca762
commit 0ead871eed
4 changed files with 83 additions and 35 deletions

View File

@ -1,13 +1,15 @@
'use strict'; 'use strict';
/**
* @typedef {import('../types').PathDataCommand} PathDataCommand
*/
/** /**
* Encode plain SVG data string into Data URI string. * Encode plain SVG data string into Data URI string.
* *
* @param {string} str input string * @type {(str: string, type?: 'base64' | 'enc' | 'unenc') => string}
* @param {string} type Data URI type
* @return {string} output string
*/ */
exports.encodeSVGDatauri = function (str, type) { exports.encodeSVGDatauri = (str, type) => {
var prefix = 'data:image/svg+xml'; var prefix = 'data:image/svg+xml';
if (!type || type === 'base64') { if (!type || type === 'base64') {
// base64 // base64
@ -26,10 +28,9 @@ exports.encodeSVGDatauri = function (str, type) {
/** /**
* Decode SVG Data URI string into plain SVG string. * Decode SVG Data URI string into plain SVG string.
* *
* @param {string} str input string * @type {(str: string) => string}
* @return {string} output string
*/ */
exports.decodeSVGDatauri = function (str) { exports.decodeSVGDatauri = (str) => {
var regexp = /data:image\/svg\+xml(;charset=[^;,]*)?(;base64)?,(.*)/; var regexp = /data:image\/svg\+xml(;charset=[^;,]*)?(;base64)?,(.*)/;
var match = regexp.exec(str); var match = regexp.exec(str);
@ -51,23 +52,31 @@ exports.decodeSVGDatauri = function (str) {
return str; return str;
}; };
/**
* @typedef {{
* noSpaceAfterFlags?: boolean,
* leadingZero?: boolean,
* negativeExtraSpace?: boolean
* }} CleanupOutDataParams
*/
/** /**
* Convert a row of numbers to an optimized string view. * Convert a row of numbers to an optimized string view.
* *
* @example * @example
* [0, -1, .5, .5] → "0-1 .5.5" * [0, -1, .5, .5] → "0-1 .5.5"
* *
* @param {number[]} data * @type {(data: Array<number>, params: CleanupOutDataParams, command: PathDataCommand) => string}
* @param {Object} params
* @param {string} [command] path data instruction
* @return {string}
*/ */
exports.cleanupOutData = function (data, params, command) { exports.cleanupOutData = (data, params, command) => {
var str = '', let str = '';
delimiter, let delimiter;
prev; /**
* @type {number}
*/
let prev;
data.forEach(function (item, i) { data.forEach((item, i) => {
// space delimiter by default // space delimiter by default
delimiter = ' '; delimiter = ' ';
@ -113,11 +122,9 @@ exports.cleanupOutData = function (data, params, command) {
* @example * @example
* -0.5 → -.5 * -0.5 → -.5
* *
* @param {number} num input number * @type {(num: number) => string}
*
* @return {string} output number as string
*/ */
var removeLeadingZero = function (num) { const removeLeadingZero = (num) => {
var strNum = num.toString(); var strNum = num.toString();
if (0 < num && num < 1 && strNum.charAt(0) === '0') { if (0 < num && num < 1 && strNum.charAt(0) === '0') {
@ -129,6 +136,9 @@ var removeLeadingZero = function (num) {
}; };
exports.removeLeadingZero = removeLeadingZero; exports.removeLeadingZero = removeLeadingZero;
/**
* @type {(name: string) => { prefix: string, local: string }}
*/
const parseName = (name) => { const parseName = (name) => {
if (name == null) { if (name == null) {
return { return {

View File

@ -17,6 +17,7 @@ const absoluteLengths = {
in: 96, in: 96,
pt: 4 / 3, pt: 4 / 3,
pc: 16, pc: 16,
px: 1,
}; };
/** /**
@ -27,15 +28,20 @@ const absoluteLengths = {
* ⬇ * ⬇
* <svg viewBox="0 0 200.284 200.284" enable-background="new 0 0 200.284 200.284"> * <svg viewBox="0 0 200.284 200.284" enable-background="new 0 0 200.284 200.284">
* *
*
* <polygon points="208.250977 77.1308594 223.069336 ... "/> * <polygon points="208.250977 77.1308594 223.069336 ... "/>
* ⬇ * ⬇
* <polygon points="208.251 77.131 223.069 ... "/> * <polygon points="208.251 77.131 223.069 ... "/>
* *
*
* @author kiyopikko * @author kiyopikko
*
* @type {import('../lib/types').Plugin<{
* floatPrecision?: number,
* leadingZero?: boolean,
* defaultPx?: boolean,
* convertToPx?: boolean
* }>}
*/ */
exports.fn = (root, params) => { exports.fn = (_root, params) => {
const { const {
floatPrecision = 3, floatPrecision = 3,
leadingZero = true, leadingZero = true,
@ -43,6 +49,9 @@ exports.fn = (root, params) => {
convertToPx = true, convertToPx = true,
} = params; } = params;
/**
* @type {(lists: string) => string}
*/
const roundValues = (lists) => { const roundValues = (lists) => {
const roundedList = []; const roundedList = [];
@ -54,12 +63,19 @@ exports.fn = (root, params) => {
if (match) { if (match) {
// 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));
let units = match[3] || ''; /**
* @type {any}
*/
let matchedUnit = match[3] || '';
/**
* @type{'' | keyof typeof absoluteLengths}
*/
let units = matchedUnit;
// convert absolute values to pixels // convert absolute values to pixels
if (convertToPx && units && units in absoluteLengths) { if (convertToPx && units && units in absoluteLengths) {
const pxNum = Number( const pxNum = Number(
(absoluteLengths[units] * match[1]).toFixed(floatPrecision) (absoluteLengths[units] * Number(match[1])).toFixed(floatPrecision)
); );
if (pxNum.toString().length < match[0].length) { if (pxNum.toString().length < match[0].length) {
@ -69,8 +85,11 @@ exports.fn = (root, params) => {
} }
// and remove leading zero // and remove leading zero
let str;
if (leadingZero) { if (leadingZero) {
num = removeLeadingZero(num); str = removeLeadingZero(num);
} else {
str = num.toString();
} }
// remove default 'px' units // remove default 'px' units
@ -78,7 +97,7 @@ exports.fn = (root, params) => {
units = ''; units = '';
} }
roundedList.push(num + units); roundedList.push(str + units);
} }
// if attribute value is "new"(only enable-background). // if attribute value is "new"(only enable-background).
else if (matchNew) { else if (matchNew) {

View File

@ -10,6 +10,7 @@ exports.description =
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|%)?$/;
const absoluteLengths = { const absoluteLengths = {
// relative to px // relative to px
cm: 96 / 2.54, cm: 96 / 2.54,
@ -17,6 +18,7 @@ const absoluteLengths = {
in: 96, in: 96,
pt: 4 / 3, pt: 4 / 3,
pc: 16, pc: 16,
px: 1,
}; };
/** /**
@ -24,8 +26,15 @@ const absoluteLengths = {
* remove default 'px' units. * remove default 'px' units.
* *
* @author Kir Belevich * @author Kir Belevich
*
* @type {import('../lib/types').Plugin<{
* floatPrecision?: number,
* leadingZero?: boolean,
* defaultPx?: boolean,
* convertToPx?: boolean
* }>}
*/ */
exports.fn = (root, params) => { exports.fn = (_root, params) => {
const { const {
floatPrecision = 3, floatPrecision = 3,
leadingZero = true, leadingZero = true,
@ -60,12 +69,21 @@ exports.fn = (root, params) => {
if (match) { if (match) {
// 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));
let units = match[3] || ''; /**
* @type {any}
*/
let matchedUnit = match[3] || '';
/**
* @type{'' | keyof typeof absoluteLengths}
*/
let units = matchedUnit;
// convert absolute values to pixels // convert absolute values to pixels
if (convertToPx && units && units in absoluteLengths) { if (convertToPx && units !== '' && units in absoluteLengths) {
const pxNum = Number( const pxNum = Number(
(absoluteLengths[units] * match[1]).toFixed(floatPrecision) (absoluteLengths[units] * Number(match[1])).toFixed(
floatPrecision
)
); );
if (pxNum.toString().length < match[0].length) { if (pxNum.toString().length < match[0].length) {
num = pxNum; num = pxNum;
@ -74,8 +92,11 @@ exports.fn = (root, params) => {
} }
// and remove leading zero // and remove leading zero
let str;
if (leadingZero) { if (leadingZero) {
num = removeLeadingZero(num); str = removeLeadingZero(num);
} else {
str = num.toString();
} }
// remove default 'px' units // remove default 'px' units
@ -83,7 +104,7 @@ exports.fn = (root, params) => {
units = ''; units = '';
} }
node.attributes[name] = num + units; node.attributes[name] = str + units;
} }
} }
}, },

View File

@ -15,8 +15,6 @@
"plugins/_transforms.js", "plugins/_transforms.js",
"plugins/_applyTransforms.js", "plugins/_applyTransforms.js",
"plugins/cleanupIDs.js", "plugins/cleanupIDs.js",
"plugins/cleanupListOfValues.js",
"plugins/cleanupNumericValues.js",
"plugins/collapseGroups.js", "plugins/collapseGroups.js",
"plugins/convertColors.js", "plugins/convertColors.js",
"plugins/convertPathData.js", "plugins/convertPathData.js",