@cyberalien/svg-utils 1.0.11 → 1.1.1

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.
Files changed (39) hide show
  1. package/lib/components/helpers/css/generate.js +10 -10
  2. package/lib/components/helpers/filenames/types.d.ts +3 -1
  3. package/lib/components/helpers/filenames/types.js +1 -0
  4. package/lib/components/jsx.js +1 -1
  5. package/lib/components/prepare/iconify.d.ts +1 -1
  6. package/lib/components/svelte.js +1 -1
  7. package/lib/components/types/options.d.ts +2 -1
  8. package/lib/components/vue-func.js +1 -1
  9. package/lib/components/vue.js +1 -1
  10. package/lib/css/hash.d.ts +1 -1
  11. package/lib/css/hash.js +2 -4
  12. package/lib/css/types.d.ts +2 -2
  13. package/lib/helpers/hash/context.d.ts +6 -0
  14. package/lib/helpers/hash/context.js +8 -0
  15. package/lib/helpers/hash/types.d.ts +24 -4
  16. package/lib/helpers/hash/unique.js +3 -4
  17. package/lib/index.d.ts +4 -3
  18. package/lib/index.js +2 -1
  19. package/lib/svg/ids/change.js +2 -2
  20. package/lib/svg/ids/types.d.ts +3 -1
  21. package/lib/svg/ids/unique.d.ts +2 -1
  22. package/lib/svg/ids/unique.js +4 -6
  23. package/lib/svg-css/content.d.ts +1 -1
  24. package/lib/svg-css/props/props.js +1 -1
  25. package/lib/svg-css/root.d.ts +1 -1
  26. package/lib/svg-css/root.js +2 -4
  27. package/lib/svg-css/types.d.ts +1 -3
  28. package/lib/xml/parse.js +9 -9
  29. package/package.json +11 -11
  30. package/lib/svg-css/animations/attribute.d.ts +0 -11
  31. package/lib/svg-css/animations/attribute.js +0 -19
  32. package/lib/svg-css/animations/common.d.ts +0 -8
  33. package/lib/svg-css/animations/common.js +0 -16
  34. package/lib/svg-css/animations/find.d.ts +0 -9
  35. package/lib/svg-css/animations/find.js +0 -48
  36. package/lib/svg-css/animations/types.d.ts +0 -19
  37. package/lib/svg-css/animations/types.js +0 -1
  38. /package/lib/svg-css/{animations → props}/tags.d.ts +0 -0
  39. /package/lib/svg-css/{animations → props}/tags.js +0 -0
@@ -21,51 +21,51 @@ function generateCSSFilesForComponent(content, imports, assets, options) {
21
21
  const mergedContent = [];
22
22
  for (const className in classes) {
23
23
  const baseContent = stringifyCSSSelector(`${classNamePrefix}.${className}`, classes[className]);
24
- let content$1 = baseContent;
24
+ let content = baseContent;
25
25
  if (embedAnimations && keyframes) {
26
26
  for (const animationName in keyframes) if (baseContent.includes(animationName)) {
27
27
  const value = keyframes[animationName];
28
- content$1 += "\n" + (typeof value === "string" ? value : stringifyCSSKeyframes(keyframesPrefix + animationName, value));
28
+ content += "\n" + (typeof value === "string" ? value : stringifyCSSKeyframes(keyframesPrefix + animationName, value));
29
29
  }
30
30
  }
31
31
  if (mergeCSS) {
32
- mergedContent.push(content$1);
32
+ mergedContent.push(content);
33
33
  continue;
34
34
  }
35
35
  const filename = getGeneratedCSSFilename(className, options);
36
36
  assets.push({
37
37
  ...filename,
38
- content: content$1
38
+ content
39
39
  });
40
40
  if (isModule) imports.modules[filename.import] = generateCSSDefaultImportName(className);
41
41
  else imports.css.add(filename.import);
42
42
  }
43
43
  if (!embedAnimations && keyframes) for (const animationName in keyframes) {
44
44
  const value = keyframes[animationName];
45
- const content$1 = typeof value === "string" ? value : stringifyCSSKeyframes(keyframesPrefix + animationName, value);
45
+ const content = typeof value === "string" ? value : stringifyCSSKeyframes(keyframesPrefix + animationName, value);
46
46
  if (mergeCSS) {
47
- mergedContent.push(content$1);
47
+ mergedContent.push(content);
48
48
  continue;
49
49
  }
50
50
  const filename = getGeneratedCSSFilename(animationName, options);
51
51
  assets.push({
52
52
  ...filename,
53
- content: content$1
53
+ content
54
54
  });
55
55
  if (isModule) imports.modules[filename.import] = generateCSSDefaultImportName(animationName);
56
56
  else imports.css.add(filename.import);
57
57
  }
58
58
  if (mergeCSS && mergedContent.length) {
59
- const content$1 = mergedContent.join("\n");
59
+ const content = mergedContent.join("\n");
60
60
  if (typeof mergeCSS == "object") {
61
61
  assets.push({
62
62
  ...mergeCSS,
63
- content: content$1
63
+ content
64
64
  });
65
65
  if (isModule) imports.modules[mergeCSS.import] = "css";
66
66
  else if (!returnCSS) imports.css.add(mergeCSS.import);
67
67
  }
68
- return returnCSS ? content$1 : void 0;
68
+ return returnCSS ? content : void 0;
69
69
  }
70
70
  }
71
71
 
@@ -1,7 +1,9 @@
1
+ import { UniqueHashPartialOptions } from "../../../helpers/hash/types.js";
1
2
  import { FactoryIconData } from "../../types/data.js";
2
3
  import { ComponentFactoryFileSystemOptions, GeneratedAssetPath } from "../../types/options.js";
4
+ interface Options extends Pick<UniqueHashPartialOptions, 'context'>, Pick<ComponentFactoryFileSystemOptions, 'rootPath' | 'doubleDirsForComponents' | 'prefixDirsForComponents' | 'sharedTypes'> {}
3
5
  /**
4
6
  * Generate component types filename based on options
5
7
  */
6
- declare function getGeneratedComponentTypesFilename(icon: Pick<FactoryIconData, 'name' | 'prefix'>, content: string, options: Pick<ComponentFactoryFileSystemOptions, 'rootPath' | 'doubleDirsForComponents' | 'prefixDirsForComponents' | 'sharedTypes'>): GeneratedAssetPath;
8
+ declare function getGeneratedComponentTypesFilename(icon: Pick<FactoryIconData, 'name' | 'prefix'>, content: string, options: Options): GeneratedAssetPath;
7
9
  export { getGeneratedComponentTypesFilename };
@@ -7,6 +7,7 @@ import { getGeneratedComponentFilename } from "../../export/filename.js";
7
7
  */
8
8
  function getGeneratedComponentTypesFilename(icon, content, options) {
9
9
  if (options.sharedTypes) return getGeneratedAssetFilename(`types/${getUniqueHash(content, {
10
+ context: options.context,
10
11
  css: true,
11
12
  length: 8
12
13
  })}.d.ts`, options.rootPath);
@@ -52,7 +52,7 @@ function createJSXComponent(data, options) {
52
52
  value: "props",
53
53
  template: "...props,"
54
54
  };
55
- const getViewBox = (viewBox$1) => isStringViewBox ? `'${stringifyIconViewBox(viewBox$1)}'` : JSON.stringify(minifyViewBox(viewBox$1));
55
+ const getViewBox = (viewBox) => isStringViewBox ? `'${stringifyIconViewBox(viewBox)}'` : JSON.stringify(minifyViewBox(viewBox));
56
56
  if (hasComputedViewbox) {
57
57
  componentExternalCode.push(`const baseViewBox = ${getViewBox(viewBox)};`, `const squareViewBox = ${getViewBox(makeSquareViewBox(viewBox))};`);
58
58
  componentInternalCode.push(`const viewBox = useMemo(() => square ? squareViewBox : baseViewBox, [square]);`);
@@ -9,7 +9,7 @@ interface Options extends ConvertSVGContentOptions {
9
9
  /**
10
10
  * Convert IconifyIcon data to FactoryIconData
11
11
  */
12
- declare function convertIconifyIconToFactoryContent(icon: IconifyIcon, prefix: string, name: string, options?: Options): FactoryIconData;
12
+ declare function convertIconifyIconToFactoryContent(icon: IconifyIcon, prefix: string, name: string, options: Options): FactoryIconData;
13
13
  /**
14
14
  * Create metadata assets for an icon set
15
15
  */
@@ -39,7 +39,7 @@ function createSvelteComponent(data, options) {
39
39
  const props = {};
40
40
  if (!hasFallback) props.xmlns = "http://www.w3.org/2000/svg";
41
41
  const viewBoxPropValue = `viewBox${hasComputedViewbox ? "Computed" : ""}`;
42
- const getViewBox = (viewBox$1) => isStringViewBox ? `'${stringifyIconViewBox(viewBox$1)}'` : JSON.stringify(minifyViewBox(viewBox$1));
42
+ const getViewBox = (viewBox) => isStringViewBox ? `'${stringifyIconViewBox(viewBox)}'` : JSON.stringify(minifyViewBox(viewBox));
43
43
  if (hasComputedViewbox) componentCode.push(`const baseViewBox = ${getViewBox(viewBox)};`, `const squareViewBox = ${getViewBox(makeSquareViewBox(viewBox))};`, `let ${viewBoxPropValue} = $derived(square ? squareViewBox : baseViewBox);`);
44
44
  else componentCode.push(`const ${viewBoxPropValue} = ${getViewBox(viewBox)};`);
45
45
  const ratioValue = getViewBoxRatio(viewBox);
@@ -1,3 +1,4 @@
1
+ import { UniqueHashPartialOptions } from "../../helpers/hash/types.js";
1
2
  import { CSSExportMode } from "./css.js";
2
3
  /**
3
4
  * Asset path, generated from configuration
@@ -31,5 +32,5 @@ interface ComponentFactoryRenderingOptions {
31
32
  /**
32
33
  * Options for component factory
33
34
  */
34
- interface ComponentFactoryOptions extends ComponentFactoryFileSystemOptions, ComponentFactoryRenderingOptions {}
35
+ interface ComponentFactoryOptions extends ComponentFactoryFileSystemOptions, ComponentFactoryRenderingOptions, Pick<UniqueHashPartialOptions, 'context'> {}
35
36
  export { ComponentFactoryFileSystemOptions, ComponentFactoryOptions, ComponentFactoryRenderingOptions, GeneratedAssetPath };
@@ -37,7 +37,7 @@ function createVueFunctionalComponent(data, options) {
37
37
  const componentCode = [];
38
38
  const props = {};
39
39
  if (!hasFallback) props.xmlns = "http://www.w3.org/2000/svg";
40
- const getViewBox = (viewBox$1) => isStringViewBox ? `'${stringifyIconViewBox(viewBox$1)}'` : JSON.stringify(minifyViewBox(viewBox$1));
40
+ const getViewBox = (viewBox) => isStringViewBox ? `'${stringifyIconViewBox(viewBox)}'` : JSON.stringify(minifyViewBox(viewBox));
41
41
  if (hasComputedViewbox) componentCode.push(`const baseViewBox = ${getViewBox(viewBox)};`, `const squareViewBox = ${getViewBox(makeSquareViewBox(viewBox))};`, `const viewBox = computed(() => props.square ? squareViewBox : baseViewBox);`);
42
42
  else componentCode.push(`const viewBox = ${getViewBox(viewBox)};`);
43
43
  const ratioValue = getViewBoxRatio(viewBox);
@@ -37,7 +37,7 @@ function createVueComponent(data, options) {
37
37
  const componentCode = [];
38
38
  const props = {};
39
39
  if (!hasFallback) props.xmlns = "http://www.w3.org/2000/svg";
40
- const getViewBox = (viewBox$1) => isStringViewBox ? `'${stringifyIconViewBox(viewBox$1)}'` : JSON.stringify(minifyViewBox(viewBox$1));
40
+ const getViewBox = (viewBox) => isStringViewBox ? `'${stringifyIconViewBox(viewBox)}'` : JSON.stringify(minifyViewBox(viewBox));
41
41
  if (hasComputedViewbox) componentCode.push(`const baseViewBox = ${getViewBox(viewBox)};`, `const squareViewBox = ${getViewBox(makeSquareViewBox(viewBox))};`, `const viewBox = computed(() => props.square ? squareViewBox : baseViewBox);`);
42
42
  else componentCode.push(`const viewBox = ${getViewBox(viewBox)};`);
43
43
  const ratioValue = getViewBoxRatio(viewBox);
package/lib/css/hash.d.ts CHANGED
@@ -2,5 +2,5 @@ import { CSSHashOptions, CSSRules } from "./types.js";
2
2
  /**
3
3
  * Get class name for CSS rules
4
4
  */
5
- declare function createCSSClassName(rules: CSSRules, prefix?: string, options?: CSSHashOptions): string;
5
+ declare function createCSSClassName(rules: CSSRules, options: CSSHashOptions): string;
6
6
  export { createCSSClassName };
package/lib/css/hash.js CHANGED
@@ -1,15 +1,13 @@
1
1
  import { sortObject } from "../helpers/misc/sort-object.js";
2
2
  import { getUniqueHash } from "../helpers/hash/unique.js";
3
3
 
4
- const length = 6;
5
4
  /**
6
5
  * Get class name for CSS rules
7
6
  */
8
- function createCSSClassName(rules, prefix = "", options) {
7
+ function createCSSClassName(rules, options) {
9
8
  return getUniqueHash(sortObject(rules), {
10
9
  css: true,
11
- length,
12
- prefix,
10
+ length: 6,
13
11
  ...options
14
12
  });
15
13
  }
@@ -1,4 +1,4 @@
1
- import { UniqueHashOptions } from "../helpers/hash/types.js";
1
+ import { UniqueHashPartialOptions } from "../helpers/hash/types.js";
2
2
  /**
3
3
  * CSS rules
4
4
  */
@@ -17,5 +17,5 @@ interface CSSKeyframes {
17
17
  /**
18
18
  * Hash options
19
19
  */
20
- type CSSHashOptions = Partial<Pick<UniqueHashOptions, 'length' | 'lengths' | 'throwOnCollision'>>;
20
+ type CSSHashOptions = UniqueHashPartialOptions;
21
21
  export { CSSHashOptions, CSSKeyframe, CSSKeyframes, CSSRules };
@@ -0,0 +1,6 @@
1
+ import { HashContext } from "./types.js";
2
+ /**
3
+ * Create new hash context, used to make sure all hashes within the same context are unique
4
+ */
5
+ declare function createUniqueHashContext(): HashContext;
6
+ export { createUniqueHashContext };
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Create new hash context, used to make sure all hashes within the same context are unique
3
+ */
4
+ function createUniqueHashContext() {
5
+ return { cache: Object.create(null) };
6
+ }
7
+
8
+ export { createUniqueHashContext };
@@ -1,8 +1,28 @@
1
- interface UniqueHashOptions {
1
+ /**
2
+ * Context for hashing functions, used to ensure uniqueness
3
+ */
4
+ interface HashContext {
5
+ cache?: Record<string, string>;
6
+ }
7
+ /**
8
+ * Length option for hash
9
+ */
10
+ type LengthOption = number | ((content: string) => number);
11
+ /**
12
+ * Partial options, used for extending type
13
+ */
14
+ interface UniqueHashPartialOptions {
15
+ context: HashContext;
2
16
  prefix?: string;
3
- css: boolean;
4
- length: number | ((content: string) => number);
17
+ length?: LengthOption;
5
18
  lengths?: Record<string, number>;
6
19
  throwOnCollision?: boolean;
7
20
  }
8
- export { UniqueHashOptions };
21
+ /**
22
+ * Options for unique hash generation
23
+ */
24
+ interface UniqueHashOptions extends UniqueHashPartialOptions {
25
+ css: boolean;
26
+ length: LengthOption;
27
+ }
28
+ export { HashContext, UniqueHashOptions, UniqueHashPartialOptions };
@@ -2,8 +2,6 @@ import { sortObject } from "../misc/sort-object.js";
2
2
  import { hashToString } from "./stringify.js";
3
3
  import { hashString } from "./hash.js";
4
4
 
5
- const uniqueHashes = Object.create(null);
6
- const uniqueWithPrefixHashes = Object.create(null);
7
5
  /**
8
6
  * Hash an object, make sure hash is unique
9
7
  *
@@ -19,14 +17,15 @@ const uniqueWithPrefixHashes = Object.create(null);
19
17
  * 8 chars = 183t unique hashes
20
18
  */
21
19
  function getUniqueHash(data, options) {
22
- const { length, lengths, css } = options;
20
+ const { length, lengths, css, context } = options;
23
21
  const prefix = options.prefix || "";
24
22
  const str = typeof data === "string" ? data : JSON.stringify(sortObject(data));
25
23
  const hasPrefix = !!prefix;
26
24
  const values = hashString(str);
27
25
  let hash = hashToString(values, css, hasPrefix, typeof length === "function" ? length(str) : length);
28
26
  if (lengths?.[hash]) hash = hashToString(values, css, hasPrefix, lengths[hash]);
29
- const cache = hasPrefix ? uniqueWithPrefixHashes : uniqueHashes;
27
+ if (!context.cache) context.cache = Object.create(null);
28
+ const cache = context.cache;
30
29
  const result = `${prefix}${hash}`;
31
30
  if (!cache[result]) cache[result] = str;
32
31
  else if (cache[result] !== str) {
package/lib/index.d.ts CHANGED
@@ -1,10 +1,11 @@
1
1
  import { ClassProp, classProps, defaultClassProp } from "./classname/const.js";
2
2
  import { splitClassName, toggleClassName } from "./classname/toggle.js";
3
- import { UniqueHashOptions } from "./helpers/hash/types.js";
3
+ import { HashContext, UniqueHashOptions, UniqueHashPartialOptions } from "./helpers/hash/types.js";
4
4
  import { ParsedXMLNode, ParsedXMLTagElement, ParsedXMLTextElement, StringifyXMLOptions } from "./xml/types.js";
5
5
  import { BaseConvertSVGContentOptions, ConvertSVGContentOptions, ConvertedSVGContent } from "./svg-css/types.js";
6
6
  import { createCSSClassName } from "./css/hash.js";
7
7
  import { stringifyCSSKeyframes, stringifyCSSRules, stringifyCSSSelector } from "./css/stringify.js";
8
+ import { createUniqueHashContext } from "./helpers/hash/context.js";
8
9
  import { hashString } from "./helpers/hash/hash.js";
9
10
  import { hashToString } from "./helpers/hash/stringify.js";
10
11
  import { getUniqueHash } from "./helpers/hash/unique.js";
@@ -16,7 +17,7 @@ import { sortObject } from "./helpers/misc/sort-object.js";
16
17
  import { iterateXMLContent } from "./xml/iterate.js";
17
18
  import { parseXMLContent } from "./xml/parse.js";
18
19
  import { stringifyXMLContent } from "./xml/stringify.js";
19
- import { ChangeIDResult } from "./svg/ids/types.js";
20
+ import { ChangeIDResult, UniqueIDOptions } from "./svg/ids/types.js";
20
21
  import { changeIDInString } from "./svg/ids/string.js";
21
22
  import { removeDuplicateIDs } from "./svg/ids/duplicate.js";
22
23
  import { removeUnusedIDs } from "./svg/ids/unused.js";
@@ -24,4 +25,4 @@ import { changeSVGIDs } from "./svg/ids/change.js";
24
25
  import { createUniqueIDs } from "./svg/ids/unique.js";
25
26
  import { convertSVGRootToCSS } from "./svg-css/root.js";
26
27
  import { convertSVGContentToCSSRules } from "./svg-css/content.js";
27
- export { BaseConvertSVGContentOptions, ChangeIDResult, ClassProp, ComparisonKey, ConvertSVGContentOptions, ConvertedSVGContent, ParsedXMLNode, ParsedXMLTagElement, ParsedXMLTextElement, StringifyXMLOptions, UniqueHashOptions, changeIDInString, changeSVGIDs, classProps, cloneObject, compareKeys, compareSets, compareValues, convertSVGContentToCSSRules, convertSVGRootToCSS, createCSSClassName, createUniqueIDs, defaultClassProp, getUniqueHash, hashString, hashToString, iterateXMLContent, parseXMLContent, removeDuplicateIDs, removeUnusedIDs, sortObject, splitClassName, stringifyCSSKeyframes, stringifyCSSRules, stringifyCSSSelector, stringifyXMLContent, toggleClassName, uniquePromise };
28
+ export { BaseConvertSVGContentOptions, ChangeIDResult, ClassProp, ComparisonKey, ConvertSVGContentOptions, ConvertedSVGContent, HashContext, ParsedXMLNode, ParsedXMLTagElement, ParsedXMLTextElement, StringifyXMLOptions, UniqueHashOptions, UniqueHashPartialOptions, UniqueIDOptions, changeIDInString, changeSVGIDs, classProps, cloneObject, compareKeys, compareSets, compareValues, convertSVGContentToCSSRules, convertSVGRootToCSS, createCSSClassName, createUniqueHashContext, createUniqueIDs, defaultClassProp, getUniqueHash, hashString, hashToString, iterateXMLContent, parseXMLContent, removeDuplicateIDs, removeUnusedIDs, sortObject, splitClassName, stringifyCSSKeyframes, stringifyCSSRules, stringifyCSSSelector, stringifyXMLContent, toggleClassName, uniquePromise };
package/lib/index.js CHANGED
@@ -3,6 +3,7 @@ import { sortObject } from "./helpers/misc/sort-object.js";
3
3
  import { compareSets, compareValues } from "./helpers/misc/compare.js";
4
4
  import { compareKeys } from "./helpers/misc/keys.js";
5
5
  import { uniquePromise } from "./helpers/misc/promises.js";
6
+ import { createUniqueHashContext } from "./helpers/hash/context.js";
6
7
  import { hashToString } from "./helpers/hash/stringify.js";
7
8
  import { hashString } from "./helpers/hash/hash.js";
8
9
  import { getUniqueHash } from "./helpers/hash/unique.js";
@@ -21,4 +22,4 @@ import { createUniqueIDs } from "./svg/ids/unique.js";
21
22
  import { convertSVGRootToCSS } from "./svg-css/root.js";
22
23
  import { convertSVGContentToCSSRules } from "./svg-css/content.js";
23
24
 
24
- export { changeIDInString, changeSVGIDs, classProps, cloneObject, compareKeys, compareSets, compareValues, convertSVGContentToCSSRules, convertSVGRootToCSS, createCSSClassName, createUniqueIDs, defaultClassProp, getUniqueHash, hashString, hashToString, iterateXMLContent, parseXMLContent, removeDuplicateIDs, removeUnusedIDs, sortObject, splitClassName, stringifyCSSKeyframes, stringifyCSSRules, stringifyCSSSelector, stringifyXMLContent, toggleClassName, uniquePromise };
25
+ export { changeIDInString, changeSVGIDs, classProps, cloneObject, compareKeys, compareSets, compareValues, convertSVGContentToCSSRules, convertSVGRootToCSS, createCSSClassName, createUniqueHashContext, createUniqueIDs, defaultClassProp, getUniqueHash, hashString, hashToString, iterateXMLContent, parseXMLContent, removeDuplicateIDs, removeUnusedIDs, sortObject, splitClassName, stringifyCSSKeyframes, stringifyCSSRules, stringifyCSSSelector, stringifyXMLContent, toggleClassName, uniquePromise };
@@ -40,8 +40,8 @@ function changeSVGIDs(root, callback) {
40
40
  attrib,
41
41
  id
42
42
  });
43
- [node, ...stack].forEach((node$1) => {
44
- const parentID = idMap.get(node$1);
43
+ [node, ...stack].forEach((node) => {
44
+ const parentID = idMap.get(node);
45
45
  if (parentID) {
46
46
  const nested = nestedIDs.get(parentID) || [];
47
47
  if (!nested.includes(id)) {
@@ -1,6 +1,8 @@
1
+ import { UniqueHashPartialOptions } from "../../helpers/hash/types.js";
1
2
  import { ParsedXMLTagElement } from "../../xml/types.js";
2
3
  interface ChangeIDResult {
3
4
  map: Record<string, ParsedXMLTagElement[]>;
4
5
  usage: Record<string, ParsedXMLTagElement[]>;
5
6
  }
6
- export { ChangeIDResult };
7
+ type UniqueIDOptions = UniqueHashPartialOptions;
8
+ export { ChangeIDResult, UniqueIDOptions };
@@ -1,6 +1,7 @@
1
1
  import { ParsedXMLTagElement } from "../../xml/types.js";
2
+ import { UniqueIDOptions } from "./types.js";
2
3
  /**
3
4
  * Create unique IDs for SVG elements
4
5
  */
5
- declare function createUniqueIDs(root: ParsedXMLTagElement[], prefix?: string): void;
6
+ declare function createUniqueIDs(root: ParsedXMLTagElement[], options: UniqueIDOptions): void;
6
7
  export { createUniqueIDs };
@@ -1,17 +1,15 @@
1
1
  import { getUniqueHash } from "../../helpers/hash/unique.js";
2
2
  import { changeSVGIDs } from "./change.js";
3
3
 
4
- const length = 8;
5
- const lengths = {};
6
4
  /**
7
5
  * Create unique IDs for SVG elements
8
6
  */
9
- function createUniqueIDs(root, prefix = "SVG") {
7
+ function createUniqueIDs(root, options) {
10
8
  changeSVGIDs(root, (id, content) => getUniqueHash(content, {
11
9
  css: false,
12
- prefix,
13
- length,
14
- lengths
10
+ prefix: "SVG",
11
+ length: 8,
12
+ ...options
15
13
  }));
16
14
  }
17
15
 
@@ -2,5 +2,5 @@ import { ConvertSVGContentOptions, ConvertedSVGContent } from "./types.js";
2
2
  /**
3
3
  * Convert SVG content string to SVG+CSS
4
4
  */
5
- declare function convertSVGContentToCSSRules(content: string, options?: ConvertSVGContentOptions): ConvertedSVGContent;
5
+ declare function convertSVGContentToCSSRules(content: string, options: ConvertSVGContentOptions): ConvertedSVGContent;
6
6
  export { convertSVGContentToCSSRules };
@@ -1,6 +1,6 @@
1
1
  import { iterateXMLContent } from "../../xml/iterate.js";
2
2
  import { convertSVGPropertyToCSS } from "./prop.js";
3
- import { svgAnimateTransformTag, svgAnimationTag, svgSetTag } from "../animations/tags.js";
3
+ import { svgAnimateTransformTag, svgAnimationTag, svgSetTag } from "./tags.js";
4
4
 
5
5
  /**
6
6
  * Extract SVG tag properties that can be converted to CSS
@@ -6,5 +6,5 @@ import { BaseConvertSVGContentOptions } from "./types.js";
6
6
  *
7
7
  * Returns used CSS class names with rules
8
8
  */
9
- declare function convertSVGRootToCSS(root: ParsedXMLTagElement[], options?: BaseConvertSVGContentOptions): Record<string, CSSRules>;
9
+ declare function convertSVGRootToCSS(root: ParsedXMLTagElement[], options: BaseConvertSVGContentOptions): Record<string, CSSRules>;
10
10
  export { convertSVGRootToCSS };
@@ -8,15 +8,13 @@ import { extractSVGTagPropertiesForCSS } from "./props/props.js";
8
8
  *
9
9
  * Returns used CSS class names with rules
10
10
  */
11
- function convertSVGRootToCSS(root, options = {}) {
11
+ function convertSVGRootToCSS(root, options) {
12
12
  const rules = Object.create(null);
13
- const hashOptions = options.hashOptions || {};
14
- const classNamePrefix = options.classNamePrefix || "";
15
13
  iterateXMLContent(root, (node) => {
16
14
  if (node.type === "tag") {
17
15
  const props = extractSVGTagPropertiesForCSS(node, options.legacy);
18
16
  if (props) {
19
- const className = createCSSClassName(props.rules, classNamePrefix, hashOptions);
17
+ const className = createCSSClassName(props.rules, options);
20
18
  toggleClassName(node.attribs, className, true);
21
19
  rules[className] = props.rules;
22
20
  }
@@ -3,9 +3,7 @@ import { StringifyXMLOptions } from "../xml/types.js";
3
3
  /**
4
4
  * Options for converting SVG tags to SVG+CSS
5
5
  */
6
- interface BaseConvertSVGContentOptions {
7
- classNamePrefix?: string;
8
- hashOptions?: CSSHashOptions;
6
+ interface BaseConvertSVGContentOptions extends CSSHashOptions {
9
7
  legacy?: boolean;
10
8
  }
11
9
  /**
package/lib/xml/parse.js CHANGED
@@ -16,9 +16,9 @@ function parseXMLContent(content, trim = true) {
16
16
  return rootNodes;
17
17
  }
18
18
  if (content.slice(start, start + 4) === "<!--") {
19
- const end$1 = content.indexOf("-->", start);
20
- if (end$1 === -1) return null;
21
- startIndex = end$1 + 3;
19
+ const end = content.indexOf("-->", start);
20
+ if (end === -1) return null;
21
+ startIndex = end + 3;
22
22
  continue;
23
23
  }
24
24
  const rawText = content.slice(startIndex, start);
@@ -34,8 +34,8 @@ function parseXMLContent(content, trim = true) {
34
34
  let tagContent = content.slice(start + 1, end).trim();
35
35
  if (tagContent.startsWith("/")) {
36
36
  if (!parentNode) return null;
37
- const tagNameMatch$1 = tagContent.slice(1).match(/^[^\s]+/);
38
- if (parentNode.tag !== tagNameMatch$1?.[0]) return null;
37
+ const tagNameMatch = tagContent.slice(1).match(/^[^\s]+/);
38
+ if (parentNode.tag !== tagNameMatch?.[0]) return null;
39
39
  stack.pop();
40
40
  parentNode = stack.length ? stack[stack.length - 1] : null;
41
41
  startIndex = end + 1;
@@ -65,16 +65,16 @@ function parseXMLContent(content, trim = true) {
65
65
  }
66
66
  startIndex = end + 1;
67
67
  if (tagName === "style" && !selfClosing) {
68
- const end$1 = content.indexOf("</style>", startIndex);
69
- if (end$1 === -1) return null;
70
- const css = content.slice(startIndex, end$1).trim();
68
+ const end = content.indexOf("</style>", startIndex);
69
+ if (end === -1) return null;
70
+ const css = content.slice(startIndex, end).trim();
71
71
  if (css.length) parentNode.children.push({
72
72
  type: "text",
73
73
  content: css
74
74
  });
75
75
  stack.pop();
76
76
  parentNode = stack.length ? stack[stack.length - 1] : null;
77
- startIndex = end$1 + 8;
77
+ startIndex = end + 8;
78
78
  }
79
79
  } while (true);
80
80
  }
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.11",
6
+ "version": "1.1.1",
7
7
  "license": "MIT",
8
8
  "bugs": "https://github.com/cyberalien/svg-utils/issues",
9
9
  "homepage": "https://cyberalien.dev/",
@@ -23,18 +23,18 @@
23
23
  "@iconify/types": "^2.0.0"
24
24
  },
25
25
  "devDependencies": {
26
- "@eslint/eslintrc": "^3.3.1",
27
- "@eslint/js": "^9.39.1",
28
- "@iconify-json/ri": "^1.2.6",
26
+ "@eslint/eslintrc": "^3.3.3",
27
+ "@eslint/js": "^9.39.2",
28
+ "@iconify-json/ri": "^1.2.8",
29
29
  "@types/jest": "^30.0.0",
30
- "@types/node": "^24.10.0",
31
- "@typescript-eslint/eslint-plugin": "^8.46.4",
32
- "@typescript-eslint/parser": "^8.46.4",
33
- "eslint": "^9.39.1",
34
- "globals": "^16.5.0",
35
- "tsdown": "^0.15.12",
30
+ "@types/node": "^25.1.0",
31
+ "@typescript-eslint/eslint-plugin": "^8.54.0",
32
+ "@typescript-eslint/parser": "^8.54.0",
33
+ "eslint": "^9.39.2",
34
+ "globals": "^17.2.0",
35
+ "tsdown": "^0.20.1",
36
36
  "typescript": "^5.9.3",
37
- "vitest": "^4.0.8"
37
+ "vitest": "^4.0.18"
38
38
  },
39
39
  "scripts": {
40
40
  "lint": "eslint --fix src/**/*.ts && tsc --noemit",
@@ -1,11 +0,0 @@
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 };
@@ -1,19 +0,0 @@
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 };
@@ -1,8 +0,0 @@
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 };
@@ -1,16 +0,0 @@
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 };
@@ -1,9 +0,0 @@
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 };
@@ -1,48 +0,0 @@
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 };
@@ -1,19 +0,0 @@
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 };
@@ -1 +0,0 @@
1
- export { };
File without changes
File without changes