Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/03-plugins/convert-path-data.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ svgo:
lineShorthands:
description: If to convert regular lines to an explicit horizontal or vertical line where possible.
default: true
convertToZ:
description: If to convert lines that go to the start to a `z` command.
Comment thread
KTibow marked this conversation as resolved.
Outdated
default: true
curveSmoothShorthands:
description: If to convert curves to smooth curves where possible.
default: true
Expand Down Expand Up @@ -55,6 +58,7 @@ This plugin uses multiple techniques to either reduce the number of instructions

* Convert between relative or absolute coordinates, whichever is shortest.
* Convert between commands. For example, a bézier curve that behaves like a straight line might as well use a line instruction.
* Remove commands (when applicable). For example, a command that moves to the current position can be removed.
Comment thread
KTibow marked this conversation as resolved.
Outdated
* Trim redundant delimiters and leading zeros.
* Round numeric values using conventional rounding rules.

Expand Down
44 changes: 42 additions & 2 deletions plugins/convertPathData.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ let arcTolerance;
* },
* straightCurves: boolean,
* lineShorthands: boolean,
* convertToZ: boolean,
* curveSmoothShorthands: boolean,
* floatPrecision: number | false,
* transformPrecision: number,
Expand Down Expand Up @@ -95,6 +96,7 @@ exports.fn = (root, params) => {
},
straightCurves = true,
lineShorthands = true,
convertToZ = true,
curveSmoothShorthands = true,
floatPrecision = 3,
transformPrecision = 5,
Expand All @@ -116,6 +118,7 @@ exports.fn = (root, params) => {
makeArcs,
straightCurves,
lineShorthands,
convertToZ,
curveSmoothShorthands,
floatPrecision,
transformPrecision,
Expand Down Expand Up @@ -167,6 +170,14 @@ exports.fn = (root, params) => {
(computedStyle['stroke-linecap'].type === 'dynamic' ||
computedStyle['stroke-linecap'].value !== 'butt');
const maybeHasStrokeAndLinecap = maybeHasStroke && maybeHasLinecap;
// TODO: when stroke is used, prefer z more
// Z is the same as going home at 90 and 0 degrees, but not at other degrees
Comment thread
KTibow marked this conversation as resolved.
Outdated
const isSafeToUseZ = maybeHasStroke
? computedStyle['stroke-linecap']?.type === 'static' &&
computedStyle['stroke-linecap'].value === 'round' &&
computedStyle['stroke-linejoin']?.type === 'static' &&
computedStyle['stroke-linejoin'].value === 'round'
: true;

var data = path2js(node);

Expand All @@ -175,6 +186,7 @@ exports.fn = (root, params) => {
convertToRelative(data);

data = filters(data, newParams, {
isSafeToUseZ,
maybeHasStrokeAndLinecap,
hasMarkerMid,
});
Expand Down Expand Up @@ -371,10 +383,14 @@ const convertToRelative = (pathData) => {
* @type {(
* path: PathDataItem[],
* params: InternalParams,
* aux: { maybeHasStrokeAndLinecap: boolean, hasMarkerMid: boolean }
* aux: { isSafeToUseZ: boolean, maybeHasStrokeAndLinecap: boolean, hasMarkerMid: boolean }
* ) => PathDataItem[]}
*/
function filters(path, params, { maybeHasStrokeAndLinecap, hasMarkerMid }) {
function filters(
path,
params,
{ isSafeToUseZ, maybeHasStrokeAndLinecap, hasMarkerMid }
) {
var stringify = data2Path.bind(null, params),
relSubpoint = [0, 0],
pathBase = [0, 0],
Expand Down Expand Up @@ -664,6 +680,20 @@ function filters(path, params, { maybeHasStrokeAndLinecap, hasMarkerMid }) {
}
}

// convert going home to z
// m 0 0 h 5 v 5 l -5 -5 -> m 0 0 h 5 v 5 z
if (
params.convertToZ &&
(isSafeToUseZ || next?.command === 'Z' || next?.command === 'z') &&
(command === 'l' || command === 'h' || command === 'v')
) {
// @ts-ignore
if (pathBase[0] === item.coords[0] && pathBase[1] === item.coords[1]) {
command = 'z';
data = [];
}
}

// collapse repeated commands
// h 20 h 30 -> h 50
if (
Expand Down Expand Up @@ -806,6 +836,16 @@ function filters(path, params, { maybeHasStrokeAndLinecap, hasMarkerMid }) {
if (prev.command === 'Z' || prev.command === 'z') return false;
prev = item;
}
if (
(command === 'Z' || command === 'z') &&
params.removeUseless &&
isSafeToUseZ &&
// @ts-ignore
item.base[0] === item.coords[0] &&
// @ts-ignore
item.base[1] === item.coords[1]
)
return false;

return true;
});
Expand Down
3 changes: 2 additions & 1 deletion plugins/plugins-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ type DefaultPlugins = {
};
straightCurves?: boolean;
lineShorthands?: boolean;
convertToZ?: boolean;
curveSmoothShorthands?: boolean;
floatPrecision?: number | false;
transformPrecision?: number;
Expand Down Expand Up @@ -138,7 +139,7 @@ type DefaultPlugins = {
moveElemsAttrsToGroup: void;
moveGroupAttrsToElems: void;
removeComments: {
preservePatterns: Array<RegExp|string> | false
preservePatterns: Array<RegExp | string> | false;
};
removeDesc: {
removeAny?: boolean;
Expand Down
2 changes: 1 addition & 1 deletion test/coa/testSvg/test.1.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion test/coa/testSvg/test.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 4 additions & 4 deletions test/plugins/convertPathData.12.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion test/plugins/convertPathData.13.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 3 additions & 3 deletions test/plugins/convertPathData.14.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion test/plugins/convertPathData.18.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion test/plugins/convertPathData.19.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion test/plugins/convertPathData.20.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 13 additions & 0 deletions test/plugins/convertPathData.27.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion test/svgo/plugins-order.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.