@cyberalien/svg-utils 1.0.10 → 1.0.11
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/lib/svg-css/animations/attribute.d.ts +11 -0
- package/lib/svg-css/animations/attribute.js +19 -0
- package/lib/svg-css/animations/common.d.ts +8 -0
- package/lib/svg-css/animations/common.js +16 -0
- package/lib/svg-css/animations/find.d.ts +9 -0
- package/lib/svg-css/animations/find.js +48 -0
- package/lib/svg-css/animations/tags.d.ts +1 -9
- package/lib/svg-css/animations/tags.js +3 -14
- package/lib/svg-css/animations/types.d.ts +19 -0
- package/lib/svg-css/animations/types.js +1 -0
- package/lib/svg-css/props/prop.d.ts +10 -1
- package/lib/svg-css/props/prop.js +6 -4
- package/lib/svg-css/props/props.js +8 -4
- package/lib/xml/stringify.d.ts +2 -2
- package/lib/xml/stringify.js +5 -1
- package/package.json +1 -1
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ParsedXMLTagElement } from "../../xml/types.js";
|
|
2
|
+
import { getSVGPropertyType } from "../props/prop.js";
|
|
3
|
+
interface CheckResult {
|
|
4
|
+
attributeName: string;
|
|
5
|
+
type: ReturnType<typeof getSVGPropertyType>;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Get animated attribute name and type
|
|
9
|
+
*/
|
|
10
|
+
declare function getAnimatedAttributeData(node: ParsedXMLTagElement, stack: ParsedXMLTagElement[], supportLegacyBrowsers?: boolean): undefined | CheckResult;
|
|
11
|
+
export { getAnimatedAttributeData };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { getSVGPropertyType } from "../props/prop.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Get animated attribute name and type
|
|
5
|
+
*/
|
|
6
|
+
function getAnimatedAttributeData(node, stack, supportLegacyBrowsers) {
|
|
7
|
+
const parentNode = stack[stack.length - 1];
|
|
8
|
+
if (!parentNode) return;
|
|
9
|
+
const parentTag = parentNode.tag;
|
|
10
|
+
const attributeName = node.attribs.attributeName;
|
|
11
|
+
if (typeof attributeName !== "string") return;
|
|
12
|
+
const type = getSVGPropertyType(parentTag, attributeName, supportLegacyBrowsers);
|
|
13
|
+
return type ? {
|
|
14
|
+
attributeName,
|
|
15
|
+
type
|
|
16
|
+
} : void 0;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export { getAnimatedAttributeData };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ParsedXMLTagElement } from "../../xml/types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Check for common failures
|
|
4
|
+
*
|
|
5
|
+
* Returns true on success
|
|
6
|
+
*/
|
|
7
|
+
declare function checkAnimationTagForCompatibility(node: ParsedXMLTagElement): boolean | undefined;
|
|
8
|
+
export { checkAnimationTagForCompatibility };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
const supportedValues = {
|
|
2
|
+
additive: "replace",
|
|
3
|
+
accumulate: "none"
|
|
4
|
+
};
|
|
5
|
+
/**
|
|
6
|
+
* Check for common failures
|
|
7
|
+
*
|
|
8
|
+
* Returns true on success
|
|
9
|
+
*/
|
|
10
|
+
function checkAnimationTagForCompatibility(node) {
|
|
11
|
+
if (node.children.length) return;
|
|
12
|
+
const attribs = node.attribs;
|
|
13
|
+
for (const attr in supportedValues) if (attribs[attr] && attribs[attr] !== supportedValues[attr]) return;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export { checkAnimationTagForCompatibility };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ParsedXMLTagElement } from "../../xml/types.js";
|
|
2
|
+
import { FindSVGAnimationsOptions, SVGAnimationsContext } from "./types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Find all animations in SVG tree
|
|
5
|
+
*
|
|
6
|
+
* @todo Implement this
|
|
7
|
+
*/
|
|
8
|
+
declare function findAnimationsInSVGTree(root: ParsedXMLTagElement[], options: FindSVGAnimationsOptions): SVGAnimationsContext;
|
|
9
|
+
export { findAnimationsInSVGTree };
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { iterateXMLContent } from "../../xml/iterate.js";
|
|
2
|
+
import { svgAnimateMotionTag, svgAnimateTransformTag, svgAnimationTag, svgSetTag } from "./tags.js";
|
|
3
|
+
import { getAnimatedAttributeData } from "./attribute.js";
|
|
4
|
+
import { checkAnimationTagForCompatibility } from "./common.js";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Find all animations in SVG tree
|
|
8
|
+
*
|
|
9
|
+
* @todo Implement this
|
|
10
|
+
*/
|
|
11
|
+
function findAnimationsInSVGTree(root, options) {
|
|
12
|
+
const animatedProperties = /* @__PURE__ */ new Map();
|
|
13
|
+
let failed = false;
|
|
14
|
+
const context = {
|
|
15
|
+
failed,
|
|
16
|
+
animatedProperties
|
|
17
|
+
};
|
|
18
|
+
iterateXMLContent(root, (node, stack) => {
|
|
19
|
+
if (context.failed || node.type !== "tag") return;
|
|
20
|
+
switch (node.tag) {
|
|
21
|
+
case svgAnimateMotionTag:
|
|
22
|
+
failed = true;
|
|
23
|
+
return "abort";
|
|
24
|
+
case svgAnimateTransformTag:
|
|
25
|
+
if (!checkAnimationTagForCompatibility(node)) {
|
|
26
|
+
failed = true;
|
|
27
|
+
return "abort";
|
|
28
|
+
}
|
|
29
|
+
failed = true;
|
|
30
|
+
return "abort";
|
|
31
|
+
case svgSetTag:
|
|
32
|
+
case svgAnimationTag:
|
|
33
|
+
if (!checkAnimationTagForCompatibility(node)) {
|
|
34
|
+
failed = true;
|
|
35
|
+
return "abort";
|
|
36
|
+
}
|
|
37
|
+
break;
|
|
38
|
+
default: return;
|
|
39
|
+
}
|
|
40
|
+
if (!getAnimatedAttributeData(node, stack, options.supportLegacyBrowsers)) {
|
|
41
|
+
failed = true;
|
|
42
|
+
return "abort";
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
return failed ? { failed: true } : context;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export { findAnimationsInSVGTree };
|
|
@@ -2,18 +2,10 @@
|
|
|
2
2
|
* Tag used to set attribute value without animation duration
|
|
3
3
|
*/
|
|
4
4
|
declare const svgSetTag = "set";
|
|
5
|
-
/**
|
|
6
|
-
* Tag to discard animation
|
|
7
|
-
*/
|
|
8
|
-
declare const svgDiscardTag = "discard";
|
|
9
5
|
/**
|
|
10
6
|
* Attribute animation tag
|
|
11
7
|
*/
|
|
12
8
|
declare const svgAnimationTag = "animate";
|
|
13
|
-
/**
|
|
14
|
-
* Tags for animating one attribute in SVG
|
|
15
|
-
*/
|
|
16
|
-
declare const svgSimpleAnimationTags: string[];
|
|
17
9
|
/**
|
|
18
10
|
* Tag for animating transformations in SVG
|
|
19
11
|
*/
|
|
@@ -26,4 +18,4 @@ declare const svgAnimateMotionTag = "animateMotion";
|
|
|
26
18
|
* All tags for animating SVG
|
|
27
19
|
*/
|
|
28
20
|
declare const svgAnimationTags: string[];
|
|
29
|
-
export { svgAnimateMotionTag, svgAnimateTransformTag, svgAnimationTag, svgAnimationTags,
|
|
21
|
+
export { svgAnimateMotionTag, svgAnimateTransformTag, svgAnimationTag, svgAnimationTags, svgSetTag };
|
|
@@ -3,22 +3,10 @@
|
|
|
3
3
|
*/
|
|
4
4
|
const svgSetTag = "set";
|
|
5
5
|
/**
|
|
6
|
-
* Tag to discard animation
|
|
7
|
-
*/
|
|
8
|
-
const svgDiscardTag = "discard";
|
|
9
|
-
/**
|
|
10
6
|
* Attribute animation tag
|
|
11
7
|
*/
|
|
12
8
|
const svgAnimationTag = "animate";
|
|
13
9
|
/**
|
|
14
|
-
* Tags for animating one attribute in SVG
|
|
15
|
-
*/
|
|
16
|
-
const svgSimpleAnimationTags = [
|
|
17
|
-
svgSetTag,
|
|
18
|
-
svgDiscardTag,
|
|
19
|
-
svgAnimationTag
|
|
20
|
-
];
|
|
21
|
-
/**
|
|
22
10
|
* Tag for animating transformations in SVG
|
|
23
11
|
*/
|
|
24
12
|
const svgAnimateTransformTag = "animateTransform";
|
|
@@ -30,9 +18,10 @@ const svgAnimateMotionTag = "animateMotion";
|
|
|
30
18
|
* All tags for animating SVG
|
|
31
19
|
*/
|
|
32
20
|
const svgAnimationTags = [
|
|
33
|
-
|
|
21
|
+
svgSetTag,
|
|
22
|
+
svgAnimationTag,
|
|
34
23
|
svgAnimateTransformTag,
|
|
35
24
|
svgAnimateMotionTag
|
|
36
25
|
];
|
|
37
26
|
|
|
38
|
-
export { svgAnimateMotionTag, svgAnimateTransformTag, svgAnimationTag, svgAnimationTags,
|
|
27
|
+
export { svgAnimateMotionTag, svgAnimateTransformTag, svgAnimationTag, svgAnimationTags, svgSetTag };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { ParsedXMLTagElement } from "../../xml/types.js";
|
|
2
|
+
/**
|
|
3
|
+
* SVG animations context
|
|
4
|
+
*/
|
|
5
|
+
interface FailedSVGAnimationsContext {
|
|
6
|
+
failed: true;
|
|
7
|
+
}
|
|
8
|
+
interface SuccessfulSVGAnimationsContext {
|
|
9
|
+
failed: false;
|
|
10
|
+
animatedProperties: Map<ParsedXMLTagElement, Set<string>>;
|
|
11
|
+
}
|
|
12
|
+
type SVGAnimationsContext = FailedSVGAnimationsContext | SuccessfulSVGAnimationsContext;
|
|
13
|
+
/**
|
|
14
|
+
* Options for finding animations in SVG tree
|
|
15
|
+
*/
|
|
16
|
+
interface FindSVGAnimationsOptions {
|
|
17
|
+
supportLegacyBrowsers?: boolean;
|
|
18
|
+
}
|
|
19
|
+
export { FindSVGAnimationsOptions, SVGAnimationsContext };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
|
@@ -1,5 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SVG property types
|
|
3
|
+
*/
|
|
4
|
+
declare const propTypes: readonly ["path", "px", "raw"];
|
|
5
|
+
type SVGPropertyType = (typeof propTypes)[number];
|
|
6
|
+
/**
|
|
7
|
+
* Get property type
|
|
8
|
+
*/
|
|
9
|
+
declare function getSVGPropertyType(tag: string, prop: string, supportLegacyBrowsers?: boolean): SVGPropertyType | undefined;
|
|
1
10
|
/**
|
|
2
11
|
* Convert property to CSS
|
|
3
12
|
*/
|
|
4
13
|
declare function convertSVGPropertyToCSS(tag: string, prop: string, value: string | number, supportLegacyBrowsers?: boolean): [string, string] | undefined;
|
|
5
|
-
export { convertSVGPropertyToCSS };
|
|
14
|
+
export { convertSVGPropertyToCSS, getSVGPropertyType };
|
|
@@ -46,11 +46,13 @@ const skipTags = [
|
|
|
46
46
|
"set",
|
|
47
47
|
"discard"
|
|
48
48
|
];
|
|
49
|
+
const legacyProps = ["d"];
|
|
49
50
|
/**
|
|
50
51
|
* Get property type
|
|
51
52
|
*/
|
|
52
|
-
function getSVGPropertyType(tag, prop) {
|
|
53
|
+
function getSVGPropertyType(tag, prop, supportLegacyBrowsers = false) {
|
|
53
54
|
if (skipTags.includes(tag)) return;
|
|
55
|
+
if (supportLegacyBrowsers && legacyProps.includes(prop)) return;
|
|
54
56
|
for (const type of propTypes) if (props[tag]?.[type]?.includes(prop) || props["*"]?.[type]?.includes(prop)) return type;
|
|
55
57
|
if (prop.startsWith("stroke") || prop.startsWith("fill")) return "raw";
|
|
56
58
|
}
|
|
@@ -58,9 +60,9 @@ function getSVGPropertyType(tag, prop) {
|
|
|
58
60
|
* Convert property to CSS
|
|
59
61
|
*/
|
|
60
62
|
function convertSVGPropertyToCSS(tag, prop, value, supportLegacyBrowsers = false) {
|
|
61
|
-
switch (getSVGPropertyType(tag, prop)) {
|
|
63
|
+
switch (getSVGPropertyType(tag, prop, supportLegacyBrowsers)) {
|
|
62
64
|
case "path":
|
|
63
|
-
if (
|
|
65
|
+
if (typeof value !== "string") return;
|
|
64
66
|
return [prop, `path("${value.replace(/\s+/g, " ")}")`];
|
|
65
67
|
case "px":
|
|
66
68
|
if (typeof value === "string" && !value.match(/^[0-9.-]+$/)) return [prop, value];
|
|
@@ -71,4 +73,4 @@ function convertSVGPropertyToCSS(tag, prop, value, supportLegacyBrowsers = false
|
|
|
71
73
|
}
|
|
72
74
|
}
|
|
73
75
|
|
|
74
|
-
export { convertSVGPropertyToCSS };
|
|
76
|
+
export { convertSVGPropertyToCSS, getSVGPropertyType };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { iterateXMLContent } from "../../xml/iterate.js";
|
|
2
2
|
import { convertSVGPropertyToCSS } from "./prop.js";
|
|
3
|
-
import { svgAnimateTransformTag,
|
|
3
|
+
import { svgAnimateTransformTag, svgAnimationTag, svgSetTag } from "../animations/tags.js";
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Extract SVG tag properties that can be converted to CSS
|
|
@@ -14,12 +14,16 @@ function extractSVGTagPropertiesForCSS(tag, supportLegacyBrowsers = false) {
|
|
|
14
14
|
};
|
|
15
15
|
const animatedProps = /* @__PURE__ */ new Set();
|
|
16
16
|
iterateXMLContent(tag.children, (node) => {
|
|
17
|
-
if (node.type === "tag") {
|
|
18
|
-
|
|
17
|
+
if (node.type === "tag") switch (node.tag) {
|
|
18
|
+
case svgSetTag:
|
|
19
|
+
case svgAnimationTag: {
|
|
19
20
|
const prop = node.attribs.attributeName;
|
|
20
21
|
if (typeof prop === "string") animatedProps.add(prop);
|
|
22
|
+
break;
|
|
21
23
|
}
|
|
22
|
-
|
|
24
|
+
case svgAnimateTransformTag:
|
|
25
|
+
animatedProps.add("transform");
|
|
26
|
+
break;
|
|
23
27
|
}
|
|
24
28
|
});
|
|
25
29
|
for (const prop in tag.attribs) if (!animatedProps.has(prop)) {
|
package/lib/xml/stringify.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ParsedXMLNode, StringifyXMLOptions } from "./types.js";
|
|
2
2
|
/**
|
|
3
3
|
* Convert parsed XML content to string
|
|
4
4
|
*/
|
|
5
|
-
declare function stringifyXMLContent(root:
|
|
5
|
+
declare function stringifyXMLContent(root: ParsedXMLNode[], options?: StringifyXMLOptions): string | null;
|
|
6
6
|
export { stringifyXMLContent };
|
package/lib/xml/stringify.js
CHANGED
|
@@ -18,6 +18,10 @@ function stringifyXMLContent(root, options) {
|
|
|
18
18
|
const tabs = (length) => tab.repeat(length);
|
|
19
19
|
const nl = prettyPrint === false ? "" : "\n";
|
|
20
20
|
const add = (node, depth) => {
|
|
21
|
+
if (node.type !== "tag") {
|
|
22
|
+
output += node.content;
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
21
25
|
output += tabs(depth) + "<" + node.tag;
|
|
22
26
|
for (const key in node.attribs) {
|
|
23
27
|
const value = node.attribs[key];
|
|
@@ -31,7 +35,7 @@ function stringifyXMLContent(root, options) {
|
|
|
31
35
|
}
|
|
32
36
|
}
|
|
33
37
|
if (!node.children.length) {
|
|
34
|
-
if (fullOptions.useSelfClosing) output += " />" + nl;
|
|
38
|
+
if (fullOptions.useSelfClosing) output += (prettyPrint ? " " : "") + "/>" + nl;
|
|
35
39
|
else output += "></" + node.tag + ">" + nl;
|
|
36
40
|
return true;
|
|
37
41
|
}
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"type": "module",
|
|
4
4
|
"description": "Common functions for working with SVG used by various packages.",
|
|
5
5
|
"author": "Vjacheslav Trushkin",
|
|
6
|
-
"version": "1.0.
|
|
6
|
+
"version": "1.0.11",
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"bugs": "https://github.com/cyberalien/svg-utils/issues",
|
|
9
9
|
"homepage": "https://cyberalien.dev/",
|