@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.
@@ -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, svgDiscardTag, svgSetTag, svgSimpleAnimationTags };
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
- ...svgSimpleAnimationTags,
21
+ svgSetTag,
22
+ svgAnimationTag,
34
23
  svgAnimateTransformTag,
35
24
  svgAnimateMotionTag
36
25
  ];
37
26
 
38
- export { svgAnimateMotionTag, svgAnimateTransformTag, svgAnimationTag, svgAnimationTags, svgDiscardTag, svgSetTag, svgSimpleAnimationTags };
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 (supportLegacyBrowsers || typeof value !== "string") return;
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, svgSimpleAnimationTags } from "../animations/tags.js";
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
- if (svgSimpleAnimationTags.includes(node.tag)) {
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
- if (node.tag === svgAnimateTransformTag) animatedProps.add("transform");
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)) {
@@ -1,6 +1,6 @@
1
- import { ParsedXMLTagElement, StringifyXMLOptions } from "./types.js";
1
+ import { ParsedXMLNode, StringifyXMLOptions } from "./types.js";
2
2
  /**
3
3
  * Convert parsed XML content to string
4
4
  */
5
- declare function stringifyXMLContent(root: ParsedXMLTagElement[], options?: StringifyXMLOptions): string | null;
5
+ declare function stringifyXMLContent(root: ParsedXMLNode[], options?: StringifyXMLOptions): string | null;
6
6
  export { stringifyXMLContent };
@@ -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.10",
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/",