@cyberalien/svg-utils 1.0.1 → 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/lib/components/export/exports.js +7 -4
- package/lib/components/export/file.d.ts +8 -1
- package/lib/components/export/file.js +7 -2
- package/lib/components/export/merge.js +4 -0
- package/lib/components/helpers/content/stringify.d.ts +1 -1
- package/lib/components/helpers/content/stringify.js +3 -3
- package/lib/components/helpers/css/generate.d.ts +1 -1
- package/lib/components/helpers/css/generate.js +9 -7
- package/lib/components/helpers/filenames/css.js +1 -2
- package/lib/components/helpers/filenames/types.js +4 -7
- package/lib/components/prepare/options.js +1 -2
- package/lib/components/raw.js +5 -3
- package/lib/components/svelte.d.ts +0 -1
- package/lib/components/svelte.js +4 -3
- package/lib/components/types/component.d.ts +2 -0
- package/lib/components/types/css.d.ts +6 -1
- package/lib/components/vue-func.js +5 -4
- package/lib/components/vue.d.ts +0 -1
- package/lib/components/vue.js +4 -6
- package/lib/css/hash.js +1 -2
- package/lib/helpers/hash/unique.js +1 -2
- package/lib/helpers/misc/promises.d.ts +6 -0
- package/lib/helpers/misc/promises.js +58 -0
- package/lib/index.d.ts +2 -1
- package/lib/index.js +2 -1
- package/lib/svg/ids/change.js +1 -2
- package/package.json +11 -11
|
@@ -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)
|
|
9
|
-
types
|
|
10
|
-
|
|
11
|
-
|
|
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:
|
|
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,
|
|
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'
|
|
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
|
-
|
|
6
|
+
componentType?: 'svelte';
|
|
7
7
|
}
|
|
8
8
|
/**
|
|
9
9
|
* Generate CSS files for component
|
|
@@ -10,12 +10,14 @@ 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
|
|
14
|
-
const
|
|
15
|
-
const
|
|
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;
|
|
17
|
-
const classNamePrefix =
|
|
18
|
-
const keyframesPrefix =
|
|
19
|
+
const classNamePrefix = isComponent && componentType === "svelte" ? ":global " : "";
|
|
20
|
+
const keyframesPrefix = isComponent && componentType === "svelte" ? "-global-" : "";
|
|
19
21
|
const mergedContent = [];
|
|
20
22
|
for (const className in classes) {
|
|
21
23
|
const baseContent = stringifyCSSSelector(`${classNamePrefix}.${className}`, classes[className]);
|
|
@@ -61,9 +63,9 @@ function generateCSSFilesForComponent(content, imports, assets, options) {
|
|
|
61
63
|
content: content$1
|
|
62
64
|
});
|
|
63
65
|
if (isModule) imports.modules[mergeCSS.import] = "css";
|
|
64
|
-
else imports.css.add(mergeCSS.import);
|
|
66
|
+
else if (!returnCSS) imports.css.add(mergeCSS.import);
|
|
65
67
|
}
|
|
66
|
-
return
|
|
68
|
+
return returnCSS ? content$1 : void 0;
|
|
67
69
|
}
|
|
68
70
|
}
|
|
69
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
|
-
|
|
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
|
-
|
|
11
|
-
|
|
12
|
-
|
|
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
|
}
|
package/lib/components/raw.js
CHANGED
|
@@ -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
|
|
package/lib/components/svelte.js
CHANGED
|
@@ -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 === true ? "svelte" : 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
|
-
|
|
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
|
-
|
|
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
|
}
|
package/lib/components/vue.d.ts
CHANGED
package/lib/components/vue.js
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 };
|
package/lib/svg/ids/change.js
CHANGED
|
@@ -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
|
|
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.
|
|
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.
|
|
28
|
-
"@iconify-json/ri": "^1.2.
|
|
27
|
+
"@eslint/js": "^9.39.1",
|
|
28
|
+
"@iconify-json/ri": "^1.2.6",
|
|
29
29
|
"@types/jest": "^30.0.0",
|
|
30
|
-
"@types/node": "^24.
|
|
31
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
|
32
|
-
"@typescript-eslint/parser": "^8.
|
|
33
|
-
"eslint": "^9.
|
|
34
|
-
"globals": "^16.
|
|
35
|
-
"tsdown": "^0.15.
|
|
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": "^
|
|
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"
|