@cyberalien/svg-utils 1.0.0 → 1.0.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/README.md ADDED
@@ -0,0 +1,17 @@
1
+ # SVG Utils
2
+
3
+ Common functions for working with SVG used by various packages.
4
+
5
+ Usable in any environment.
6
+
7
+ The only dependency is types package with TypeScript definition.
8
+
9
+ ## Documentation
10
+
11
+ n/a
12
+
13
+ ## License
14
+
15
+ The library is released with MIT license.
16
+
17
+ © 2025-PRESENT Vjacheslav Trushkin
@@ -5,10 +5,13 @@ function createExportsForMainFiles(data, options = {}) {
5
5
  const result = options?.data || Object.create(null);
6
6
  const ext = options.ext || "";
7
7
  const defaultProp = options.defaultProp || "default";
8
- for (const { icon, filename, types } of data) result[`./${icon}${ext}`] = types ? {
9
- types: `./${types}`,
10
- [defaultProp]: `./${filename}`
11
- } : `./${filename}`;
8
+ for (const { icon, filename, css, types } of data) {
9
+ result[`./${icon}${ext}`] = types ? {
10
+ types: `./${types}`,
11
+ [defaultProp]: `./${filename}`
12
+ } : `./${filename}`;
13
+ if (css) result[`./${icon}.css`] = `./${css}`;
14
+ }
12
15
  return result;
13
16
  }
14
17
 
@@ -1,6 +1,13 @@
1
1
  import { FactoryComponent, FactoryGeneratedComponent } from "../types/component.js";
2
+ import { FactoryIconData } from "../types/data.js";
3
+ import { ComponentFactoryFileSystemOptions } from "../types/options.js";
4
+ interface Options extends Pick<ComponentFactoryFileSystemOptions, 'doubleDirsForComponents' | 'prefixDirsForComponents'> {
5
+ includePrefix?: boolean;
6
+ extension: string;
7
+ cssExtension?: string;
8
+ }
2
9
  /**
3
10
  * Add icon and filename to generated component
4
11
  */
5
- declare function convertGeneratedComponentToFile(icon: string, filename: string, item: FactoryGeneratedComponent): FactoryComponent;
12
+ declare function convertGeneratedComponentToFile(icon: Pick<FactoryIconData, 'name' | 'prefix'>, item: FactoryGeneratedComponent, options: Options): FactoryComponent;
6
13
  export { convertGeneratedComponentToFile };
@@ -1,10 +1,15 @@
1
+ import { getGeneratedComponentFilename } from "./filename.js";
2
+
1
3
  /**
2
4
  * Add icon and filename to generated component
3
5
  */
4
- function convertGeneratedComponentToFile(icon, filename, item) {
6
+ function convertGeneratedComponentToFile(icon, item, options) {
7
+ const { prefix, name } = icon;
8
+ const filename = getGeneratedComponentFilename(icon, options.extension, options);
5
9
  return {
6
- icon,
10
+ icon: options.includePrefix ? `${prefix}/${name}` : name,
7
11
  filename,
12
+ css: item.style ? getGeneratedComponentFilename(icon, options.cssExtension ?? ".css", options) : void 0,
8
13
  ...item
9
14
  };
10
15
  }
@@ -16,6 +16,10 @@ function mergeExportedComponentFiles(items, files) {
16
16
  for (const item of items) {
17
17
  for (const asset of item.assets) add(asset);
18
18
  add(item);
19
+ if (item.css && item.style) add({
20
+ filename: item.css,
21
+ content: item.style
22
+ });
19
23
  }
20
24
  return files;
21
25
  }
@@ -3,5 +3,5 @@ import { ComponentFactoryRenderingOptions } from "../../types/options.js";
3
3
  /**
4
4
  * Convert icon content to a string literal
5
5
  */
6
- declare function stringifyFactoryIconContent(icon: ComponentFactorySource, options: Pick<ComponentFactoryRenderingOptions, 'cssMode' | 'mergeCSS'>): string;
6
+ declare function stringifyFactoryIconContent(icon: ComponentFactorySource, options: Pick<ComponentFactoryRenderingOptions, 'cssMode' | 'mergeCSS'>, embedCSS?: string): string;
7
7
  export { stringifyFactoryIconContent };
@@ -3,14 +3,14 @@ import { generateCSSDefaultImportName } from "../css/name.js";
3
3
  /**
4
4
  * Convert icon content to a string literal
5
5
  */
6
- function stringifyFactoryIconContent(icon, options) {
6
+ function stringifyFactoryIconContent(icon, options, embedCSS) {
7
7
  const { cssMode, mergeCSS } = options;
8
- let content = "`" + icon.content.replace(/`/g, "\\`") + "`";
8
+ let content = "`" + (embedCSS ? `<style>${embedCSS}</style>${icon.content}` : icon.content).replace(/`/g, "\\`") + "`";
9
9
  switch (cssMode) {
10
- case "import": return content;
11
10
  case "module":
12
11
  for (const className in icon.classes) content = content.replace(new RegExp("([\" ])(" + className + ")([\" ])", "g"), `$1\${${mergeCSS ? "css" : generateCSSDefaultImportName(className)}['${className}']}$3`);
13
12
  return content;
13
+ default: return content;
14
14
  }
15
15
  }
16
16
 
@@ -3,7 +3,7 @@ import { ComponentFactorySource } from "../../types/source.js";
3
3
  import { ComponentFactoryOptions } from "../../types/options.js";
4
4
  import { FactoryComponentImports } from "../imports/types.js";
5
5
  interface Options extends Pick<ComponentFactoryOptions, 'cssMode' | 'cssPath' | 'doubleDirsForCSS' | 'mergeCSS'> {
6
- styleInComponent?: boolean;
6
+ componentType?: 'svelte';
7
7
  }
8
8
  /**
9
9
  * Generate CSS files for component
@@ -10,18 +10,22 @@ import { getGeneratedCSSFilename } from "../filenames/css.js";
10
10
  function generateCSSFilesForComponent(content, imports, assets, options) {
11
11
  const { classes, keyframes } = content;
12
12
  if (!classes) return;
13
- const isModule = options.cssMode === "module";
14
- const styleInComponent = (!isModule && options.styleInComponent) ?? false;
15
- const mergeCSS = (styleInComponent || options.mergeCSS) ?? false;
13
+ const { cssMode, componentType } = options;
14
+ const isComponent = cssMode === "embed";
15
+ const returnCSS = isComponent || cssMode === "prop";
16
+ const isModule = cssMode === "module";
17
+ const mergeCSS = (returnCSS || options.mergeCSS) ?? false;
16
18
  const embedAnimations = isModule && !mergeCSS;
19
+ const classNamePrefix = isComponent && componentType === "svelte" ? ":global " : "";
20
+ const keyframesPrefix = isComponent && componentType === "svelte" ? "-global-" : "";
17
21
  const mergedContent = [];
18
22
  for (const className in classes) {
19
- const baseContent = stringifyCSSSelector(`.${className}`, classes[className]);
23
+ const baseContent = stringifyCSSSelector(`${classNamePrefix}.${className}`, classes[className]);
20
24
  let content$1 = baseContent;
21
25
  if (embedAnimations && keyframes) {
22
26
  for (const animationName in keyframes) if (baseContent.includes(animationName)) {
23
27
  const value = keyframes[animationName];
24
- content$1 += "\n" + (typeof value === "string" ? value : stringifyCSSKeyframes(animationName, value));
28
+ content$1 += "\n" + (typeof value === "string" ? value : stringifyCSSKeyframes(keyframesPrefix + animationName, value));
25
29
  }
26
30
  }
27
31
  if (mergeCSS) {
@@ -38,7 +42,7 @@ function generateCSSFilesForComponent(content, imports, assets, options) {
38
42
  }
39
43
  if (!embedAnimations && keyframes) for (const animationName in keyframes) {
40
44
  const value = keyframes[animationName];
41
- const content$1 = typeof value === "string" ? value : stringifyCSSKeyframes(animationName, value);
45
+ const content$1 = typeof value === "string" ? value : stringifyCSSKeyframes(keyframesPrefix + animationName, value);
42
46
  if (mergeCSS) {
43
47
  mergedContent.push(content$1);
44
48
  continue;
@@ -59,9 +63,9 @@ function generateCSSFilesForComponent(content, imports, assets, options) {
59
63
  content: content$1
60
64
  });
61
65
  if (isModule) imports.modules[mergeCSS.import] = "css";
62
- else imports.css.add(mergeCSS.import);
66
+ else if (!returnCSS) imports.css.add(mergeCSS.import);
63
67
  }
64
- return styleInComponent ? content$1 : void 0;
68
+ return returnCSS ? content$1 : void 0;
65
69
  }
66
70
  }
67
71
 
@@ -6,8 +6,7 @@ import { getGeneratedAssetFilename } from "./asset.js";
6
6
  function getGeneratedCSSFilename(name, options) {
7
7
  const { cssPath, doubleDirsForCSS, cssMode } = options;
8
8
  const baseName = doubleDirsForCSS ? `${name.slice(0, 1).toLowerCase()}/${name}` : name;
9
- const filename = cssMode === "module" ? `${baseName}.module.css` : `${baseName}.css`;
10
- return getGeneratedAssetFilename(filename, cssPath);
9
+ return getGeneratedAssetFilename(cssMode === "module" ? `${baseName}.module.css` : `${baseName}.css`, cssPath);
11
10
  }
12
11
 
13
12
  export { getGeneratedCSSFilename };
@@ -6,13 +6,10 @@ import { getGeneratedAssetFilename } from "./asset.js";
6
6
  * Generate component types filename based on options
7
7
  */
8
8
  function getGeneratedComponentTypesFilename(icon, content, options) {
9
- if (options.sharedTypes) {
10
- const hash = getUniqueHash(content, {
11
- css: true,
12
- length: 8
13
- });
14
- return getGeneratedAssetFilename(`types/${hash}.d.ts`, options.rootPath);
15
- }
9
+ if (options.sharedTypes) return getGeneratedAssetFilename(`types/${getUniqueHash(content, {
10
+ css: true,
11
+ length: 8
12
+ })}.d.ts`, options.rootPath);
16
13
  const filename = getGeneratedComponentFilename(icon, ".d.ts", options);
17
14
  return {
18
15
  filename,
@@ -12,13 +12,12 @@ function componentFactoryFileSystemOptions(base) {
12
12
  doubleDirsForComponents,
13
13
  prefixDirsForComponents
14
14
  });
15
- const cssPath = base.cssPath ?? getGeneratedAssetFilename("css", rootPath);
16
15
  return {
17
16
  doubleDirsForCSS,
18
17
  prefixDirsForComponents,
19
18
  doubleDirsForComponents,
20
19
  rootPath,
21
- cssPath,
20
+ cssPath: base.cssPath ?? getGeneratedAssetFilename("css", rootPath),
22
21
  sharedTypes: base.sharedTypes ?? false
23
22
  };
24
23
  }
@@ -14,7 +14,8 @@ function createRawComponent(data, options) {
14
14
  const assets = [];
15
15
  const imports = createFactoryImports();
16
16
  const codeLines = [];
17
- generateCSSFilesForComponent(data.icon, imports, assets, options);
17
+ const style = generateCSSFilesForComponent(data.icon, imports, assets, options);
18
+ const isEmbeddedCSS = options.cssMode === "embed";
18
19
  const props = {
19
20
  xmlns: "http://www.w3.org/2000/svg",
20
21
  ...getComponentSizeValues(options, data.viewBox),
@@ -22,7 +23,7 @@ function createRawComponent(data, options) {
22
23
  };
23
24
  const icon = {
24
25
  ...data.icon,
25
- content: `<svg ${stringifyFactoryProps(props, factoryPropTemplate)}>${data.icon.content}</svg>`
26
+ content: `<svg ${stringifyFactoryProps(props, factoryPropTemplate)}>${isEmbeddedCSS && style ? `<style>${style}</style>` : ""}${data.icon.content}</svg>`
26
27
  };
27
28
  codeLines.push(`const icon = ${stringifyFactoryIconContent(icon, options)};\n`);
28
29
  codeLines.push("export default icon;\n");
@@ -35,7 +36,8 @@ function createRawComponent(data, options) {
35
36
  });
36
37
  return {
37
38
  assets,
38
- content: codeLines.join("\n")
39
+ content: codeLines.join("\n"),
40
+ style: isEmbeddedCSS ? void 0 : style
39
41
  };
40
42
  }
41
43
 
@@ -3,7 +3,6 @@ import { FactoryIconData } from "./types/data.js";
3
3
  import { ComponentFactoryOptions } from "./types/options.js";
4
4
  interface SvelteOptions extends ComponentFactoryOptions {
5
5
  ts?: boolean;
6
- styles?: boolean;
7
6
  }
8
7
  /**
9
8
  * Create Svelte component code
@@ -17,14 +17,13 @@ import { getViewBoxRatio } from "./helpers/content/ratio.js";
17
17
  */
18
18
  function createSvelteComponent(data, options) {
19
19
  const useTS = options.ts ?? false;
20
- const styleInComponent = options.styles ?? false;
21
20
  const assets = [];
22
21
  const imports = createFactoryImports();
23
22
  const hasFallback = !!data.fallback;
24
23
  if (hasFallback) imports.default["@iconify/css-svelte"] = "Icon";
25
24
  const styleContent = generateCSSFilesForComponent(data.icon, imports, assets, {
26
25
  ...options,
27
- styleInComponent
26
+ componentType: "svelte"
28
27
  });
29
28
  let hasFixedSize = !!options.width && !!options.height;
30
29
  const viewBox = data.viewBox;
@@ -93,11 +92,13 @@ ${componentCode.join("\n")}
93
92
  <\/script>
94
93
  ${template}
95
94
  `;
96
- if (styleContent) content += `<style>\n:global {\n${styleContent}\n}\n</style>\n`;
95
+ const style = options.cssMode === "prop" ? styleContent : void 0;
96
+ if (styleContent && !style) content += `<style>\n${styleContent}\n</style>\n`;
97
97
  const types = addSvelteComponentTypes(data, options, assets, props);
98
98
  return {
99
99
  assets,
100
100
  content,
101
+ style,
101
102
  types
102
103
  };
103
104
  }
@@ -17,6 +17,7 @@ interface GeneratedAssetFile extends GeneratedComponentFile {
17
17
  interface FactoryGeneratedComponent {
18
18
  assets: GeneratedAssetFile[];
19
19
  content: string;
20
+ style?: string;
20
21
  types?: string;
21
22
  }
22
23
  /**
@@ -25,5 +26,6 @@ interface FactoryGeneratedComponent {
25
26
  interface FactoryComponent extends Omit<FactoryGeneratedComponent, 'ext' | 'forceExtension'> {
26
27
  icon: string;
27
28
  filename: string;
29
+ css?: string;
28
30
  }
29
31
  export { FactoryComponent, FactoryGeneratedComponent, GeneratedAssetFile, GeneratedComponentFile };
@@ -1,5 +1,10 @@
1
1
  /**
2
2
  * Method of importing CSS in generated components
3
+ *
4
+ * 'import' - Create external CSS file and import it in component
5
+ * 'module' - Create CSS module and import it in component
6
+ * 'embed' - Embed CSS styles in component (if supported by component, throws error otherwise)
7
+ * 'prop' - Export CSS as separate property in generated data, do not import in component, do not create asset
3
8
  */
4
- type CSSExportMode = 'import' | 'module';
9
+ type CSSExportMode = 'import' | 'module' | 'embed' | 'prop';
5
10
  export { CSSExportMode };
@@ -22,7 +22,8 @@ function createVueFunctionalComponent(data, options) {
22
22
  if (hasFallback) imports.named["@iconify/css-vue"] = new Set(["Icon"]);
23
23
  const vueNamedImports = new Set(["defineComponent", "h"]);
24
24
  imports.named["vue"] = vueNamedImports;
25
- generateCSSFilesForComponent(data.icon, imports, assets, options);
25
+ const style = generateCSSFilesForComponent(data.icon, imports, assets, options);
26
+ const isEmbeddedCSS = options.cssMode === "embed";
26
27
  let hasFixedSize = !!options.width && !!options.height;
27
28
  const viewBox = data.viewBox;
28
29
  const hasComputedViewbox = options.square && !hasFixedSize && viewBox.width !== viewBox.height;
@@ -73,7 +74,7 @@ function createVueFunctionalComponent(data, options) {
73
74
  value: "viewBox",
74
75
  template: hasComputedViewbox ? "viewBox: viewBox.value," : "viewBox,"
75
76
  };
76
- props[hasFallback ? "content" : "innerHTML"] = { value: stringifyFactoryIconContent(data.icon, options) };
77
+ props[hasFallback ? "content" : "innerHTML"] = { value: stringifyFactoryIconContent(data.icon, options, isEmbeddedCSS ? style : void 0) };
77
78
  if (data.fallback) props.fallback = data.fallback;
78
79
  const types = addVueComponentTypes(data, options, assets, props);
79
80
  componentCode.push(`return () => h(${hasFallback ? "Icon" : "'svg'"}, {
@@ -89,10 +90,10 @@ function createVueFunctionalComponent(data, options) {
89
90
  }
90
91
  );
91
92
  `;
92
- const content = `${stringifyFactoryImports(imports)}\n${componentFunction}\nexport default Component;\n`;
93
93
  return {
94
94
  assets,
95
- content,
95
+ content: `${stringifyFactoryImports(imports)}\n${componentFunction}\nexport default Component;\n`,
96
+ style: isEmbeddedCSS ? void 0 : style,
96
97
  types
97
98
  };
98
99
  }
@@ -3,7 +3,6 @@ import { FactoryIconData } from "./types/data.js";
3
3
  import { ComponentFactoryOptions } from "./types/options.js";
4
4
  interface VueOptions extends ComponentFactoryOptions {
5
5
  ts?: boolean;
6
- styles?: boolean;
7
6
  }
8
7
  /**
9
8
  * Create Vue component code
@@ -17,17 +17,13 @@ import { addVueComponentTypes } from "./helpers/ts/vue.js";
17
17
  */
18
18
  function createVueComponent(data, options) {
19
19
  const useTS = options.ts ?? false;
20
- const styleInComponent = options.styles ?? false;
21
20
  const assets = [];
22
21
  const imports = createFactoryImports();
23
22
  const hasFallback = !!data.fallback;
24
23
  if (hasFallback) imports.named["@iconify/css-vue"] = new Set(["Icon"]);
25
24
  const vueNamedImports = /* @__PURE__ */ new Set();
26
25
  imports.named["vue"] = vueNamedImports;
27
- const styleContent = generateCSSFilesForComponent(data.icon, imports, assets, {
28
- ...options,
29
- styleInComponent
30
- });
26
+ const styleContent = generateCSSFilesForComponent(data.icon, imports, assets, options);
31
27
  let hasFixedSize = !!options.width && !!options.height;
32
28
  const viewBox = data.viewBox;
33
29
  const hasComputedViewbox = options.square && !hasFixedSize && viewBox.width !== viewBox.height;
@@ -95,11 +91,13 @@ ${componentCode.join("\n")}
95
91
  <\/script>
96
92
  ${template}
97
93
  `;
98
- if (styleContent) content += `<style>\n${styleContent}\n</style>\n`;
94
+ const style = options.cssMode === "prop" ? styleContent : void 0;
95
+ if (styleContent && !style) content += `<style>\n${styleContent}\n</style>\n`;
99
96
  const types = addVueComponentTypes(data, options, assets, props);
100
97
  return {
101
98
  assets,
102
99
  content,
100
+ style,
103
101
  types
104
102
  };
105
103
  }
package/lib/css/hash.js CHANGED
@@ -6,8 +6,7 @@ const length = 6;
6
6
  * Get class name for CSS rules
7
7
  */
8
8
  function createCSSClassName(rules, prefix = "", options) {
9
- const sorted = sortObject(rules);
10
- return getUniqueHash(sorted, {
9
+ return getUniqueHash(sortObject(rules), {
11
10
  css: true,
12
11
  length,
13
12
  prefix,
@@ -24,8 +24,7 @@ function getUniqueHash(data, options) {
24
24
  const str = typeof data === "string" ? data : JSON.stringify(sortObject(data));
25
25
  const hasPrefix = !!prefix;
26
26
  const values = hashString(str);
27
- const defaultLength = typeof length === "function" ? length(str) : length;
28
- let hash = hashToString(values, css, hasPrefix, defaultLength);
27
+ let hash = hashToString(values, css, hasPrefix, typeof length === "function" ? length(str) : length);
29
28
  if (lengths?.[hash]) hash = hashToString(values, css, hasPrefix, lengths[hash]);
30
29
  const cache = hasPrefix ? uniqueWithPrefixHashes : uniqueHashes;
31
30
  const result = `${prefix}${hash}`;
@@ -0,0 +1,6 @@
1
+ type ComparisonKey = string | number | symbol | object;
2
+ /**
3
+ * Make sure multiple instances of Promise or callback are not ran at the same time
4
+ */
5
+ declare function uniquePromise<T>(key: ComparisonKey, callback: () => T | Promise<T>): Promise<T>;
6
+ export { uniquePromise };
@@ -0,0 +1,58 @@
1
+ import { sortObject } from "./sort-object.js";
2
+
3
+ let cache = [];
4
+ /**
5
+ * Compare keys, return true on match
6
+ */
7
+ function compareKeys(key1, key2) {
8
+ if (key1 === key2) return true;
9
+ if (typeof key1 !== "object" || typeof key2 !== "object" || !key1 || !key2) return false;
10
+ return JSON.stringify(sortObject(key1)) === JSON.stringify(sortObject(key2));
11
+ }
12
+ /**
13
+ * Make sure multiple instances of Promise or callback are not ran at the same time
14
+ */
15
+ function uniquePromise(key, callback) {
16
+ return new Promise((resolve, reject) => {
17
+ const cachedItem = cache.find((item) => compareKeys(key, item.key));
18
+ if (cachedItem) {
19
+ cachedItem.callbacks.push({
20
+ resolve,
21
+ reject
22
+ });
23
+ return;
24
+ }
25
+ const newItem = {
26
+ key,
27
+ callbacks: [{
28
+ resolve,
29
+ reject
30
+ }]
31
+ };
32
+ cache.push(newItem);
33
+ function done(data, err) {
34
+ cache = cache.filter((item) => item !== newItem);
35
+ newItem.callbacks.forEach((item) => {
36
+ try {
37
+ if (data === void 0) item.reject(err);
38
+ else item.resolve(data);
39
+ } catch (err2) {}
40
+ });
41
+ }
42
+ let cb;
43
+ try {
44
+ cb = callback();
45
+ } catch (err) {
46
+ done(void 0, err);
47
+ return;
48
+ }
49
+ if (cb instanceof Promise) cb.then((data) => {
50
+ done(data);
51
+ }).catch((err) => {
52
+ done(void 0, err);
53
+ });
54
+ else done(cb);
55
+ });
56
+ }
57
+
58
+ export { uniquePromise };
package/lib/index.d.ts CHANGED
@@ -10,6 +10,7 @@ import { hashToString } from "./helpers/hash/stringify.js";
10
10
  import { getUniqueHash } from "./helpers/hash/unique.js";
11
11
  import { cloneObject } from "./helpers/misc/clone.js";
12
12
  import { compareSets, compareValues } from "./helpers/misc/compare.js";
13
+ import { uniquePromise } from "./helpers/misc/promises.js";
13
14
  import { sortObject } from "./helpers/misc/sort-object.js";
14
15
  import { iterateXMLContent } from "./xml/iterate.js";
15
16
  import { parseXMLContent } from "./xml/parse.js";
@@ -22,4 +23,4 @@ import { changeSVGIDs } from "./svg/ids/change.js";
22
23
  import { createUniqueIDs } from "./svg/ids/unique.js";
23
24
  import { convertSVGRootToCSS } from "./svg-css/root.js";
24
25
  import { convertSVGContentToCSSRules } from "./svg-css/content.js";
25
- export { ChangeIDResult, ClassProp, ConvertSVGContentOptions, ConvertedSVGContent, ParsedXMLNode, ParsedXMLTagElement, ParsedXMLTextElement, StringifyXMLOptions, UniqueHashOptions, changeIDInString, changeSVGIDs, classProps, cloneObject, compareSets, compareValues, convertSVGContentToCSSRules, convertSVGRootToCSS, createCSSClassName, createUniqueIDs, defaultClassProp, getUniqueHash, hashString, hashToString, iterateXMLContent, parseXMLContent, removeDuplicateIDs, removeUnusedIDs, sortObject, splitClassName, stringifyCSSKeyframes, stringifyCSSRules, stringifyCSSSelector, stringifyXMLContent, toggleClassName };
26
+ export { ChangeIDResult, ClassProp, ConvertSVGContentOptions, ConvertedSVGContent, ParsedXMLNode, ParsedXMLTagElement, ParsedXMLTextElement, StringifyXMLOptions, UniqueHashOptions, changeIDInString, changeSVGIDs, classProps, cloneObject, compareSets, compareValues, convertSVGContentToCSSRules, convertSVGRootToCSS, createCSSClassName, createUniqueIDs, defaultClassProp, getUniqueHash, hashString, hashToString, iterateXMLContent, parseXMLContent, removeDuplicateIDs, removeUnusedIDs, sortObject, splitClassName, stringifyCSSKeyframes, stringifyCSSRules, stringifyCSSSelector, stringifyXMLContent, toggleClassName, uniquePromise };
package/lib/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { cloneObject } from "./helpers/misc/clone.js";
2
2
  import { sortObject } from "./helpers/misc/sort-object.js";
3
3
  import { compareSets, compareValues } from "./helpers/misc/compare.js";
4
+ import { uniquePromise } from "./helpers/misc/promises.js";
4
5
  import { hashToString } from "./helpers/hash/stringify.js";
5
6
  import { hashString } from "./helpers/hash/hash.js";
6
7
  import { getUniqueHash } from "./helpers/hash/unique.js";
@@ -19,4 +20,4 @@ import { createUniqueIDs } from "./svg/ids/unique.js";
19
20
  import { convertSVGRootToCSS } from "./svg-css/root.js";
20
21
  import { convertSVGContentToCSSRules } from "./svg-css/content.js";
21
22
 
22
- export { changeIDInString, changeSVGIDs, classProps, cloneObject, compareSets, compareValues, convertSVGContentToCSSRules, convertSVGRootToCSS, createCSSClassName, createUniqueIDs, defaultClassProp, getUniqueHash, hashString, hashToString, iterateXMLContent, parseXMLContent, removeDuplicateIDs, removeUnusedIDs, sortObject, splitClassName, stringifyCSSKeyframes, stringifyCSSRules, stringifyCSSSelector, stringifyXMLContent, toggleClassName };
23
+ export { changeIDInString, changeSVGIDs, classProps, cloneObject, compareSets, compareValues, convertSVGContentToCSSRules, convertSVGRootToCSS, createCSSClassName, createUniqueIDs, defaultClassProp, getUniqueHash, hashString, hashToString, iterateXMLContent, parseXMLContent, removeDuplicateIDs, removeUnusedIDs, sortObject, splitClassName, stringifyCSSKeyframes, stringifyCSSRules, stringifyCSSSelector, stringifyXMLContent, toggleClassName, uniquePromise };
@@ -97,8 +97,7 @@ function changeSVGIDs(root, callback) {
97
97
  const node = idNodes.get(id);
98
98
  const content = stringifyXMLContent([node]);
99
99
  if (!content) throw new Error(`Failed to stringify node with ID: ${id}`);
100
- const cleanedContent = changeIDInString(content, id, "{id}");
101
- const newID = callback(id, cleanedContent, node.tag);
100
+ const newID = callback(id, changeIDInString(content, id, "{id}"), node.tag);
102
101
  if (newID !== id) parse([id, newID]);
103
102
  allIDs.delete(id);
104
103
  const idUsage = [];
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.0",
6
+ "version": "1.0.2",
7
7
  "license": "MIT",
8
8
  "bugs": "https://github.com/cyberalien/svg-utils/issues",
9
9
  "homepage": "https://cyberalien.dev/",
@@ -24,20 +24,20 @@
24
24
  },
25
25
  "devDependencies": {
26
26
  "@eslint/eslintrc": "^3.3.1",
27
- "@eslint/js": "^9.37.0",
28
- "@iconify-json/ri": "^1.2.5",
27
+ "@eslint/js": "^9.39.1",
28
+ "@iconify-json/ri": "^1.2.6",
29
29
  "@types/jest": "^30.0.0",
30
- "@types/node": "^24.6.2",
31
- "@typescript-eslint/eslint-plugin": "^8.45.0",
32
- "@typescript-eslint/parser": "^8.45.0",
33
- "eslint": "^9.37.0",
34
- "globals": "^16.4.0",
35
- "tsdown": "^0.15.6",
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",
36
36
  "typescript": "^5.9.3",
37
- "vitest": "^3.2.4"
37
+ "vitest": "^4.0.8"
38
38
  },
39
39
  "scripts": {
40
- "lint": "eslint --fix src/**/*.ts",
40
+ "lint": "eslint --fix src/**/*.ts && tsc --noemit",
41
41
  "prebuild": "pnpm run lint",
42
42
  "build": "tsdown",
43
43
  "test": "vitest"