svg-path-simplify 0.4.2 → 0.4.4
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 +21 -0
- package/README.md +7 -4
- package/dist/svg-path-simplify.esm.js +3593 -1279
- package/dist/svg-path-simplify.esm.min.js +2 -2
- package/dist/svg-path-simplify.js +3594 -1278
- package/dist/svg-path-simplify.min.js +2 -2
- package/dist/svg-path-simplify.pathdata.esm.js +1017 -538
- package/dist/svg-path-simplify.pathdata.esm.min.js +2 -2
- package/dist/svg-path-simplify.poly.cjs +9 -8
- package/docs/privacy-webapp.md +24 -0
- package/index.html +331 -152
- package/package.json +1 -1
- package/src/constants.js +4 -0
- package/src/css_parse.js +317 -0
- package/src/detect_input.js +76 -28
- package/src/index.js +8 -0
- package/src/pathData_simplify_cubic.js +26 -16
- package/src/pathData_simplify_harmonize_cpts.js +77 -1
- package/src/pathData_simplify_revertToquadratics.js +0 -1
- package/src/pathSimplify-main.js +304 -276
- package/src/pathSimplify-only-pathdata.js +7 -2
- package/src/pathSimplify-presets.js +254 -0
- package/src/poly-fit-curve-schneider.js +14 -7
- package/src/simplify_poly_RC.js +102 -0
- package/src/simplify_poly_RDP.js +109 -1
- package/src/simplify_poly_radial_distance.js +3 -3
- package/src/string_helpers.js +130 -4
- package/src/svg-getAttributes.js +4 -2
- package/src/svgii/convert_units.js +1 -1
- package/src/svgii/geometry.js +322 -5
- package/src/svgii/geometry_bbox_element.js +1 -1
- package/src/svgii/geometry_deduceRadius.js +116 -27
- package/src/svgii/geometry_length.js +253 -0
- package/src/svgii/pathData_analyze.js +18 -0
- package/src/svgii/pathData_convert.js +193 -89
- package/src/svgii/pathData_fix_directions.js +12 -14
- package/src/svgii/pathData_fromPoly.js +3 -3
- package/src/svgii/pathData_getLength.js +86 -0
- package/src/svgii/pathData_parse.js +2 -0
- package/src/svgii/pathData_parse_els.js +66 -68
- package/src/svgii/pathData_reorder.js +122 -16
- package/src/svgii/pathData_simplify_refineCorners.js +130 -35
- package/src/svgii/pathData_simplify_refine_round.js +420 -0
- package/src/svgii/pathData_split_to_groups.js +168 -0
- package/src/svgii/pathData_stringify.js +26 -64
- package/src/svgii/pathData_toPolygon.js +3 -4
- package/src/svgii/poly_analyze.js +61 -0
- package/src/svgii/poly_normalize.js +11 -2
- package/src/svgii/poly_to_pathdata.js +85 -24
- package/src/svgii/rounding.js +80 -78
- package/src/svgii/svg_cleanup.js +421 -619
- package/src/svgii/svg_cleanup_convertPathLength.js +39 -0
- package/src/svgii/svg_cleanup_general_svg_atts.js +97 -0
- package/src/svgii/svg_cleanup_normalize_transforms.js +83 -0
- package/src/svgii/svg_cleanup_remove_els_and_atts.js +77 -0
- package/src/svgii/svg_cleanup_ungroup.js +36 -0
- package/src/svgii/svg_el_parse_style_props.js +72 -47
- package/src/svgii/svg_getElementLength.js +67 -0
- package/src/svgii/svg_validate.js +220 -0
- package/tests/testSVG.js +14 -1
- package/src/svgii/pathData_refine_round.js +0 -222
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { scaleProps } from "./svg_cleanup_normalize_transforms";
|
|
2
|
+
import { getElementLength } from "./svg_getElementLength";
|
|
3
|
+
|
|
4
|
+
export function convertPathLengthAtt(el, {
|
|
5
|
+
styleProps = {}
|
|
6
|
+
} = {}) {
|
|
7
|
+
|
|
8
|
+
let pathLength = styleProps['pathLength'];
|
|
9
|
+
|
|
10
|
+
if (pathLength) {
|
|
11
|
+
|
|
12
|
+
//let strokeDasharray
|
|
13
|
+
if ((styleProps['stroke-dasharray'] || styleProps['stroke-dashoffset'])) {
|
|
14
|
+
let elLength = getElementLength(el, {
|
|
15
|
+
pathLength,
|
|
16
|
+
props: styleProps
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
let scale = elLength / pathLength
|
|
20
|
+
styleProps = scaleProps(styleProps, { props: ['stroke-dasharray', 'stroke-dashoffset'], scale })
|
|
21
|
+
|
|
22
|
+
// set absolute
|
|
23
|
+
if (styleProps['stroke-dasharray']) el.setAttribute('stroke-dasharray', styleProps['stroke-dasharray'].join(' '))
|
|
24
|
+
if (styleProps['stroke-dashoffset']) el.setAttribute('stroke-dashoffset', styleProps['stroke-dashoffset'][0])
|
|
25
|
+
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// tag for removal
|
|
29
|
+
delete styleProps['pathLength'];
|
|
30
|
+
styleProps.remove.push('pathLength')
|
|
31
|
+
el.removeAttribute('pathLength')
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return styleProps;
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* general clean up to remove bullshit like
|
|
3
|
+
* version or enable background
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export function cleanupSVGAttributes(svg, {
|
|
7
|
+
removeIds = false,
|
|
8
|
+
removeClassNames = false,
|
|
9
|
+
removeDimensions = false,
|
|
10
|
+
stylesToAttributes = false,
|
|
11
|
+
allowMeta = false,
|
|
12
|
+
allowAriaAtts = false,
|
|
13
|
+
allowDataAtts = false,
|
|
14
|
+
} = {}) {
|
|
15
|
+
|
|
16
|
+
//console.log('cleanupSVGAtts');
|
|
17
|
+
let allowed = new Set(['viewBox', 'xmlns', 'width', 'height']);
|
|
18
|
+
|
|
19
|
+
if (!removeIds) allowed.add('id')
|
|
20
|
+
if (!removeClassNames) allowed.add('class')
|
|
21
|
+
if (removeDimensions) {
|
|
22
|
+
allowed.delete('width')
|
|
23
|
+
allowed.delete('height')
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
allowed = Array.from(allowed)
|
|
27
|
+
if (!stylesToAttributes) {
|
|
28
|
+
allowed.push('fill', 'stroke', 'stroke-width', 'stroke-linecap', 'stroke-linejoin', 'font-size', 'font-family', 'font-style', 'style');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
removeExcludedAttribues(svg, { allowed, allowMeta, allowAriaAtts, allowDataAtts })
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function removeExcludedAttribues(el, {
|
|
35
|
+
allowed = ['viewBox', 'xmlns', 'width', 'height', 'id', 'class'],
|
|
36
|
+
allowAriaAtts = true,
|
|
37
|
+
allowDataAtts = true,
|
|
38
|
+
allowMeta = false
|
|
39
|
+
} = {}) {
|
|
40
|
+
let atts = [...el.attributes].map((att) => att.name);
|
|
41
|
+
atts.forEach((att) => {
|
|
42
|
+
|
|
43
|
+
let isMeta = allowMeta && (att === 'title')
|
|
44
|
+
let isAria = allowAriaAtts && att.startsWith('aria-')
|
|
45
|
+
let isData = allowDataAtts && att.startsWith('data-')
|
|
46
|
+
//console.log(att, isData, 'allowDataAtts', allowDataAtts);
|
|
47
|
+
|
|
48
|
+
if (
|
|
49
|
+
!allowed.includes(att) &&
|
|
50
|
+
!isAria && !isData && !isMeta
|
|
51
|
+
) {
|
|
52
|
+
el.removeAttribute(att);
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
export function removeNameSpaceAtts(el, {
|
|
60
|
+
include = ['xlink:href']
|
|
61
|
+
} = {}) {
|
|
62
|
+
let atts = [...el.attributes].map((att) => att.name);
|
|
63
|
+
atts.forEach((att) => {
|
|
64
|
+
if (att.includes(":") && !include.includes(att)) {
|
|
65
|
+
el.removeAttribute(att);
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
export function removeElAtts(el, exclude = [], include = []) {
|
|
72
|
+
let atts = [...el.attributes].map((att) => att.name);
|
|
73
|
+
atts.forEach((att) => {
|
|
74
|
+
if (exclude.includes(att) && !include.includes(att)) {
|
|
75
|
+
el.removeAttribute(att);
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
/*
|
|
82
|
+
|
|
83
|
+
function cleanSvgPrologue(svgString) {
|
|
84
|
+
return (
|
|
85
|
+
svgString
|
|
86
|
+
// Remove XML prologues like <?xml ... ?>
|
|
87
|
+
.replace(/<\?xml[\s\S]*?\?>/gi, "")
|
|
88
|
+
// Remove DOCTYPE declarations
|
|
89
|
+
.replace(/<!DOCTYPE[\s\S]*?>/gi, "")
|
|
90
|
+
// Remove comments <!-- ... -->
|
|
91
|
+
.replace(/<!--[\s\S]*?-->/g, "")
|
|
92
|
+
// Trim extra whitespace
|
|
93
|
+
.trim()
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
*/
|
|
97
|
+
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { roundTo } from "./rounding";
|
|
2
|
+
|
|
3
|
+
export function setNormalizedTransformsToEl(el, {
|
|
4
|
+
styleProps = {},
|
|
5
|
+
} = {}) {
|
|
6
|
+
let { remove, matrix, transComponents } = styleProps;
|
|
7
|
+
let name = el.nodeName.toLowerCase()
|
|
8
|
+
|
|
9
|
+
if(!matrix) return styleProps;
|
|
10
|
+
|
|
11
|
+
let { rotate, scaleX, scaleY, skewX, translateX, translateY } = transComponents;
|
|
12
|
+
//console.log(rotate, scaleX, scaleY, skewX, skewY, translateX, translateY);
|
|
13
|
+
|
|
14
|
+
// scale attributes instead of transform
|
|
15
|
+
let hasRot = rotate !== 0 || skewX !== 0;
|
|
16
|
+
let unProportional = scaleX !== scaleY;
|
|
17
|
+
let scalableByAtt = ['circle', 'ellipse', 'rect']
|
|
18
|
+
//let needsTrans = (name === 'g') || (hasRot) || unProportional
|
|
19
|
+
let needsTrans = (hasRot) || unProportional
|
|
20
|
+
needsTrans = true
|
|
21
|
+
|
|
22
|
+
if (!needsTrans && scalableByAtt.includes(name)) {
|
|
23
|
+
|
|
24
|
+
if (name === 'circle' || name === 'ellipse') {
|
|
25
|
+
styleProps.cx[0] = [styleProps.cx[0] * scaleX + translateX]
|
|
26
|
+
styleProps.cy[0] = [styleProps.cy[0] * scaleX + translateY]
|
|
27
|
+
|
|
28
|
+
if (styleProps.r) styleProps.r[0] = [styleProps.r[0] * scaleX]
|
|
29
|
+
if (styleProps.rx) styleProps.rx[0] = [styleProps.rx[0] * scaleX]
|
|
30
|
+
if (styleProps.ry) styleProps.ry[0] = [styleProps.ry[0] * scaleX]
|
|
31
|
+
|
|
32
|
+
}
|
|
33
|
+
else if (name === 'rect') {
|
|
34
|
+
let x = styleProps.x ? styleProps.x[0] + translateX : translateX;
|
|
35
|
+
let y = styleProps.y ? styleProps.y[0] + translateY : translateY;
|
|
36
|
+
|
|
37
|
+
let rx = styleProps.rx ? styleProps.rx[0] * scaleX : 0;
|
|
38
|
+
let ry = styleProps.ry ? styleProps.ry[0] * scaleY : 0;
|
|
39
|
+
|
|
40
|
+
styleProps.x = [x]
|
|
41
|
+
styleProps.y = [y]
|
|
42
|
+
|
|
43
|
+
styleProps.rx = [rx]
|
|
44
|
+
styleProps.ry = [ry]
|
|
45
|
+
|
|
46
|
+
styleProps.width = [styleProps.width[0] * scaleX]
|
|
47
|
+
styleProps.height = [styleProps.height[0] * scaleX]
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// remove now obsolete transform properties
|
|
51
|
+
delete styleProps.matrix
|
|
52
|
+
delete styleProps.transformArr
|
|
53
|
+
delete styleProps.transComponents
|
|
54
|
+
|
|
55
|
+
// mark transform attribute for removal
|
|
56
|
+
styleProps.remove.push('transform')
|
|
57
|
+
|
|
58
|
+
// scale props like stroke width or dash-array
|
|
59
|
+
styleProps = scaleProps(styleProps, { props: ['stroke-width', 'stroke-dasharray'], scale: scaleX })
|
|
60
|
+
|
|
61
|
+
} else {
|
|
62
|
+
el.setAttribute('transform', transComponents.matrixAtt)
|
|
63
|
+
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return styleProps
|
|
67
|
+
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
export function scaleProps(styleProps = {}, { props = [], scale = 1 } = {}, round = true) {
|
|
73
|
+
if (scale === 1 || !props.length) return props;
|
|
74
|
+
|
|
75
|
+
for (let i = 0; i < props.length; i++) {
|
|
76
|
+
let prop = props[i];
|
|
77
|
+
|
|
78
|
+
if (styleProps[prop] !== undefined) {
|
|
79
|
+
styleProps[prop] = styleProps[prop].map(val => round ? roundTo(val * scale, 2) : val * scale)
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return styleProps
|
|
83
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
export function removeHiddenSvgEls(svg) {
|
|
2
|
+
let els = svg.querySelectorAll('*')
|
|
3
|
+
els.forEach(el => {
|
|
4
|
+
let name = el.nodeName.toLowerCase()
|
|
5
|
+
let style = el.getAttribute('style') || ''
|
|
6
|
+
let isHiddenByStyle = style ? style.trim().includes('display:none') : false;
|
|
7
|
+
let isHidden = (el.getAttribute('display') && el.getAttribute('display') === 'none') || isHiddenByStyle;
|
|
8
|
+
if (isHidden) el.remove();
|
|
9
|
+
})
|
|
10
|
+
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
export function removeSvgEls(svg, {
|
|
17
|
+
removeElements = [],
|
|
18
|
+
removeNameSpaced = true,
|
|
19
|
+
} = {}) {
|
|
20
|
+
|
|
21
|
+
// always remove scripts
|
|
22
|
+
removeElements.push('script');
|
|
23
|
+
|
|
24
|
+
let els = svg.querySelectorAll('*')
|
|
25
|
+
let allowMeta = !removeElements.includes('metadata');
|
|
26
|
+
|
|
27
|
+
els.forEach(el => {
|
|
28
|
+
let nodeName = el.nodeName;
|
|
29
|
+
let isMeta = allowMeta && el.closest('metadata')
|
|
30
|
+
if (
|
|
31
|
+
!isMeta &&
|
|
32
|
+
((removeNameSpaced && nodeName.includes(':')) ||
|
|
33
|
+
removeElements.includes(nodeName))
|
|
34
|
+
) {
|
|
35
|
+
el.remove()
|
|
36
|
+
}
|
|
37
|
+
})
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
/*export function removeSvgEls(svg, remove = []) {
|
|
43
|
+
// remove elements
|
|
44
|
+
if (remove.length) {
|
|
45
|
+
let selector = remove.join(', ').replaceAll(':', '\\:');
|
|
46
|
+
svg.querySelectorAll(selector).forEach(el => {
|
|
47
|
+
el.remove()
|
|
48
|
+
})
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
*/
|
|
52
|
+
|
|
53
|
+
export function removeSvgAtts(svg, remove = []) {
|
|
54
|
+
removeAtts(svg, remove)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function removeAtts(el, remove = []) {
|
|
58
|
+
remove.forEach(att => {
|
|
59
|
+
el.removeAttribute(att);
|
|
60
|
+
})
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
export function removeSvgChildAtts(svg, remove = []) {
|
|
65
|
+
if (remove.length) {
|
|
66
|
+
let selector = remove.map(att => { return `[${att}]` }).join(', ')
|
|
67
|
+
// escape name spaced
|
|
68
|
+
.replaceAll(':', '\\:')
|
|
69
|
+
|
|
70
|
+
svg.querySelectorAll(selector).forEach(el => {
|
|
71
|
+
remove.forEach(att => {
|
|
72
|
+
el.removeAttribute(att);
|
|
73
|
+
})
|
|
74
|
+
})
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { getElementAtts } from "../svg-getAttributes";
|
|
2
|
+
|
|
3
|
+
export function ungroupElements(groups) {
|
|
4
|
+
groups.forEach((g, i) => {
|
|
5
|
+
let children = [...g.children];
|
|
6
|
+
|
|
7
|
+
children.forEach(child => {
|
|
8
|
+
g.parentNode.insertBefore(child, g)
|
|
9
|
+
})
|
|
10
|
+
g.remove()
|
|
11
|
+
})
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
export function removeGroupProps(groups, {
|
|
16
|
+
remove = [],
|
|
17
|
+
allowDataAtts = true,
|
|
18
|
+
allowAriaAtts = true
|
|
19
|
+
} = {}) {
|
|
20
|
+
|
|
21
|
+
groups.forEach((g, i) => {
|
|
22
|
+
let atts = Object.keys(getElementAtts(g));
|
|
23
|
+
|
|
24
|
+
atts.forEach(att => {
|
|
25
|
+
//console.log('remove', remove);
|
|
26
|
+
let isData = !allowDataAtts && att.startsWith('data-')
|
|
27
|
+
let isAria = !allowAriaAtts && att.startsWith('aria-')
|
|
28
|
+
//console.log(isData, att);
|
|
29
|
+
//styleProps.remove.push('transform', 'style')
|
|
30
|
+
if (remove.includes(att) || isData || isAria) {
|
|
31
|
+
g.removeAttribute(att)
|
|
32
|
+
}
|
|
33
|
+
})
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
}
|
|
@@ -18,16 +18,19 @@ export function parseStylesProperties(el, {
|
|
|
18
18
|
autoRoundValues = false,
|
|
19
19
|
minifyRgbColors = false,
|
|
20
20
|
removeInvalid = true,
|
|
21
|
+
allowDataAtts = true,
|
|
22
|
+
allowAriaAtts = true,
|
|
21
23
|
removeDefaults = true,
|
|
22
24
|
cleanUpStrokes = true,
|
|
23
25
|
normalizeTransforms = true,
|
|
24
|
-
removeIds=false,
|
|
25
|
-
removeClassNames=false,
|
|
26
|
+
removeIds = false,
|
|
27
|
+
removeClassNames = false,
|
|
26
28
|
|
|
27
|
-
include=[],
|
|
29
|
+
include = [],
|
|
28
30
|
exclude = [],
|
|
29
31
|
width = 0,
|
|
30
32
|
height = 0,
|
|
33
|
+
stylesheetProps = {}
|
|
31
34
|
} = {}) {
|
|
32
35
|
|
|
33
36
|
//autoRoundValues = false;
|
|
@@ -35,22 +38,52 @@ export function parseStylesProperties(el, {
|
|
|
35
38
|
|
|
36
39
|
let nodeName = el.nodeName.toLowerCase();
|
|
37
40
|
let attProps = getSvgPresentationAtts(el)
|
|
38
|
-
let
|
|
41
|
+
let inlineCssProps = getSvgCssProps(el)
|
|
42
|
+
|
|
43
|
+
// get CSS properties from SVG style element
|
|
44
|
+
let cssRuleSelectors = el.cssRules || [];
|
|
45
|
+
let cssProps = {};
|
|
46
|
+
|
|
47
|
+
cssRuleSelectors.forEach(selector => {
|
|
48
|
+
for (let prop in stylesheetProps[selector]) {
|
|
49
|
+
let val = stylesheetProps[selector][prop];
|
|
50
|
+
//console.log('!!val', val);
|
|
51
|
+
|
|
52
|
+
// check CSS vars
|
|
53
|
+
if (val.startsWith('var(')) {
|
|
54
|
+
let varName = val.replace(/[var\(|\)]/g, '').trim()
|
|
55
|
+
//console.log('!!isvar', val, varName, stylesheetProps[':root']);
|
|
56
|
+
if (stylesheetProps[':root']) {
|
|
57
|
+
val = `var(${varName}, ${stylesheetProps[':root'][varName]})`
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
cssProps[prop] = val
|
|
61
|
+
}
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
//console.log('cssProps', cssProps);
|
|
65
|
+
//console.log('styleSheetProps', cssRuleSelectors, stylesheetProps);
|
|
39
66
|
|
|
40
67
|
/**
|
|
41
|
-
* merge props
|
|
42
|
-
*
|
|
68
|
+
* merge props by specificity
|
|
69
|
+
* 1. attributes
|
|
70
|
+
* 2. CSS rules
|
|
71
|
+
* 3. inline CSS
|
|
43
72
|
*/
|
|
44
73
|
let props = {
|
|
45
74
|
...attProps,
|
|
46
75
|
...cssProps,
|
|
76
|
+
...inlineCssProps,
|
|
47
77
|
}
|
|
48
78
|
|
|
49
79
|
//console.log('!props combined', props);
|
|
50
80
|
|
|
51
|
-
|
|
81
|
+
// obsolete/not style relevant anymore
|
|
52
82
|
delete props['style'];
|
|
53
|
-
|
|
83
|
+
delete props['class'];
|
|
84
|
+
delete props['id'];
|
|
85
|
+
|
|
86
|
+
exclude.push('style', 'class', 'id')
|
|
54
87
|
|
|
55
88
|
let remove = ['style']
|
|
56
89
|
let transformsStandalone = ['scale', 'translate', 'rotate'];
|
|
@@ -61,9 +94,10 @@ export function parseStylesProperties(el, {
|
|
|
61
94
|
*/
|
|
62
95
|
|
|
63
96
|
if (removeInvalid || removeDefaults || removeNameSpaced) {
|
|
64
|
-
let propsFilteredObj = filterSvgElProps(nodeName, props, { removeIds, removeClassNames, removeDefaults, removeNameSpaced, exclude, cleanUpStrokes, include: [...transformsStandalone, ...include], cleanUpStrokes: false })
|
|
97
|
+
let propsFilteredObj = filterSvgElProps(nodeName, props, { allowDataAtts, allowAriaAtts, removeIds, removeClassNames, removeDefaults, removeNameSpaced, exclude, cleanUpStrokes, include: [...transformsStandalone, ...include], cleanUpStrokes: false })
|
|
65
98
|
props = propsFilteredObj.propsFiltered
|
|
66
99
|
remove.push(...propsFilteredObj.remove)
|
|
100
|
+
//console.log(propsFilteredObj.remove, allowDataAtts, allowAriaAtts);
|
|
67
101
|
}
|
|
68
102
|
|
|
69
103
|
//console.log('???props', nodeName, props, remove);
|
|
@@ -84,11 +118,16 @@ export function parseStylesProperties(el, {
|
|
|
84
118
|
|
|
85
119
|
// minify rgb values
|
|
86
120
|
if (minifyRgbColors && colorProps.includes(prop)) {
|
|
121
|
+
//console.log(minifyRgbColors, nodeName, prop, valueStr);
|
|
122
|
+
|
|
87
123
|
let color = parseColor(valueStr)
|
|
124
|
+
|
|
88
125
|
if (color.mode === 'rgba' || color.mode === 'rgb') {
|
|
89
126
|
let hex = rgba2Hex(color)
|
|
90
127
|
valueStr = hex;
|
|
91
128
|
}
|
|
129
|
+
//console.log(nodeName, color, valueStr);
|
|
130
|
+
|
|
92
131
|
}
|
|
93
132
|
|
|
94
133
|
|
|
@@ -131,7 +170,6 @@ export function parseStylesProperties(el, {
|
|
|
131
170
|
else {
|
|
132
171
|
//console.log('other', prop);
|
|
133
172
|
item.values = parseValue(valueStr);
|
|
134
|
-
|
|
135
173
|
}
|
|
136
174
|
|
|
137
175
|
if (item.values.length) {
|
|
@@ -158,10 +196,11 @@ export function parseStylesProperties(el, {
|
|
|
158
196
|
|
|
159
197
|
if (prop !== 'transforms') {
|
|
160
198
|
|
|
161
|
-
|
|
199
|
+
//cleanUpStrokes &&
|
|
200
|
+
if ((prop === 'stroke-dasharray' || prop === 'stroke-dashoffset')) {
|
|
162
201
|
normalizedDiagonal = true
|
|
163
202
|
for (let i = 0; i < values.length; i++) {
|
|
164
|
-
let val = normalizeUnits(values[i].value, { unit: values[i].unit, width, height, normalizedDiagonal, fontSize })
|
|
203
|
+
let val = normalizeUnits(values[i].value, { unit: values[i].unit, width, height, normalizedDiagonal, fontSize, autoRoundValues })
|
|
165
204
|
valsNew.push(val)
|
|
166
205
|
}
|
|
167
206
|
}
|
|
@@ -206,14 +245,12 @@ export function parseStylesProperties(el, {
|
|
|
206
245
|
if (prop === 'scale' && unit === '%') {
|
|
207
246
|
valAbs = valAbs * 0.01;
|
|
208
247
|
} else {
|
|
209
|
-
if (prop === 'r')
|
|
248
|
+
if (prop === 'r' && width!==height) normalizedDiagonal = true;
|
|
210
249
|
valAbs = normalizeUnits(val.value, { unit, width, height, isHorizontal, isVertical, normalizedDiagonal, fontSize })
|
|
211
250
|
|
|
212
251
|
if (autoRoundValues && isNumeric) {
|
|
213
252
|
valAbs = autoRound(valAbs)
|
|
214
253
|
}
|
|
215
|
-
|
|
216
|
-
//console.log('norm', prop, valAbs, 'val', val, unit, isHorizontal, isVertical, width, height, 'isNumeric', isNumeric);
|
|
217
254
|
}
|
|
218
255
|
}
|
|
219
256
|
valsNew.push(valAbs)
|
|
@@ -423,23 +460,25 @@ export function filterSvgElProps(elNodename = '', props = {}, {
|
|
|
423
460
|
allowAriaAtts = false,
|
|
424
461
|
cleanUpStrokes = true,
|
|
425
462
|
//include = ['id', 'class'],
|
|
426
|
-
include=[],
|
|
427
|
-
removeIds=false,
|
|
428
|
-
removeClassNames=false,
|
|
463
|
+
include = [],
|
|
464
|
+
removeIds = false,
|
|
465
|
+
removeClassNames = false,
|
|
429
466
|
exclude = [],
|
|
467
|
+
inheritedProps = null,
|
|
430
468
|
} = {}) {
|
|
431
469
|
let propsFiltered = {}
|
|
432
470
|
let remove = [];
|
|
433
471
|
|
|
434
|
-
if(!removeIds) include.push('id')
|
|
435
|
-
if(!removeClassNames) include.push('class')
|
|
472
|
+
if (!removeIds) include.push('id')
|
|
473
|
+
if (!removeClassNames) include.push('class')
|
|
436
474
|
//console.log('???include', 'removeIds', removeIds, include);
|
|
437
475
|
|
|
476
|
+
|
|
438
477
|
// allow defaults for nested
|
|
439
478
|
//removeDefaults = false;
|
|
440
479
|
|
|
441
|
-
let noStrokeColor = cleanUpStrokes ? (props['stroke'] === undefined) : false;
|
|
442
|
-
//console.log('noStrokeColor', elNodename, 'cleanUpStrokes', cleanUpStrokes);
|
|
480
|
+
let noStrokeColor = cleanUpStrokes ? (props['stroke'] === undefined || props['stroke'][0] === 'none') : false;
|
|
481
|
+
//console.log('noStrokeColor', elNodename, 'cleanUpStrokes', cleanUpStrokes, 'noStrokeColor', noStrokeColor);
|
|
443
482
|
|
|
444
483
|
for (let prop in props) {
|
|
445
484
|
let values = props[prop]
|
|
@@ -451,13 +490,16 @@ export function filterSvgElProps(elNodename = '', props = {}, {
|
|
|
451
490
|
(attLookup.atts[prop] ? attLookup.atts[prop].includes(elNodename) : false) :
|
|
452
491
|
false;
|
|
453
492
|
|
|
493
|
+
|
|
454
494
|
// remove null transforms
|
|
455
495
|
if (prop === 'transform' && value === 'matrix(1 0 0 1 0 0)') isValid = false;
|
|
456
496
|
|
|
457
497
|
// allow data attributes
|
|
458
|
-
let isDataAtt =
|
|
459
|
-
let isMeta =
|
|
460
|
-
let isAria =
|
|
498
|
+
let isDataAtt = prop.startsWith('data-') ? true : false;
|
|
499
|
+
let isMeta = prop === 'title'
|
|
500
|
+
let isAria = prop.startsWith('aria-')
|
|
501
|
+
|
|
502
|
+
if ((allowDataAtts && isDataAtt) || (allowAriaAtts && isAria) || (allowMeta && isMeta)) continue
|
|
461
503
|
|
|
462
504
|
// filter out defaults
|
|
463
505
|
let isDefault = removeDefaults ?
|
|
@@ -468,16 +510,7 @@ export function filterSvgElProps(elNodename = '', props = {}, {
|
|
|
468
510
|
|
|
469
511
|
if (isDefault || isDataAtt || isMeta || isAria || isFutileStroke) isValid = false
|
|
470
512
|
if (include.includes(prop)) isValid = true;
|
|
471
|
-
|
|
472
|
-
//console.log('!valid', prop, isValid);
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
/*
|
|
476
|
-
if (isDataAtt || include.includes(prop)) isValid = true;
|
|
477
|
-
if (isDefault) isValid = false
|
|
478
|
-
if (exclude.length && exclude.includes(prop)) isValid = false;
|
|
479
|
-
if (noStrokeColor && strokeAtts.includes(prop)) isValid = false
|
|
480
|
-
*/
|
|
513
|
+
if (exclude.includes(prop)) isValid = false
|
|
481
514
|
|
|
482
515
|
|
|
483
516
|
if (isValid) {
|
|
@@ -489,23 +522,15 @@ export function filterSvgElProps(elNodename = '', props = {}, {
|
|
|
489
522
|
}
|
|
490
523
|
}
|
|
491
524
|
|
|
492
|
-
/*
|
|
493
|
-
// set explicit stroke width when disabled by stroke color
|
|
494
|
-
if (propsFiltered['stroke'] && propsFiltered['stroke'][0] === 'none') {
|
|
495
|
-
propsFiltered['stroke-width'] = [1]
|
|
496
|
-
remove.push('stroke', 'stroke-width')
|
|
497
|
-
console.log('remove', remove);
|
|
498
|
-
}
|
|
499
|
-
*/
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
//remove=[]
|
|
503
525
|
return { propsFiltered, remove }
|
|
504
526
|
}
|
|
505
527
|
|
|
506
528
|
|
|
507
529
|
export function parseValue(valStr = '') {
|
|
508
|
-
|
|
530
|
+
//exclude url or var functions or font family
|
|
531
|
+
//let exclude = ['font-family', 'url', 'var'];
|
|
532
|
+
valStr = valStr.replace('!important', '');
|
|
533
|
+
let valArr = (valStr.includes("'") || valStr.includes('(') || valStr.includes(')')) ? [valStr] : valStr.split(/,| /).filter(Boolean);
|
|
509
534
|
|
|
510
535
|
for (let i = 0; i < valArr.length; i++) {
|
|
511
536
|
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { getElementAtts } from "../svg-getAttributes";
|
|
2
|
+
import { getDistance } from "./geometry";
|
|
3
|
+
import { getEllipseLength, getPolygonLength } from "./geometry_length";
|
|
4
|
+
import { parsePathDataNormalized } from "./pathData_convert";
|
|
5
|
+
import { getPathDataLength } from "./pathData_getLength";
|
|
6
|
+
import { getPathDataFromEl, rectToPathData } from "./pathData_parse_els";
|
|
7
|
+
import { normalizePoly } from "./poly_normalize";
|
|
8
|
+
|
|
9
|
+
export function getElementLength(el, {
|
|
10
|
+
props = {},
|
|
11
|
+
pathLength = 0,
|
|
12
|
+
} = {}) {
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
let nodeName = el.nodeName;
|
|
16
|
+
let len = 0;
|
|
17
|
+
|
|
18
|
+
props = JSON.parse(JSON.stringify(props))
|
|
19
|
+
|
|
20
|
+
for (let prop in props) {
|
|
21
|
+
if (props[prop] && props[prop].length && props[prop].length === 1) {
|
|
22
|
+
props[prop] = props[prop][0]
|
|
23
|
+
//console.log(prop, props[prop]);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
//console.log(props);
|
|
28
|
+
let { x = 0, y = 0, x1 = 0, y1 = 0, x2 = 0, y2 = 0, width = 0, height = 0, r = 0, rx = 0, ry = 0, cx = 0, cy = 0 } = props;
|
|
29
|
+
|
|
30
|
+
let pts = nodeName === 'polygon' || nodeName === 'polyline' ? el.getAttribute('points') : [];
|
|
31
|
+
let isPolygon = nodeName === 'polygon';
|
|
32
|
+
if (pts.length) {
|
|
33
|
+
pts = normalizePoly(pts);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// we need to convert rects with corner rounding
|
|
37
|
+
let pathData = []
|
|
38
|
+
if (nodeName === 'rect' && (rx || ry)) {
|
|
39
|
+
pathData = rectToPathData(x, y, width, height, rx, ry)
|
|
40
|
+
nodeName = 'path'
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
switch (nodeName) {
|
|
44
|
+
case 'line':
|
|
45
|
+
len = getDistance({ x: x1, y: y1 }, { x: x2, y: y2 });
|
|
46
|
+
break;
|
|
47
|
+
case 'rect':
|
|
48
|
+
len = width * 2 + height * 2;
|
|
49
|
+
break;
|
|
50
|
+
case 'circle':
|
|
51
|
+
len = 2 * Math.PI * r;
|
|
52
|
+
break;
|
|
53
|
+
case 'ellipse':
|
|
54
|
+
len = getEllipseLength(rx, ry);
|
|
55
|
+
break;
|
|
56
|
+
case 'polygon':
|
|
57
|
+
case 'polyline':
|
|
58
|
+
len = getPolygonLength(pts, isPolygon)
|
|
59
|
+
break;
|
|
60
|
+
case 'path':
|
|
61
|
+
pathData = pathData.length ? pathData : parsePathDataNormalized(el.getAttribute('d'));
|
|
62
|
+
len = getPathDataLength(pathData);
|
|
63
|
+
break;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return len
|
|
67
|
+
}
|