svg-path-simplify 0.4.1 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -0
- package/dist/svg-path-simplify.esm.js +528 -165
- package/dist/svg-path-simplify.esm.min.js +2 -2
- package/dist/svg-path-simplify.js +528 -165
- package/dist/svg-path-simplify.min.js +2 -2
- package/dist/svg-path-simplify.pathdata.esm.js +40 -0
- package/dist/svg-path-simplify.pathdata.esm.min.js +2 -2
- package/index.html +79 -16
- package/package.json +5 -2
- package/src/pathSimplify-main.js +15 -4
- package/src/string_helpers.js +18 -0
- package/src/svgii/convert_units.js +8 -2
- package/src/svgii/pathData_convert.js +38 -0
- package/src/svgii/pathData_parse_els.js +135 -133
- package/src/svgii/svg-styles-to-attributes-const.js +1 -0
- package/src/svgii/svg_cleanup.js +328 -36
- package/src/svgii/svg_el_parse_style_props.js +29 -3
- package/tests/testSVG_shape.js +59 -0
- package/tests/testSVG_transform.js +61 -0
|
@@ -1729,6 +1729,7 @@
|
|
|
1729
1729
|
const transVertical = ['scaleY', 'translateY', 'skewY'];
|
|
1730
1730
|
|
|
1731
1731
|
const colorProps = ['fill', 'stroke', 'stop-color'];
|
|
1732
|
+
const geometryProps = ['d', 'points', 'cx', 'cy', 'x1', 'x2', 'y1', 'y2', 'width', 'height', 'r', 'rx', 'ry', 'x', 'y'];
|
|
1732
1733
|
|
|
1733
1734
|
const geometryEls = [
|
|
1734
1735
|
"path",
|
|
@@ -2070,7 +2071,14 @@
|
|
|
2070
2071
|
|
|
2071
2072
|
let attributes = [...el.attributes];
|
|
2072
2073
|
let attNames = attributes.map(att => att.name);
|
|
2073
|
-
|
|
2074
|
+
|
|
2075
|
+
// doesn't work in node!
|
|
2076
|
+
|
|
2077
|
+
|
|
2078
|
+
let attValues = [];
|
|
2079
|
+
attNames.forEach(att=>{
|
|
2080
|
+
attValues.push(el.getAttribute(att));
|
|
2081
|
+
});
|
|
2074
2082
|
|
|
2075
2083
|
let isSquare = width === height;
|
|
2076
2084
|
|
|
@@ -3904,6 +3912,7 @@
|
|
|
3904
3912
|
toShorthands = true,
|
|
3905
3913
|
toLonghands = false,
|
|
3906
3914
|
toRelative = true,
|
|
3915
|
+
toMixed = false,
|
|
3907
3916
|
toAbsolute = false,
|
|
3908
3917
|
decimals = 3,
|
|
3909
3918
|
arcToCubic = false,
|
|
@@ -3919,6 +3928,8 @@
|
|
|
3919
3928
|
|
|
3920
3929
|
} = {}) {
|
|
3921
3930
|
|
|
3931
|
+
let pathDataAbs = [];
|
|
3932
|
+
|
|
3922
3933
|
// pathdata properties - test= true adds a manual test
|
|
3923
3934
|
if (testTypes) {
|
|
3924
3935
|
|
|
@@ -3946,12 +3957,38 @@
|
|
|
3946
3957
|
|
|
3947
3958
|
if (hasQuadratics && quadraticToCubic) pathData = pathDataQuadraticToCubic(pathData);
|
|
3948
3959
|
|
|
3960
|
+
if(toMixed) toRelative = true;
|
|
3961
|
+
|
|
3949
3962
|
// pre round - before relative conversion to minimize distortions
|
|
3950
3963
|
if (decimals > -1 && toRelative) pathData = roundPathData(pathData, decimals);
|
|
3951
3964
|
|
|
3965
|
+
// clone absolute pathdata
|
|
3966
|
+
if(toMixed){
|
|
3967
|
+
pathDataAbs = JSON.parse(JSON.stringify(pathData));
|
|
3968
|
+
}
|
|
3969
|
+
|
|
3952
3970
|
if (toRelative) pathData = pathDataToRelative(pathData);
|
|
3953
3971
|
if (decimals > -1) pathData = roundPathData(pathData, decimals);
|
|
3954
3972
|
|
|
3973
|
+
// choose most compact commands: relative or absolute
|
|
3974
|
+
if(toMixed){
|
|
3975
|
+
for(let i=0; i<pathData.length; i++){
|
|
3976
|
+
let com = pathData[i];
|
|
3977
|
+
let comA = pathDataAbs[i];
|
|
3978
|
+
// compare Lengths
|
|
3979
|
+
let comStr = [com.type, com.values.join(' ')].join('').replaceAll(' -', '-').replaceAll(' 0.', ' .');
|
|
3980
|
+
let comStrA = [comA.type, comA.values.join(' ')].join('').replaceAll(' -', '-').replaceAll(' 0.', ' .');
|
|
3981
|
+
|
|
3982
|
+
let lenR = comStr.length;
|
|
3983
|
+
let lenA = comStrA.length;
|
|
3984
|
+
|
|
3985
|
+
if(lenA<lenR){
|
|
3986
|
+
|
|
3987
|
+
pathData[i] = pathDataAbs[i];
|
|
3988
|
+
}
|
|
3989
|
+
}
|
|
3990
|
+
}
|
|
3991
|
+
|
|
3955
3992
|
return pathData
|
|
3956
3993
|
}
|
|
3957
3994
|
|
|
@@ -3962,6 +3999,9 @@
|
|
|
3962
3999
|
*/
|
|
3963
4000
|
|
|
3964
4001
|
function optimizeArcPathData(pathData = []) {
|
|
4002
|
+
|
|
4003
|
+
let remove =[];
|
|
4004
|
+
|
|
3965
4005
|
pathData.forEach((com, i) => {
|
|
3966
4006
|
let { type, values } = com;
|
|
3967
4007
|
if (type === 'A') {
|
|
@@ -3971,6 +4011,12 @@
|
|
|
3971
4011
|
let M = { x: x0, y: y0 };
|
|
3972
4012
|
let p = { x, y };
|
|
3973
4013
|
|
|
4014
|
+
if(rx===0 || ry===0){
|
|
4015
|
+
pathData[i]= null;
|
|
4016
|
+
remove.push(i);
|
|
4017
|
+
|
|
4018
|
+
}
|
|
4019
|
+
|
|
3974
4020
|
// rx and ry are large enough
|
|
3975
4021
|
if (rx >= 1 && (x === x0 || y === y0)) {
|
|
3976
4022
|
let diff = Math.abs(rx - ry) / rx;
|
|
@@ -3993,6 +4039,8 @@
|
|
|
3993
4039
|
}
|
|
3994
4040
|
}
|
|
3995
4041
|
});
|
|
4042
|
+
|
|
4043
|
+
if(remove.length) pathData = pathData.filter(Boolean);
|
|
3996
4044
|
return pathData;
|
|
3997
4045
|
}
|
|
3998
4046
|
|
|
@@ -5618,133 +5666,6 @@
|
|
|
5618
5666
|
return transObj;
|
|
5619
5667
|
}
|
|
5620
5668
|
|
|
5621
|
-
function pathElToShape(el, {
|
|
5622
|
-
convert_rects = false,
|
|
5623
|
-
convert_ellipses = false,
|
|
5624
|
-
convert_poly = false,
|
|
5625
|
-
convert_lines = false
|
|
5626
|
-
} = {}) {
|
|
5627
|
-
|
|
5628
|
-
let pathData = parsePathDataNormalized(el.getAttribute('d'));
|
|
5629
|
-
let coms = Array.from(new Set(pathData.map(com => com.type))).join('');
|
|
5630
|
-
|
|
5631
|
-
let hasArcs = (/[a]/gi).test(coms);
|
|
5632
|
-
let hasBeziers = (/[csqt]/gi).test(coms);
|
|
5633
|
-
let hasLines = (/[l]/gi).test(coms);
|
|
5634
|
-
let isPoly = !(/[acqts]/gi).test(coms);
|
|
5635
|
-
let closed = (/[z]/gi).test(coms);
|
|
5636
|
-
let shape = null;
|
|
5637
|
-
let type = null;
|
|
5638
|
-
|
|
5639
|
-
let attributes = getElementAtts(el);
|
|
5640
|
-
let attsNew = {};
|
|
5641
|
-
let decimals = 7;
|
|
5642
|
-
|
|
5643
|
-
if (isPoly) {
|
|
5644
|
-
|
|
5645
|
-
// is line
|
|
5646
|
-
if (pathData.length === 2 && convert_lines) {
|
|
5647
|
-
type = 'line';
|
|
5648
|
-
shape = document.createElementNS(svgNs, type);
|
|
5649
|
-
let [x1, y1, x2, y2] = [...pathData[0].values, ...pathData[1].values].map(val => roundTo(val, decimals));
|
|
5650
|
-
attsNew = { x1, y1, x2, y2 };
|
|
5651
|
-
}
|
|
5652
|
-
// polygon, polyline or rect
|
|
5653
|
-
else {
|
|
5654
|
-
|
|
5655
|
-
let vertices = getPathDataVertices(pathData);
|
|
5656
|
-
let bb = getPolyBBox(vertices);
|
|
5657
|
-
let areaPoly = getPolygonArea(vertices, true);
|
|
5658
|
-
let areaRect = bb.width * bb.height;
|
|
5659
|
-
let areaDiff = Math.abs(1 - areaRect / areaPoly);
|
|
5660
|
-
|
|
5661
|
-
// is rect
|
|
5662
|
-
if (convert_rects && areaDiff < 0.01) {
|
|
5663
|
-
type = 'rect';
|
|
5664
|
-
shape = document.createElementNS(svgNs, type);
|
|
5665
|
-
let { x, y, width, height } = bb;
|
|
5666
|
-
attsNew = { x, y, width, height };
|
|
5667
|
-
|
|
5668
|
-
}
|
|
5669
|
-
// polyline or polygon
|
|
5670
|
-
else if(convert_poly) {
|
|
5671
|
-
type = closed ? 'polygon' : 'polyline';
|
|
5672
|
-
shape = document.createElementNS(svgNs, type);
|
|
5673
|
-
let points = vertices.map(pt => { return [pt.x, pt.y] }).flat().map(val => roundTo(val, decimals)).join(' ');
|
|
5674
|
-
attsNew = { points };
|
|
5675
|
-
}
|
|
5676
|
-
}
|
|
5677
|
-
}
|
|
5678
|
-
// circles or ellipses
|
|
5679
|
-
else if (!hasLines && convert_ellipses) {
|
|
5680
|
-
|
|
5681
|
-
// try to convert cubics to arcs
|
|
5682
|
-
if (!hasArcs && hasBeziers) {
|
|
5683
|
-
pathData = pathDataCubicsToArc(pathData, { areaThreshold: 2.5 });
|
|
5684
|
-
hasArcs = pathData.filter(com => com.type === 'A').length;
|
|
5685
|
-
}
|
|
5686
|
-
|
|
5687
|
-
if (hasArcs) {
|
|
5688
|
-
let pathData2 = getPathDataVerbose(pathData, { addArcParams: true });
|
|
5689
|
-
let arcComs = pathData2.filter(com => com.type === 'A');
|
|
5690
|
-
|
|
5691
|
-
let cxVals = new Set();
|
|
5692
|
-
let cyVals = new Set();
|
|
5693
|
-
let rxVals = new Set();
|
|
5694
|
-
let ryVals = new Set();
|
|
5695
|
-
|
|
5696
|
-
if (arcComs.length > 1) {
|
|
5697
|
-
|
|
5698
|
-
pathData2.forEach(com => {
|
|
5699
|
-
if (com.type === 'A') {
|
|
5700
|
-
|
|
5701
|
-
cxVals.add(roundTo(com.cx, decimals));
|
|
5702
|
-
cyVals.add(roundTo(com.cy, decimals));
|
|
5703
|
-
rxVals.add(roundTo(com.rx, decimals));
|
|
5704
|
-
ryVals.add(roundTo(com.ry, decimals));
|
|
5705
|
-
}
|
|
5706
|
-
});
|
|
5707
|
-
}
|
|
5708
|
-
|
|
5709
|
-
cxVals = Array.from(cxVals);
|
|
5710
|
-
cyVals = Array.from(cyVals);
|
|
5711
|
-
rxVals = Array.from(rxVals);
|
|
5712
|
-
ryVals = Array.from(ryVals);
|
|
5713
|
-
|
|
5714
|
-
if(cxVals.length===1 && cyVals.length===1 && rxVals.length===1 && ryVals.length===1){
|
|
5715
|
-
let [rx, ry, cx, cy] = [rxVals[0], ryVals[0], cxVals[0], cyVals[0]];
|
|
5716
|
-
type = rx===ry ? 'circle' : 'ellipse';
|
|
5717
|
-
shape = document.createElementNS(svgNs, type);
|
|
5718
|
-
attsNew = type==='circle' ? { r:rx, cx, cy } : {rx, ry, cx, cy};
|
|
5719
|
-
}
|
|
5720
|
-
}
|
|
5721
|
-
}
|
|
5722
|
-
|
|
5723
|
-
// if el could be replaced
|
|
5724
|
-
if (shape) {
|
|
5725
|
-
let ignore = ['id', 'class'];
|
|
5726
|
-
|
|
5727
|
-
// set shape attributes
|
|
5728
|
-
for (let att in attsNew) {
|
|
5729
|
-
shape.setAttribute(att, attsNew[att]);
|
|
5730
|
-
}
|
|
5731
|
-
|
|
5732
|
-
// copy old attributes
|
|
5733
|
-
for (let att in attributes) {
|
|
5734
|
-
|
|
5735
|
-
if (attLookup.atts[att].includes(type) || ignore.includes(att) || att.startsWith('data-')) {
|
|
5736
|
-
shape.setAttribute(att, attributes[att]);
|
|
5737
|
-
}
|
|
5738
|
-
}
|
|
5739
|
-
|
|
5740
|
-
// replace
|
|
5741
|
-
el = shape;
|
|
5742
|
-
}
|
|
5743
|
-
|
|
5744
|
-
return el;
|
|
5745
|
-
|
|
5746
|
-
}
|
|
5747
|
-
|
|
5748
5669
|
function shapeElToPath(el, { width = 0,
|
|
5749
5670
|
height = 0,
|
|
5750
5671
|
convert_rects = false,
|
|
@@ -5923,6 +5844,133 @@
|
|
|
5923
5844
|
|
|
5924
5845
|
}
|
|
5925
5846
|
|
|
5847
|
+
function pathElToShape(el, {
|
|
5848
|
+
convert_rects = false,
|
|
5849
|
+
convert_ellipses = false,
|
|
5850
|
+
convert_poly = false,
|
|
5851
|
+
convert_lines = false
|
|
5852
|
+
} = {}) {
|
|
5853
|
+
|
|
5854
|
+
let pathData = parsePathDataNormalized(el.getAttribute('d'));
|
|
5855
|
+
let coms = Array.from(new Set(pathData.map(com => com.type))).join('');
|
|
5856
|
+
|
|
5857
|
+
let hasArcs = (/[a]/gi).test(coms);
|
|
5858
|
+
let hasBeziers = (/[csqt]/gi).test(coms);
|
|
5859
|
+
let hasLines = (/[l]/gi).test(coms);
|
|
5860
|
+
let isPoly = !(/[acqts]/gi).test(coms);
|
|
5861
|
+
let closed = (/[z]/gi).test(coms);
|
|
5862
|
+
let shape = null;
|
|
5863
|
+
let type = null;
|
|
5864
|
+
|
|
5865
|
+
let attributes = getElementAtts(el);
|
|
5866
|
+
let attsNew = {};
|
|
5867
|
+
let decimals = 7;
|
|
5868
|
+
|
|
5869
|
+
if (isPoly) {
|
|
5870
|
+
|
|
5871
|
+
// is line
|
|
5872
|
+
if (pathData.length === 2 && convert_lines) {
|
|
5873
|
+
type = 'line';
|
|
5874
|
+
shape = document.createElementNS(svgNs, type);
|
|
5875
|
+
let [x1, y1, x2, y2] = [...pathData[0].values, ...pathData[1].values].map(val => roundTo(val, decimals));
|
|
5876
|
+
attsNew = { x1, y1, x2, y2 };
|
|
5877
|
+
}
|
|
5878
|
+
// polygon, polyline or rect
|
|
5879
|
+
else {
|
|
5880
|
+
|
|
5881
|
+
let vertices = getPathDataVertices(pathData);
|
|
5882
|
+
let bb = getPolyBBox(vertices);
|
|
5883
|
+
let areaPoly = getPolygonArea(vertices, true);
|
|
5884
|
+
let areaRect = bb.width * bb.height;
|
|
5885
|
+
let areaDiff = Math.abs(1 - areaRect / areaPoly);
|
|
5886
|
+
|
|
5887
|
+
// is rect
|
|
5888
|
+
if (convert_rects && areaDiff < 0.01) {
|
|
5889
|
+
type = 'rect';
|
|
5890
|
+
shape = document.createElementNS(svgNs, type);
|
|
5891
|
+
let { x, y, width, height } = bb;
|
|
5892
|
+
attsNew = { x, y, width, height };
|
|
5893
|
+
|
|
5894
|
+
}
|
|
5895
|
+
// polyline or polygon
|
|
5896
|
+
else if(convert_poly) {
|
|
5897
|
+
type = closed ? 'polygon' : 'polyline';
|
|
5898
|
+
shape = document.createElementNS(svgNs, type);
|
|
5899
|
+
let points = vertices.map(pt => { return [pt.x, pt.y] }).flat().map(val => roundTo(val, decimals)).join(' ');
|
|
5900
|
+
attsNew = { points };
|
|
5901
|
+
}
|
|
5902
|
+
}
|
|
5903
|
+
}
|
|
5904
|
+
// circles or ellipses
|
|
5905
|
+
else if (!hasLines && convert_ellipses) {
|
|
5906
|
+
|
|
5907
|
+
// try to convert cubics to arcs
|
|
5908
|
+
if (!hasArcs && hasBeziers) {
|
|
5909
|
+
pathData = pathDataCubicsToArc(pathData, { areaThreshold: 2.5 });
|
|
5910
|
+
hasArcs = pathData.filter(com => com.type === 'A').length;
|
|
5911
|
+
}
|
|
5912
|
+
|
|
5913
|
+
if (hasArcs) {
|
|
5914
|
+
let pathData2 = getPathDataVerbose(pathData, { addArcParams: true });
|
|
5915
|
+
let arcComs = pathData2.filter(com => com.type === 'A');
|
|
5916
|
+
|
|
5917
|
+
let cxVals = new Set();
|
|
5918
|
+
let cyVals = new Set();
|
|
5919
|
+
let rxVals = new Set();
|
|
5920
|
+
let ryVals = new Set();
|
|
5921
|
+
|
|
5922
|
+
if (arcComs.length > 1) {
|
|
5923
|
+
|
|
5924
|
+
pathData2.forEach(com => {
|
|
5925
|
+
if (com.type === 'A') {
|
|
5926
|
+
|
|
5927
|
+
cxVals.add(roundTo(com.cx, decimals));
|
|
5928
|
+
cyVals.add(roundTo(com.cy, decimals));
|
|
5929
|
+
rxVals.add(roundTo(com.rx, decimals));
|
|
5930
|
+
ryVals.add(roundTo(com.ry, decimals));
|
|
5931
|
+
}
|
|
5932
|
+
});
|
|
5933
|
+
}
|
|
5934
|
+
|
|
5935
|
+
cxVals = Array.from(cxVals);
|
|
5936
|
+
cyVals = Array.from(cyVals);
|
|
5937
|
+
rxVals = Array.from(rxVals);
|
|
5938
|
+
ryVals = Array.from(ryVals);
|
|
5939
|
+
|
|
5940
|
+
if(cxVals.length===1 && cyVals.length===1 && rxVals.length===1 && ryVals.length===1){
|
|
5941
|
+
let [rx, ry, cx, cy] = [rxVals[0], ryVals[0], cxVals[0], cyVals[0]];
|
|
5942
|
+
type = rx===ry ? 'circle' : 'ellipse';
|
|
5943
|
+
shape = document.createElementNS(svgNs, type);
|
|
5944
|
+
attsNew = type==='circle' ? { r:rx, cx, cy } : {rx, ry, cx, cy};
|
|
5945
|
+
}
|
|
5946
|
+
}
|
|
5947
|
+
}
|
|
5948
|
+
|
|
5949
|
+
// if el could be replaced
|
|
5950
|
+
if (shape) {
|
|
5951
|
+
let ignore = ['id', 'class'];
|
|
5952
|
+
|
|
5953
|
+
// set shape attributes
|
|
5954
|
+
for (let att in attsNew) {
|
|
5955
|
+
shape.setAttribute(att, attsNew[att]);
|
|
5956
|
+
}
|
|
5957
|
+
|
|
5958
|
+
// copy old attributes
|
|
5959
|
+
for (let att in attributes) {
|
|
5960
|
+
|
|
5961
|
+
if (attLookup.atts[att].includes(type) || ignore.includes(att) || att.startsWith('data-')) {
|
|
5962
|
+
shape.setAttribute(att, attributes[att]);
|
|
5963
|
+
}
|
|
5964
|
+
}
|
|
5965
|
+
|
|
5966
|
+
// replace
|
|
5967
|
+
el = shape;
|
|
5968
|
+
}
|
|
5969
|
+
|
|
5970
|
+
return el;
|
|
5971
|
+
|
|
5972
|
+
}
|
|
5973
|
+
|
|
5926
5974
|
function pathDataRemoveColinear(pathData, {
|
|
5927
5975
|
tolerance = 1,
|
|
5928
5976
|
|
|
@@ -6785,6 +6833,10 @@
|
|
|
6785
6833
|
removeDefaults = true,
|
|
6786
6834
|
cleanUpStrokes = true,
|
|
6787
6835
|
normalizeTransforms = true,
|
|
6836
|
+
removeIds=false,
|
|
6837
|
+
removeClassNames=false,
|
|
6838
|
+
|
|
6839
|
+
include=[],
|
|
6788
6840
|
exclude = [],
|
|
6789
6841
|
width = 0,
|
|
6790
6842
|
height = 0,
|
|
@@ -6815,7 +6867,7 @@
|
|
|
6815
6867
|
*/
|
|
6816
6868
|
|
|
6817
6869
|
if (removeInvalid || removeDefaults || removeNameSpaced) {
|
|
6818
|
-
let propsFilteredObj = filterSvgElProps(nodeName, props, { removeDefaults, removeNameSpaced, exclude, cleanUpStrokes, include: transformsStandalone, cleanUpStrokes: false });
|
|
6870
|
+
let propsFilteredObj = filterSvgElProps(nodeName, props, { removeIds, removeClassNames, removeDefaults, removeNameSpaced, exclude, cleanUpStrokes, include: [...transformsStandalone, ...include], cleanUpStrokes: false });
|
|
6819
6871
|
props = propsFilteredObj.propsFiltered;
|
|
6820
6872
|
remove.push(...propsFilteredObj.remove);
|
|
6821
6873
|
}
|
|
@@ -7149,13 +7201,21 @@
|
|
|
7149
7201
|
removeInvalid = true,
|
|
7150
7202
|
removeDefaults = true,
|
|
7151
7203
|
allowDataAtts = true,
|
|
7204
|
+
allowMeta = false,
|
|
7205
|
+
allowAriaAtts = false,
|
|
7152
7206
|
cleanUpStrokes = true,
|
|
7153
|
-
|
|
7207
|
+
|
|
7208
|
+
include=[],
|
|
7209
|
+
removeIds=false,
|
|
7210
|
+
removeClassNames=false,
|
|
7154
7211
|
exclude = [],
|
|
7155
7212
|
} = {}) {
|
|
7156
7213
|
let propsFiltered = {};
|
|
7157
7214
|
let remove = [];
|
|
7158
7215
|
|
|
7216
|
+
if(!removeIds) include.push('id');
|
|
7217
|
+
if(!removeClassNames) include.push('class');
|
|
7218
|
+
|
|
7159
7219
|
// allow defaults for nested
|
|
7160
7220
|
|
|
7161
7221
|
let noStrokeColor = cleanUpStrokes ? (props['stroke'] === undefined) : false;
|
|
@@ -7170,25 +7230,35 @@
|
|
|
7170
7230
|
false;
|
|
7171
7231
|
|
|
7172
7232
|
// remove null transforms
|
|
7173
|
-
if(prop==='transform' && value==='matrix(1 0 0 1 0 0)') isValid = false;
|
|
7233
|
+
if (prop === 'transform' && value === 'matrix(1 0 0 1 0 0)') isValid = false;
|
|
7174
7234
|
|
|
7175
7235
|
// allow data attributes
|
|
7176
7236
|
let isDataAtt = allowDataAtts ? prop.startsWith('data-') : false;
|
|
7237
|
+
let isMeta = allowMeta && prop === 'title';
|
|
7238
|
+
let isAria = allowAriaAtts && prop.startsWith('aria-');
|
|
7177
7239
|
|
|
7178
7240
|
// filter out defaults
|
|
7179
7241
|
let isDefault = removeDefaults ?
|
|
7180
7242
|
(attLookup.defaults[prop] ? attLookup.defaults[prop] !== undefined && attLookup.defaults[prop].includes(value) : false) :
|
|
7181
7243
|
false;
|
|
7182
7244
|
|
|
7245
|
+
let isFutileStroke = noStrokeColor && strokeAtts.includes(prop);
|
|
7246
|
+
|
|
7247
|
+
if (isDefault || isDataAtt || isMeta || isAria || isFutileStroke) isValid = false;
|
|
7248
|
+
if (include.includes(prop)) isValid = true;
|
|
7249
|
+
|
|
7250
|
+
/*
|
|
7183
7251
|
if (isDataAtt || include.includes(prop)) isValid = true;
|
|
7184
|
-
if (isDefault) isValid = false
|
|
7252
|
+
if (isDefault) isValid = false
|
|
7185
7253
|
if (exclude.length && exclude.includes(prop)) isValid = false;
|
|
7186
|
-
if (noStrokeColor && strokeAtts.includes(prop)) isValid = false
|
|
7254
|
+
if (noStrokeColor && strokeAtts.includes(prop)) isValid = false
|
|
7255
|
+
*/
|
|
7187
7256
|
|
|
7188
7257
|
if (isValid) {
|
|
7189
7258
|
propsFiltered[prop] = props[prop];
|
|
7190
7259
|
}
|
|
7191
7260
|
else {
|
|
7261
|
+
|
|
7192
7262
|
remove.push(prop);
|
|
7193
7263
|
}
|
|
7194
7264
|
}
|
|
@@ -7287,6 +7357,23 @@
|
|
|
7287
7357
|
return props
|
|
7288
7358
|
}
|
|
7289
7359
|
|
|
7360
|
+
function toCamelCase(str) {
|
|
7361
|
+
return str
|
|
7362
|
+
.split(/[-| ]/)
|
|
7363
|
+
.map((e,i) => i
|
|
7364
|
+
? e.charAt(0).toUpperCase() + e.slice(1).toLowerCase()
|
|
7365
|
+
: e.toLowerCase()
|
|
7366
|
+
)
|
|
7367
|
+
.join('')
|
|
7368
|
+
}
|
|
7369
|
+
|
|
7370
|
+
function toShortStr(str){
|
|
7371
|
+
if(isNumericValue(str)) return str
|
|
7372
|
+
let strShort = str.split('-').map(str=>{return str.replace(/a|e|i|o|u/g,'') }).join('-');
|
|
7373
|
+
strShort = toCamelCase(strShort);
|
|
7374
|
+
return strShort
|
|
7375
|
+
}
|
|
7376
|
+
|
|
7290
7377
|
function removeEmptySVGEls(svg) {
|
|
7291
7378
|
let els = svg.querySelectorAll('g, defs');
|
|
7292
7379
|
els.forEach(el => {
|
|
@@ -7298,6 +7385,8 @@
|
|
|
7298
7385
|
removeHidden = true,
|
|
7299
7386
|
|
|
7300
7387
|
stylesToAttributes = true,
|
|
7388
|
+
attributesToGroup = false,
|
|
7389
|
+
|
|
7301
7390
|
removePrologue = true,
|
|
7302
7391
|
removeIds = false,
|
|
7303
7392
|
removeClassNames = false,
|
|
@@ -7317,9 +7406,14 @@
|
|
|
7317
7406
|
|
|
7318
7407
|
mergePaths = false,
|
|
7319
7408
|
removeOffCanvas = true,
|
|
7409
|
+
|
|
7320
7410
|
cleanupSVGAtts = true,
|
|
7321
7411
|
removeNameSpaced = true,
|
|
7322
|
-
|
|
7412
|
+
|
|
7413
|
+
// meta
|
|
7414
|
+
allowMeta = false,
|
|
7415
|
+
allowDataAtts = true,
|
|
7416
|
+
allowAriaAtts = true,
|
|
7323
7417
|
|
|
7324
7418
|
shapeConvert = false,
|
|
7325
7419
|
convert_rects = false,
|
|
@@ -7334,6 +7428,8 @@
|
|
|
7334
7428
|
excludedEls = [],
|
|
7335
7429
|
} = {}) {
|
|
7336
7430
|
|
|
7431
|
+
if (attributesToGroup) stylesToAttributes = true;
|
|
7432
|
+
|
|
7337
7433
|
// replace namespaced refs
|
|
7338
7434
|
if (fixHref) svgMarkup = svgMarkup.replaceAll("xlink:href=", "href=");
|
|
7339
7435
|
|
|
@@ -7351,9 +7447,16 @@
|
|
|
7351
7447
|
normalizeTransforms,
|
|
7352
7448
|
removeDefaults: false,
|
|
7353
7449
|
cleanUpStrokes: false,
|
|
7450
|
+
allowMeta,
|
|
7451
|
+
allowDataAtts,
|
|
7452
|
+
allowAriaAtts,
|
|
7354
7453
|
autoRoundValues,
|
|
7454
|
+
removeIds,
|
|
7455
|
+
removeClassNames,
|
|
7355
7456
|
minifyRgbColors,
|
|
7356
7457
|
};
|
|
7458
|
+
|
|
7459
|
+
// root svg properties
|
|
7357
7460
|
let stylePropsSVG = parseStylesProperties(svg, propOptions);
|
|
7358
7461
|
|
|
7359
7462
|
// add svg font size for scaling relative
|
|
@@ -7365,11 +7468,9 @@
|
|
|
7365
7468
|
* be inherited by children
|
|
7366
7469
|
*/
|
|
7367
7470
|
let groups = svg.querySelectorAll('g');
|
|
7368
|
-
let groupProps = [];
|
|
7369
7471
|
|
|
7370
7472
|
groups.forEach(g => {
|
|
7371
7473
|
let stylePropsG = parseStylesProperties(g, propOptions);
|
|
7372
|
-
groupProps.push(stylePropsG);
|
|
7373
7474
|
let children = g.querySelectorAll(`${renderedEls.join(', ')}`);
|
|
7374
7475
|
|
|
7375
7476
|
// store parent styles to child property
|
|
@@ -7383,12 +7484,29 @@
|
|
|
7383
7484
|
|
|
7384
7485
|
if (cleanupSVGAtts) {
|
|
7385
7486
|
|
|
7386
|
-
let allowed = ['viewBox', 'xmlns', 'width', 'height'
|
|
7487
|
+
let allowed = new Set(['viewBox', 'xmlns', 'width', 'height']);
|
|
7488
|
+
|
|
7489
|
+
if (!removeIds) allowed.add('id');
|
|
7490
|
+
if (!removeClassNames) allowed.add('class');
|
|
7491
|
+
if (removeDimensions) {
|
|
7492
|
+
allowed.delete('width');
|
|
7493
|
+
allowed.delete('height');
|
|
7494
|
+
}
|
|
7495
|
+
|
|
7496
|
+
allowed = Array.from(allowed);
|
|
7387
7497
|
if (!stylesToAttributes) {
|
|
7388
7498
|
allowed.push('fill', 'stroke', 'stroke-width', 'stroke-linecap', 'stroke-linejoin', 'font-size', 'font-family', 'font-style', 'style');
|
|
7389
7499
|
}
|
|
7390
7500
|
|
|
7391
|
-
removeExcludedAttribues(svg, allowed);
|
|
7501
|
+
removeExcludedAttribues(svg, { allowed, allowMeta, allowAriaAtts, allowDataAtts });
|
|
7502
|
+
}
|
|
7503
|
+
|
|
7504
|
+
// remove meta
|
|
7505
|
+
if (!allowMeta) {
|
|
7506
|
+
let metaEls = svg.querySelectorAll('meta, metadata, desc, title');
|
|
7507
|
+
metaEls.forEach(meta => {
|
|
7508
|
+
meta.remove();
|
|
7509
|
+
});
|
|
7392
7510
|
}
|
|
7393
7511
|
|
|
7394
7512
|
// add viewBox
|
|
@@ -7405,9 +7523,10 @@
|
|
|
7405
7523
|
if (removeOffCanvas) removeOffCanvasEls(svg, { x, y, width, height });
|
|
7406
7524
|
|
|
7407
7525
|
// always remove scripts
|
|
7408
|
-
let removeEls = ['metadata', 'script', ...excludedEls];
|
|
7409
7526
|
|
|
7410
|
-
|
|
7527
|
+
let removeEls = ['script', ...excludedEls];
|
|
7528
|
+
|
|
7529
|
+
removeSVGEls(svg, { remove: removeEls, removeNameSpaced });
|
|
7411
7530
|
|
|
7412
7531
|
// an array of all elements' properties
|
|
7413
7532
|
let svgElProps = [];
|
|
@@ -7433,6 +7552,7 @@
|
|
|
7433
7552
|
* to user units
|
|
7434
7553
|
*/
|
|
7435
7554
|
let styleProps = parseStylesProperties(el, propOptions);
|
|
7555
|
+
let stylePropsFiltered = {};
|
|
7436
7556
|
|
|
7437
7557
|
// get parent styles
|
|
7438
7558
|
let { parentStyleProps = [] } = el;
|
|
@@ -7458,27 +7578,25 @@
|
|
|
7458
7578
|
styleProps.transformArr = transFormInherited;
|
|
7459
7579
|
|
|
7460
7580
|
// merge with svg props
|
|
7581
|
+
|
|
7461
7582
|
styleProps = {
|
|
7462
7583
|
...stylePropsSVG,
|
|
7463
7584
|
...inheritedProps,
|
|
7464
7585
|
...styleProps
|
|
7465
7586
|
};
|
|
7466
7587
|
|
|
7588
|
+
// dont inherit class
|
|
7589
|
+
if (stylePropsSVG['class'] === styleProps['class']) {
|
|
7590
|
+
delete styleProps['class'];
|
|
7591
|
+
}
|
|
7592
|
+
|
|
7467
7593
|
// add combined transforms
|
|
7468
7594
|
addTransFormProps(styleProps, transFormInherited);
|
|
7469
7595
|
|
|
7470
7596
|
let { remove, matrix, transComponents } = styleProps;
|
|
7471
7597
|
|
|
7472
|
-
// mark attributes for removal
|
|
7473
|
-
if (removeClassNames) styleProps.remove.push('class');
|
|
7474
|
-
if (removeIds) styleProps.remove.push('id');
|
|
7475
|
-
if (removeDimensions) {
|
|
7476
|
-
styleProps.remove.push('width');
|
|
7477
|
-
styleProps.remove.push('height');
|
|
7478
|
-
}
|
|
7479
|
-
|
|
7480
7598
|
// styles to atts
|
|
7481
|
-
if (unGroup || convertTransforms || minifyRgbColors
|
|
7599
|
+
if (unGroup || convertTransforms || minifyRgbColors) stylesToAttributes = true;
|
|
7482
7600
|
|
|
7483
7601
|
if (stylesToAttributes) {
|
|
7484
7602
|
|
|
@@ -7501,7 +7619,6 @@
|
|
|
7501
7619
|
styleProps.cy[0] = [styleProps.cy[0] * scaleX + translateY];
|
|
7502
7620
|
|
|
7503
7621
|
if (styleProps.r) styleProps.r[0] = [styleProps.r[0] * scaleX];
|
|
7504
|
-
|
|
7505
7622
|
if (styleProps.rx) styleProps.rx[0] = [styleProps.rx[0] * scaleX];
|
|
7506
7623
|
if (styleProps.ry) styleProps.ry[0] = [styleProps.ry[0] * scaleX];
|
|
7507
7624
|
|
|
@@ -7523,6 +7640,12 @@
|
|
|
7523
7640
|
styleProps.height = [styleProps.height[0] * scaleX];
|
|
7524
7641
|
}
|
|
7525
7642
|
|
|
7643
|
+
// remove now obsolete transform properties
|
|
7644
|
+
delete styleProps.matrix;
|
|
7645
|
+
delete styleProps.transformArr;
|
|
7646
|
+
delete styleProps.transComponents;
|
|
7647
|
+
|
|
7648
|
+
// mark transform attribute for removal
|
|
7526
7649
|
remove.push('transform');
|
|
7527
7650
|
|
|
7528
7651
|
// scale props like stroke width or dash-array
|
|
@@ -7538,17 +7661,16 @@
|
|
|
7538
7661
|
* apply consolidated
|
|
7539
7662
|
* element attributes
|
|
7540
7663
|
*/
|
|
7541
|
-
|
|
7542
|
-
|
|
7543
|
-
{ removeDefaults: true, cleanUpStrokes });
|
|
7664
|
+
stylePropsFiltered = filterSvgElProps(name, styleProps,
|
|
7665
|
+
{ removeDefaults: true, cleanUpStrokes, allowMeta, allowAriaAtts, allowDataAtts, removeIds });
|
|
7544
7666
|
|
|
7545
7667
|
remove = [...remove, ...stylePropsFiltered.remove];
|
|
7546
7668
|
|
|
7547
7669
|
for (let prop in stylePropsFiltered.propsFiltered) {
|
|
7548
7670
|
let values = styleProps[prop];
|
|
7549
|
-
|
|
7550
7671
|
let val = values.length ? values.join(' ') : values[0];
|
|
7551
7672
|
el.setAttribute(prop, val);
|
|
7673
|
+
|
|
7552
7674
|
}
|
|
7553
7675
|
|
|
7554
7676
|
// remove obsolete attributes
|
|
@@ -7576,9 +7698,19 @@
|
|
|
7576
7698
|
});
|
|
7577
7699
|
} else {
|
|
7578
7700
|
groups.forEach((g, i) => {
|
|
7579
|
-
|
|
7701
|
+
|
|
7702
|
+
let atts = Object.keys(getElementAtts(g));
|
|
7703
|
+
|
|
7580
7704
|
atts.forEach(att => {
|
|
7581
|
-
|
|
7705
|
+
|
|
7706
|
+
let isData = !allowDataAtts && att.startsWith('data-');
|
|
7707
|
+
let isAria = !allowAriaAtts && att.startsWith('aria-');
|
|
7708
|
+
|
|
7709
|
+
remove.push('transform', 'style');
|
|
7710
|
+
|
|
7711
|
+
if (remove.includes(att) || isData || isAria) {
|
|
7712
|
+
g.removeAttribute(att);
|
|
7713
|
+
}
|
|
7582
7714
|
});
|
|
7583
7715
|
});
|
|
7584
7716
|
|
|
@@ -7622,7 +7754,7 @@
|
|
|
7622
7754
|
el.replaceWith(path);
|
|
7623
7755
|
|
|
7624
7756
|
name = 'path';
|
|
7625
|
-
el = path;
|
|
7757
|
+
el = path; // required for node
|
|
7626
7758
|
|
|
7627
7759
|
}
|
|
7628
7760
|
|
|
@@ -7633,14 +7765,217 @@
|
|
|
7633
7765
|
let paths = svg.querySelectorAll('path');
|
|
7634
7766
|
paths.forEach(path => {
|
|
7635
7767
|
let shape = pathElToShape(path, { convert_rects, convert_ellipses, convert_poly, convert_lines });
|
|
7636
|
-
|
|
7768
|
+
|
|
7637
7769
|
path = shape;
|
|
7638
7770
|
});
|
|
7639
7771
|
|
|
7640
7772
|
}
|
|
7641
7773
|
|
|
7774
|
+
/**
|
|
7775
|
+
* combine styles
|
|
7776
|
+
* store in node property
|
|
7777
|
+
*/
|
|
7778
|
+
|
|
7779
|
+
if (mergePaths || attributesToGroup) {
|
|
7780
|
+
|
|
7781
|
+
let options = { allowMeta, allowAriaAtts, removeIds, removeClassNames, allowDataAtts };
|
|
7782
|
+
|
|
7783
|
+
/**
|
|
7784
|
+
* exclude properties for
|
|
7785
|
+
* adjacent path merging
|
|
7786
|
+
* e.g ignore classnames or ids
|
|
7787
|
+
*/
|
|
7788
|
+
if(mergePaths){
|
|
7789
|
+
options.removeIds = true;
|
|
7790
|
+
options.removeClassNames = true;
|
|
7791
|
+
options.allowAriaAtts = false;
|
|
7792
|
+
options.allowMeta = false;
|
|
7793
|
+
}
|
|
7794
|
+
|
|
7795
|
+
stylePropsFiltered = filterSvgElProps(name, styleProps, options).propsFiltered;
|
|
7796
|
+
|
|
7797
|
+
for (let prop in stylePropsFiltered) {
|
|
7798
|
+
|
|
7799
|
+
if (geometryProps.includes(prop)) continue;
|
|
7800
|
+
|
|
7801
|
+
let values = stylePropsFiltered[prop];
|
|
7802
|
+
let val = values.length ? values.join(' ') : values[0];
|
|
7803
|
+
|
|
7804
|
+
let propShort = toShortStr(prop);
|
|
7805
|
+
let valShort = toShortStr(val);
|
|
7806
|
+
let propStr = `${propShort}-${valShort}`;
|
|
7807
|
+
|
|
7808
|
+
// store in node property
|
|
7809
|
+
if (!el.styleSet) el.styleSet = new Set();
|
|
7810
|
+
el.styleSet.add(propStr);
|
|
7811
|
+
}
|
|
7812
|
+
|
|
7813
|
+
}
|
|
7814
|
+
|
|
7642
7815
|
}//endof element loop
|
|
7643
7816
|
|
|
7817
|
+
/**
|
|
7818
|
+
* merge paths with same styles
|
|
7819
|
+
*/
|
|
7820
|
+
if (mergePaths) {
|
|
7821
|
+
let paths = svg.querySelectorAll('path');
|
|
7822
|
+
let len = paths.length;
|
|
7823
|
+
|
|
7824
|
+
if (len) {
|
|
7825
|
+
let path0 = paths[0];
|
|
7826
|
+
let d0 = path0.getAttribute('d');
|
|
7827
|
+
let stylePrev = path0.styleSet !== undefined ? [...path0.styleSet].join('_') : '';
|
|
7828
|
+
|
|
7829
|
+
for (let i = 1; i < len; i++) {
|
|
7830
|
+
let path = paths[i];
|
|
7831
|
+
let style = path.styleSet !== undefined ? [...path.styleSet].join('_') : '';
|
|
7832
|
+
let isSibling = path.previousElementSibling === path0;
|
|
7833
|
+
let d = path.getAttribute('d');
|
|
7834
|
+
let isAbs = d.startsWith('M');
|
|
7835
|
+
|
|
7836
|
+
if (isSibling && style === stylePrev) {
|
|
7837
|
+
let dAbs = isAbs ? d : parsePathDataString(d).pathData.map(com => `${com.type} ${com.values.join(' ')}`).join(' ');
|
|
7838
|
+
|
|
7839
|
+
d0 += dAbs;
|
|
7840
|
+
path0.setAttribute('d', d0);
|
|
7841
|
+
path.remove();
|
|
7842
|
+
|
|
7843
|
+
} else {
|
|
7844
|
+
path0 = path;
|
|
7845
|
+
d0 = isAbs ? d : parsePathDataString(d).pathData.map(com => `${com.type} ${com.values.join(' ')}`).join(' ');
|
|
7846
|
+
}
|
|
7847
|
+
|
|
7848
|
+
// update style
|
|
7849
|
+
stylePrev = style;
|
|
7850
|
+
}
|
|
7851
|
+
}
|
|
7852
|
+
|
|
7853
|
+
/**
|
|
7854
|
+
* shared styles to group
|
|
7855
|
+
*/
|
|
7856
|
+
|
|
7857
|
+
if (attributesToGroup) {
|
|
7858
|
+
let els = svg.querySelectorAll(geometryEls.join(', '));
|
|
7859
|
+
let len = els.length;
|
|
7860
|
+
|
|
7861
|
+
let el0 = els[0] || null;
|
|
7862
|
+
let stylePrev = el0.styleSet !== undefined ? [...el0.styleSet].join('_') : '';
|
|
7863
|
+
|
|
7864
|
+
// all props
|
|
7865
|
+
let allProps = {};
|
|
7866
|
+
|
|
7867
|
+
// find attributes shared by all
|
|
7868
|
+
let globalAtts = [];
|
|
7869
|
+
|
|
7870
|
+
if (len) {
|
|
7871
|
+
|
|
7872
|
+
let groups = [[el0]];
|
|
7873
|
+
let idx = 0;
|
|
7874
|
+
let elPrev = el0;
|
|
7875
|
+
|
|
7876
|
+
for (let i = 0; i < len; i++) {
|
|
7877
|
+
let el = els[i];
|
|
7878
|
+
let atts = getElementAtts(el);
|
|
7879
|
+
for (let att in atts) {
|
|
7880
|
+
let att_str = `${att}_${atts[att]}`;
|
|
7881
|
+
|
|
7882
|
+
if (!allProps[att_str]) {
|
|
7883
|
+
allProps[att_str] = [];
|
|
7884
|
+
}
|
|
7885
|
+
allProps[att_str].push(el);
|
|
7886
|
+
//
|
|
7887
|
+
if (allProps[att_str].length === len) {
|
|
7888
|
+
globalAtts.push(att);
|
|
7889
|
+
}
|
|
7890
|
+
}
|
|
7891
|
+
}
|
|
7892
|
+
|
|
7893
|
+
// apply global to parent SVG
|
|
7894
|
+
if (globalAtts.length) {
|
|
7895
|
+
let atts0 = getElementAtts(el0);
|
|
7896
|
+
for (let att in atts0) {
|
|
7897
|
+
// &&
|
|
7898
|
+
if (globalAtts.includes(att) && att !== 'transform') {
|
|
7899
|
+
svg.setAttribute(att, atts0[att]);
|
|
7900
|
+
}
|
|
7901
|
+
}
|
|
7902
|
+
}
|
|
7903
|
+
|
|
7904
|
+
// detect groups
|
|
7905
|
+
for (let i = 1; i < len; i++) {
|
|
7906
|
+
let el = els[i];
|
|
7907
|
+
let styleArr = el.styleSet !== undefined ? [...el.styleSet] : [];
|
|
7908
|
+
let style = styleArr.length ? styleArr.join('_') : '';
|
|
7909
|
+
|
|
7910
|
+
// same style add to group
|
|
7911
|
+
if (style === stylePrev && elPrev.nextElementSibling === el) {
|
|
7912
|
+
groups[idx].push(el);
|
|
7913
|
+
}
|
|
7914
|
+
// start new group
|
|
7915
|
+
else {
|
|
7916
|
+
groups.push([el]);
|
|
7917
|
+
idx++;
|
|
7918
|
+
}
|
|
7919
|
+
// update style
|
|
7920
|
+
stylePrev = style;
|
|
7921
|
+
elPrev = el;
|
|
7922
|
+
|
|
7923
|
+
}// endof el loop
|
|
7924
|
+
|
|
7925
|
+
// create groups
|
|
7926
|
+
for (let i = 0; i < groups.length; i++) {
|
|
7927
|
+
let children = groups[i];
|
|
7928
|
+
let child0 = children[0];
|
|
7929
|
+
let atts = getElementAtts(child0);
|
|
7930
|
+
let groupEl = child0.parentNode.closest('g');
|
|
7931
|
+
|
|
7932
|
+
if (children.length === 1) {
|
|
7933
|
+
if (globalAtts.length) {
|
|
7934
|
+
let globalTransform = globalAtts.includes('transform');
|
|
7935
|
+
if (globalTransform) {
|
|
7936
|
+
|
|
7937
|
+
groupEl.setAttribute('transform', atts['transform']);
|
|
7938
|
+
}
|
|
7939
|
+
|
|
7940
|
+
for (let att in atts) {
|
|
7941
|
+
|
|
7942
|
+
if (globalAtts.includes(att)) {
|
|
7943
|
+
child0.removeAttribute(att);
|
|
7944
|
+
}
|
|
7945
|
+
}
|
|
7946
|
+
}
|
|
7947
|
+
continue
|
|
7948
|
+
}
|
|
7949
|
+
|
|
7950
|
+
// create new group
|
|
7951
|
+
if (!groupEl) {
|
|
7952
|
+
|
|
7953
|
+
groupEl = document.createElementNS(svgNs, 'g');
|
|
7954
|
+
child0.parentNode.insertBefore(groupEl, child0);
|
|
7955
|
+
groupEl.append(...children);
|
|
7956
|
+
}
|
|
7957
|
+
|
|
7958
|
+
// move attributes to group
|
|
7959
|
+
for (let att in atts) {
|
|
7960
|
+
let val = atts[att];
|
|
7961
|
+
|
|
7962
|
+
if (!geometryProps.includes(att)) {
|
|
7963
|
+
if (!globalAtts.includes(att) || att === 'transform') {
|
|
7964
|
+
groupEl.setAttribute(att, val);
|
|
7965
|
+
}
|
|
7966
|
+
children.forEach(child => {
|
|
7967
|
+
child.removeAttribute(att);
|
|
7968
|
+
});
|
|
7969
|
+
}
|
|
7970
|
+
}
|
|
7971
|
+
|
|
7972
|
+
} // endof groups
|
|
7973
|
+
|
|
7974
|
+
}
|
|
7975
|
+
}
|
|
7976
|
+
|
|
7977
|
+
}
|
|
7978
|
+
|
|
7644
7979
|
// remove futile clip-paths
|
|
7645
7980
|
if (cleanupClip) removeFutileClipPaths(svg, { x, y, width, height });
|
|
7646
7981
|
|
|
@@ -7786,21 +8121,41 @@
|
|
|
7786
8121
|
remove = ['metadata', 'script'],
|
|
7787
8122
|
removeNameSpaced = true,
|
|
7788
8123
|
} = {}) {
|
|
8124
|
+
|
|
7789
8125
|
let els = svg.querySelectorAll('*');
|
|
8126
|
+
|
|
8127
|
+
let allowMeta = !remove.includes('metadata');
|
|
8128
|
+
|
|
7790
8129
|
els.forEach(el => {
|
|
7791
8130
|
let nodeName = el.nodeName;
|
|
7792
|
-
|
|
7793
|
-
|
|
8131
|
+
let isMeta = allowMeta && el.closest('metadata');
|
|
8132
|
+
if (
|
|
8133
|
+
!isMeta &&
|
|
8134
|
+
((removeNameSpaced && nodeName.includes(':')) ||
|
|
8135
|
+
remove.includes(nodeName))
|
|
7794
8136
|
) {
|
|
7795
8137
|
el.remove();
|
|
7796
8138
|
}
|
|
7797
8139
|
});
|
|
7798
8140
|
}
|
|
7799
8141
|
|
|
7800
|
-
function removeExcludedAttribues(el,
|
|
8142
|
+
function removeExcludedAttribues(el, {
|
|
8143
|
+
allowed = ['viewBox', 'xmlns', 'width', 'height', 'id', 'class'],
|
|
8144
|
+
allowAriaAtts = true,
|
|
8145
|
+
allowDataAtts = true,
|
|
8146
|
+
allowMeta = false
|
|
8147
|
+
} = {}) {
|
|
7801
8148
|
let atts = [...el.attributes].map((att) => att.name);
|
|
7802
8149
|
atts.forEach((att) => {
|
|
7803
|
-
|
|
8150
|
+
|
|
8151
|
+
let isMeta = allowMeta && (att === 'title');
|
|
8152
|
+
let isAria = allowAriaAtts && att.startsWith('aria-');
|
|
8153
|
+
let isData = allowDataAtts && att.startsWith('data-');
|
|
8154
|
+
|
|
8155
|
+
if (
|
|
8156
|
+
!allowed.includes(att) &&
|
|
8157
|
+
!isAria && !isData && !isMeta
|
|
8158
|
+
) {
|
|
7804
8159
|
el.removeAttribute(att);
|
|
7805
8160
|
}
|
|
7806
8161
|
});
|
|
@@ -9843,6 +10198,7 @@
|
|
|
9843
10198
|
|
|
9844
10199
|
toAbsolute = false,
|
|
9845
10200
|
toRelative = true,
|
|
10201
|
+
toMixed = false,
|
|
9846
10202
|
toShorthands = true,
|
|
9847
10203
|
toLonghands = false,
|
|
9848
10204
|
|
|
@@ -9908,7 +10264,7 @@
|
|
|
9908
10264
|
tolerance = 1,
|
|
9909
10265
|
reversePath = false,
|
|
9910
10266
|
|
|
9911
|
-
minifyRgbColors =
|
|
10267
|
+
minifyRgbColors = true,
|
|
9912
10268
|
removePrologue = true,
|
|
9913
10269
|
removeHidden = true,
|
|
9914
10270
|
removeUnused = true,
|
|
@@ -9921,6 +10277,11 @@
|
|
|
9921
10277
|
legacyHref = false,
|
|
9922
10278
|
removeNameSpaced = true,
|
|
9923
10279
|
|
|
10280
|
+
allowMeta = false,
|
|
10281
|
+
allowDataAtts = true,
|
|
10282
|
+
allowAriaAtts = true,
|
|
10283
|
+
|
|
10284
|
+
attributesToGroup = false,
|
|
9924
10285
|
removeOffCanvas = false,
|
|
9925
10286
|
unGroup = false,
|
|
9926
10287
|
mergePaths = false,
|
|
@@ -10021,7 +10382,7 @@
|
|
|
10021
10382
|
|
|
10022
10383
|
// convert all shapes to paths
|
|
10023
10384
|
if (shapesToPaths) {
|
|
10024
|
-
shapeConvert =
|
|
10385
|
+
shapeConvert = 'toPaths';
|
|
10025
10386
|
convert_rects = true;
|
|
10026
10387
|
convert_ellipses = true;
|
|
10027
10388
|
convert_poly = true;
|
|
@@ -10030,7 +10391,8 @@
|
|
|
10030
10391
|
|
|
10031
10392
|
let svgPropObject = cleanUpSVG(input, {
|
|
10032
10393
|
removeIds, removeClassNames, removeDimensions, cleanupSVGAtts, cleanUpStrokes, removeHidden, removeUnused, removeNameSpaced, stylesToAttributes, removePrologue, fixHref, mergePaths, convertTransforms, legacyHref, cleanupDefs, cleanupClip, addViewBox, removeOffCanvas, addDimensions,
|
|
10033
|
-
shapeConvert, convert_rects, convert_ellipses, convert_poly, convert_lines, minifyRgbColors, unGroup, convertTransforms
|
|
10394
|
+
shapeConvert, convert_rects, convert_ellipses, convert_poly, convert_lines, minifyRgbColors, unGroup, convertTransforms,
|
|
10395
|
+
allowMeta, allowDataAtts, allowAriaAtts, allowMeta, attributesToGroup
|
|
10034
10396
|
}
|
|
10035
10397
|
);
|
|
10036
10398
|
svg = svgPropObject.svg;
|
|
@@ -10055,6 +10417,7 @@
|
|
|
10055
10417
|
// SVG optimization options
|
|
10056
10418
|
let pathOptions = {
|
|
10057
10419
|
toRelative,
|
|
10420
|
+
toMixed,
|
|
10058
10421
|
toAbsolute,
|
|
10059
10422
|
toLonghands,
|
|
10060
10423
|
toShorthands,
|