Skip to content

Commit

Permalink
fix: mergePaths should not merge paths with styles that depend on bou…
Browse files Browse the repository at this point in the history
…nding box (#1964)
  • Loading branch information
johnkenny54 authored Feb 25, 2024
1 parent 473c5a6 commit a8d2df6
Show file tree
Hide file tree
Showing 6 changed files with 215 additions and 1 deletion.
27 changes: 26 additions & 1 deletion plugins/mergePaths.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,34 @@
/**
* @typedef {import('../lib/types.js').ComputedStyles} ComputedStyles
* @typedef {import('../lib/types.js').StaticStyle} StaticStyle
* @typedef {import('../lib/types.js').DynamicStyle} DynamicStyle
* @typedef {import("../lib/types.js").PathDataItem} PathDataItem
* @typedef {import('../lib/types.js').XastChild} XastChild
* @typedef {import('../lib/types.js').XastElement} XastElement
*/

import { collectStylesheet, computeStyle } from '../lib/style.js';
import { path2js, js2path, intersects } from './_path.js';
import { includesUrlReference } from '../lib/svgo/tools.js';

export const name = 'mergePaths';
export const description = 'merges multiple paths in one if possible';

/**
* @param {ComputedStyles} computedStyle
* @param {string} attName
* @returns {boolean}
*/
function elementHasUrl(computedStyle, attName) {
const style = computedStyle[attName];

if (style?.type === 'static') {
return includesUrlReference(style.value);
}

return false;
}

/**
* Merge multiple Paths into one.
*
Expand Down Expand Up @@ -82,7 +101,13 @@ export const fn = (root, params) => {
if (
computedStyle['marker-start'] ||
computedStyle['marker-mid'] ||
computedStyle['marker-end']
computedStyle['marker-end'] ||
computedStyle['clip-path'] ||
computedStyle['mask'] ||
computedStyle['mask-image'] ||
['fill', 'filter', 'stroke'].some((attName) =>
elementHasUrl(computedStyle, attName),
)
) {
if (prevPathData) {
updatePreviousPath(prevChild, prevPathData);
Expand Down
37 changes: 37 additions & 0 deletions test/plugins/mergePaths.08.svg.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
Don't merge paths with a linearGradient fill (issue #1267).

===

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 300">
<style>
path.lg{fill:url(#gradient);}
</style>
<linearGradient id="gradient">
<stop offset="0" stop-color="#ff0000"/>
<stop offset="1" stop-color="#0000ff"/>
</linearGradient>
<path fill="url(#gradient)" d="M 0 0 H 100 V 80 H 0 z"/>
<path fill="url(#gradient)" d="M 200 0 H 300 V 80 H 200 z"/>
<path style="fill:url(#gradient)" d="M 0 100 h 100 v 80 H 0 z"/>
<path style="fill:url(#gradient)" d="M 200 100 H 300 v 80 H 200 z"/>
<path class="lg" d="M 0 200 h 100 v 80 H 0 z"/>
<path class="lg" d="M 200 200 H 300 v 80 H 200 z"/>
</svg>

@@@

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 300">
<style>
path.lg{fill:url(#gradient);}
</style>
<linearGradient id="gradient">
<stop offset="0" stop-color="#ff0000"/>
<stop offset="1" stop-color="#0000ff"/>
</linearGradient>
<path fill="url(#gradient)" d="M 0 0 H 100 V 80 H 0 z"/>
<path fill="url(#gradient)" d="M 200 0 H 300 V 80 H 200 z"/>
<path style="fill:url(#gradient)" d="M 0 100 h 100 v 80 H 0 z"/>
<path style="fill:url(#gradient)" d="M 200 100 H 300 v 80 H 200 z"/>
<path class="lg" d="M 0 200 h 100 v 80 H 0 z"/>
<path class="lg" d="M 200 200 H 300 v 80 H 200 z"/>
</svg>
37 changes: 37 additions & 0 deletions test/plugins/mergePaths.09.svg.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
Don't merge paths with a linearGradient stroke (issue #1267).

===

<svg xmlns="http://www.w3.org/2000/svg" viewBox="-5 -5 300 300">
<style>
path.lg{stroke:url(#gradient);}
</style>
<linearGradient id="gradient">
<stop offset="0" stop-color="#ff0000"/>
<stop offset="1" stop-color="#0000ff"/>
</linearGradient>
<path stroke="url(#gradient)" stroke-width="10" d="M 0 0 H 100 V 80 H 0 z"/>
<path stroke="url(#gradient)" stroke-width="10" d="M 200 0 H 300 V 80 H 200 z"/>
<path style="stroke:url(#gradient)" stroke-width="10" d="M 0 100 h 100 v 80 H 0 z"/>
<path style="stroke:url(#gradient)" stroke-width="10" d="M 200 100 H 300 v 80 H 200 z"/>
<path class="lg" stroke-width="10" d="M 0 200 h 100 v 80 H 0 z"/>
<path class="lg" stroke-width="10" d="M 200 200 H 300 v 80 H 200 z"/>
</svg>

@@@

<svg xmlns="http://www.w3.org/2000/svg" viewBox="-5 -5 300 300">
<style>
path.lg{stroke:url(#gradient);}
</style>
<linearGradient id="gradient">
<stop offset="0" stop-color="#ff0000"/>
<stop offset="1" stop-color="#0000ff"/>
</linearGradient>
<path stroke="url(#gradient)" stroke-width="10" d="M 0 0 H 100 V 80 H 0 z"/>
<path stroke="url(#gradient)" stroke-width="10" d="M 200 0 H 300 V 80 H 200 z"/>
<path style="stroke:url(#gradient)" stroke-width="10" d="M 0 100 h 100 v 80 H 0 z"/>
<path style="stroke:url(#gradient)" stroke-width="10" d="M 200 100 H 300 v 80 H 200 z"/>
<path class="lg" stroke-width="10" d="M 0 200 h 100 v 80 H 0 z"/>
<path class="lg" stroke-width="10" d="M 200 200 H 300 v 80 H 200 z"/>
</svg>
35 changes: 35 additions & 0 deletions test/plugins/mergePaths.10.svg.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
Don't merge paths with a filter URL (issue #1267).

===

<svg xmlns="http://www.w3.org/2000/svg" viewBox="-5 -5 300 300">
<style>
path.lg{filter:url(#blurMe);}
</style>
<filter id="blurMe" x=".1">
<feGaussianBlur stdDeviation="5"/>
</filter>
<path filter="url(#blurMe)" fill="red" d="M 0 0 H 100 V 80 H 0 z"/>
<path filter="url(#blurMe)" fill="red" d="M 200 0 H 300 V 80 H 200 z"/>
<path style="filter:url(#blurMe)" fill="red" d="M 0 100 h 100 v 80 H 0 z"/>
<path style="filter:url(#blurMe)" fill="red" d="M 200 100 H 300 v 80 H 200 z"/>
<path class="lg" fill="red" d="M 0 200 h 100 v 80 H 0 z"/>
<path class="lg" fill="red" d="M 200 200 H 300 v 80 H 200 z"/>
</svg>

@@@

<svg xmlns="http://www.w3.org/2000/svg" viewBox="-5 -5 300 300">
<style>
path.lg{filter:url(#blurMe);}
</style>
<filter id="blurMe" x=".1">
<feGaussianBlur stdDeviation="5"/>
</filter>
<path filter="url(#blurMe)" fill="red" d="M 0 0 H 100 V 80 H 0 z"/>
<path filter="url(#blurMe)" fill="red" d="M 200 0 H 300 V 80 H 200 z"/>
<path style="filter:url(#blurMe)" fill="red" d="M 0 100 h 100 v 80 H 0 z"/>
<path style="filter:url(#blurMe)" fill="red" d="M 200 100 H 300 v 80 H 200 z"/>
<path class="lg" fill="red" d="M 0 200 h 100 v 80 H 0 z"/>
<path class="lg" fill="red" d="M 200 200 H 300 v 80 H 200 z"/>
</svg>
39 changes: 39 additions & 0 deletions test/plugins/mergePaths.11.svg.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
Don't merge paths with a clip-path (issue #1267).

===

<svg xmlns="http://www.w3.org/2000/svg" viewBox="-5 -5 400 400">
<style>
path.lg{clip-path:url(#myClip);}
</style>
<clipPath id="myClip" clipPathUnits="objectBoundingBox">
<circle cx=".5" cy=".5" r=".5"/>
</clipPath>
<path clip-path="url(#myClip)" fill="red" d="M 0 0 H 100 V 80 H 0 z"/>
<path clip-path="url(#myClip)" fill="red" d="M 200 0 H 300 V 80 H 200 z"/>
<path style="clip-path:url(#myClip)" fill="red" d="M 0 100 h 100 v 80 H 0 z"/>
<path style="clip-path:url(#myClip)" fill="red" d="M 200 100 H 300 v 80 H 200 z"/>
<path class="lg" fill="red" d="M 0 200 h 100 v 80 H 0 z"/>
<path class="lg" fill="red" d="M 200 200 H 300 v 80 H 200 z"/>
<path style="clip-path:circle(25%)" fill="red" d="M 0 300 h 100 v 80 H 0 z"/>
<path style="clip-path:circle(25%)" fill="red" d="M 200 300 H 300 v 80 H 200 z"/>
</svg>

@@@

<svg xmlns="http://www.w3.org/2000/svg" viewBox="-5 -5 400 400">
<style>
path.lg{clip-path:url(#myClip);}
</style>
<clipPath id="myClip" clipPathUnits="objectBoundingBox">
<circle cx=".5" cy=".5" r=".5"/>
</clipPath>
<path clip-path="url(#myClip)" fill="red" d="M 0 0 H 100 V 80 H 0 z"/>
<path clip-path="url(#myClip)" fill="red" d="M 200 0 H 300 V 80 H 200 z"/>
<path style="clip-path:url(#myClip)" fill="red" d="M 0 100 h 100 v 80 H 0 z"/>
<path style="clip-path:url(#myClip)" fill="red" d="M 200 100 H 300 v 80 H 200 z"/>
<path class="lg" fill="red" d="M 0 200 h 100 v 80 H 0 z"/>
<path class="lg" fill="red" d="M 200 200 H 300 v 80 H 200 z"/>
<path style="clip-path:circle(25%)" fill="red" d="M 0 300 h 100 v 80 H 0 z"/>
<path style="clip-path:circle(25%)" fill="red" d="M 200 300 H 300 v 80 H 200 z"/>
</svg>
41 changes: 41 additions & 0 deletions test/plugins/mergePaths.12.svg.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
Don't merge paths with a mask (issue #1267).

===

<svg xmlns="http://www.w3.org/2000/svg" viewBox="-5 -5 400 400">
<style>
path.lg{mask:url(#mask);}
</style>
<mask id="mask" maskContentUnits="objectBoundingBox">
<rect fill="white" x="0" y="0" width="100%" height="100%"/>
<circle fill="black" cx=".5" cy=".5" r=".5"/>
</mask>
<path mask="url(#mask)" fill="red" d="M 0 0 H 100 V 80 H 0 z"/>
<path mask="url(#mask)" fill="red" d="M 200 0 H 300 V 80 H 200 z"/>
<path style="mask:url(#mask)" fill="red" d="M 0 100 h 100 v 80 H 0 z"/>
<path style="mask:url(#mask)" fill="red" d="M 200 100 H 300 v 80 H 200 z"/>
<path class="lg" fill="red" d="M 0 200 h 100 v 80 H 0 z"/>
<path class="lg" fill="red" d="M 200 200 H 300 v 80 H 200 z"/>
<path style="mask-image: linear-gradient(to left top,black, transparent)" fill="red" d="M 0 300 h 100 v 80 H 0 z"/>
<path style="mask-image: linear-gradient(to left top,black, transparent)" fill="red" d="M 200 300 H 300 v 80 H 200 z"/>
</svg>

@@@

<svg xmlns="http://www.w3.org/2000/svg" viewBox="-5 -5 400 400">
<style>
path.lg{mask:url(#mask);}
</style>
<mask id="mask" maskContentUnits="objectBoundingBox">
<rect fill="white" x="0" y="0" width="100%" height="100%"/>
<circle fill="black" cx=".5" cy=".5" r=".5"/>
</mask>
<path mask="url(#mask)" fill="red" d="M 0 0 H 100 V 80 H 0 z"/>
<path mask="url(#mask)" fill="red" d="M 200 0 H 300 V 80 H 200 z"/>
<path style="mask:url(#mask)" fill="red" d="M 0 100 h 100 v 80 H 0 z"/>
<path style="mask:url(#mask)" fill="red" d="M 200 100 H 300 v 80 H 200 z"/>
<path class="lg" fill="red" d="M 0 200 h 100 v 80 H 0 z"/>
<path class="lg" fill="red" d="M 200 200 H 300 v 80 H 200 z"/>
<path style="mask-image: linear-gradient(to left top,black, transparent)" fill="red" d="M 0 300 h 100 v 80 H 0 z"/>
<path style="mask-image: linear-gradient(to left top,black, transparent)" fill="red" d="M 200 300 H 300 v 80 H 200 z"/>
</svg>

0 comments on commit a8d2df6

Please sign in to comment.