svg-icon-baker 1.2.0 → 1.2.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.
- package/LICENSE +0 -39
- package/README.md +3 -3
- package/dist/index.mjs +113 -1
- package/package.json +10 -7
package/LICENSE
CHANGED
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
# svg-icon-baker license
|
|
2
|
-
|
|
3
|
-
svg-icon-baker is released under the MIT license:
|
|
4
|
-
|
|
5
1
|
MIT License
|
|
6
2
|
|
|
7
3
|
Copyright (c) 2025-present, yangxu52
|
|
@@ -23,38 +19,3 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
23
19
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
24
20
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
25
21
|
SOFTWARE.
|
|
26
|
-
|
|
27
|
-
# Licenses of bundled dependencies
|
|
28
|
-
|
|
29
|
-
The published svg-icon-baker artifact additionally contains code with the following licenses:
|
|
30
|
-
MIT
|
|
31
|
-
|
|
32
|
-
# Bundled dependencies:
|
|
33
|
-
|
|
34
|
-
## fast-glob
|
|
35
|
-
|
|
36
|
-
License: MIT
|
|
37
|
-
by: Kir Belevich
|
|
38
|
-
Repository: https://github.com/svg/svgo
|
|
39
|
-
|
|
40
|
-
> MIT License
|
|
41
|
-
>
|
|
42
|
-
> Copyright (c) Kir Belevich
|
|
43
|
-
>
|
|
44
|
-
> Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
45
|
-
> of this software and associated documentation files (the "Software"), to deal
|
|
46
|
-
> in the Software without restriction, including without limitation the rights
|
|
47
|
-
> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
48
|
-
> copies of the Software, and to permit persons to whom the Software is
|
|
49
|
-
> furnished to do so, subject to the following conditions:
|
|
50
|
-
>
|
|
51
|
-
> The above copyright notice and this permission notice shall be included in all
|
|
52
|
-
> copies or substantial portions of the Software.
|
|
53
|
-
>
|
|
54
|
-
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
55
|
-
> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
56
|
-
> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
57
|
-
> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
58
|
-
> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
59
|
-
> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
60
|
-
> SOFTWARE.
|
package/README.md
CHANGED
|
@@ -71,9 +71,9 @@ type Options = {
|
|
|
71
71
|
|
|
72
72
|
## Features
|
|
73
73
|
|
|
74
|
-
-
|
|
75
|
-
-
|
|
76
|
-
-
|
|
74
|
+
- Optimization: Reduce file size, and improve efficiency through `SVGO`
|
|
75
|
+
- Reference Handling: ID and reference prefixing for sprite safety
|
|
76
|
+
- Size Unify: `viewBox` preservation or inference from root dimensions
|
|
77
77
|
|
|
78
78
|
## License
|
|
79
79
|
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1,113 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { optimize } from 'svgo';
|
|
2
|
+
|
|
3
|
+
const DEFAULT_SAFE_PRESET = {
|
|
4
|
+
name: "preset-default",
|
|
5
|
+
params: {
|
|
6
|
+
overrides: {
|
|
7
|
+
removeUselessDefs: false,
|
|
8
|
+
removeHiddenElems: false,
|
|
9
|
+
removeUnknownsAndDefaults: false,
|
|
10
|
+
collapseGroups: false,
|
|
11
|
+
mergePaths: false,
|
|
12
|
+
convertShapeToPath: false
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
const DEFAULT_SAFE_PLUGINS = [{ name: "removeTitle" }, { name: "removeXMLNS" }, { name: "removeXlink" }];
|
|
17
|
+
const CORE_PLUGIN_BLOCKLIST = /* @__PURE__ */ new Set(["prefixIds"]);
|
|
18
|
+
function resolveOptions(userOption) {
|
|
19
|
+
const userObject = userOption ?? {};
|
|
20
|
+
return {
|
|
21
|
+
optimize: userObject.optimize ?? true,
|
|
22
|
+
svgoOptions: userObject.svgoOptions ?? {}
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
function createSvgoConfig(sourceName, options) {
|
|
26
|
+
const plugins = [];
|
|
27
|
+
if (options.optimize) {
|
|
28
|
+
plugins.push(DEFAULT_SAFE_PRESET);
|
|
29
|
+
plugins.push(...DEFAULT_SAFE_PLUGINS);
|
|
30
|
+
}
|
|
31
|
+
if (options.svgoOptions.plugins != null) {
|
|
32
|
+
plugins.push(...filterPlugins(options.svgoOptions.plugins));
|
|
33
|
+
}
|
|
34
|
+
plugins.push(...createCorePlugins(sourceName));
|
|
35
|
+
return {
|
|
36
|
+
multipass: options.svgoOptions.multipass,
|
|
37
|
+
floatPrecision: options.svgoOptions.floatPrecision,
|
|
38
|
+
js2svg: options.svgoOptions.js2svg,
|
|
39
|
+
plugins
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
function filterPlugins(plugins) {
|
|
43
|
+
return plugins.filter((plugin) => {
|
|
44
|
+
const name = resolvePluginName(plugin);
|
|
45
|
+
if (name == null) {
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
48
|
+
return !CORE_PLUGIN_BLOCKLIST.has(name);
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
function resolvePluginName(plugin) {
|
|
52
|
+
if (typeof plugin === "string") {
|
|
53
|
+
return plugin;
|
|
54
|
+
}
|
|
55
|
+
if (plugin && typeof plugin === "object" && "name" in plugin && typeof plugin.name === "string") {
|
|
56
|
+
return plugin.name;
|
|
57
|
+
}
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
function createCorePlugins(sourceName) {
|
|
61
|
+
return [{ name: "removeDimensions" }, { name: "prefixIds", params: { prefix: `${sourceName}-`, delim: "" } }];
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function bakeIcon(source, options) {
|
|
65
|
+
const resolvedOptions = resolveOptions(options);
|
|
66
|
+
return {
|
|
67
|
+
name: source.name,
|
|
68
|
+
content: convertToSymbol(source, resolvedOptions)
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
function bakeIcons(sources, options) {
|
|
72
|
+
const resolvedOptions = resolveOptions(options);
|
|
73
|
+
return sources.map((source) => ({
|
|
74
|
+
name: source.name,
|
|
75
|
+
content: convertToSymbol(source, resolvedOptions)
|
|
76
|
+
}));
|
|
77
|
+
}
|
|
78
|
+
function convertToSymbol(source, options) {
|
|
79
|
+
if (!source || !source.name || !source.content) {
|
|
80
|
+
throw new TypeError("Property name and content are required.");
|
|
81
|
+
}
|
|
82
|
+
if (!/^[A-Za-z][A-Za-z0-9_-]*$/.test(source.name)) {
|
|
83
|
+
throw new TypeError("Invalid name. Use letters, numbers, dash, or underscore, starting with a letter.");
|
|
84
|
+
}
|
|
85
|
+
const normalizedSource = stripLeadingSvgPreamble(source.content);
|
|
86
|
+
if (!/^\s*<svg\b/i.test(normalizedSource)) {
|
|
87
|
+
throw new Error("Parsing failed. Input must start with an <svg> root element.");
|
|
88
|
+
}
|
|
89
|
+
let result;
|
|
90
|
+
try {
|
|
91
|
+
result = optimize(normalizedSource, createSvgoConfig(source.name, options));
|
|
92
|
+
} catch (err) {
|
|
93
|
+
throw new Error(`Parsing failed. ${String(err)}`);
|
|
94
|
+
}
|
|
95
|
+
const viewBox = result.data.match(/viewBox="([^"]+)"/)?.[1];
|
|
96
|
+
if (!viewBox) {
|
|
97
|
+
throw new Error("Cannot determine viewBox. Provide an SVG with viewBox or width/height attributes.");
|
|
98
|
+
}
|
|
99
|
+
const cleanedSvg = stripLeadingSvgPreamble(result.data);
|
|
100
|
+
return toSymbolRootTag(cleanedSvg, source.name, viewBox);
|
|
101
|
+
}
|
|
102
|
+
function stripLeadingSvgPreamble(content) {
|
|
103
|
+
return content.replace(/^(?:\uFEFF|\s|<\?xml[\s\S]*?\?>|<!--[\s\S]*?-->|<!DOCTYPE[\s\S]*?>)+/i, "");
|
|
104
|
+
}
|
|
105
|
+
function toSymbolRootTag(svg, symbolId, viewBox) {
|
|
106
|
+
const rootOpenTag = svg.match(/^\s*<svg\b[^>]*>/i)[0];
|
|
107
|
+
const preservedAttrs = rootOpenTag.replace(/^\s*<svg\b/i, "").replace(/>\s*$/i, "").replace(/\s+id=(['"])[^'"]*\1/gi, "").replace(/\s+viewBox=(['"])[^'"]*\1/gi, "").replace(/\s+width=(['"])[^'"]*\1/gi, "").replace(/\s+height=(['"])[^'"]*\1/gi, "").trim();
|
|
108
|
+
const attrs = preservedAttrs ? ` ${preservedAttrs}` : "";
|
|
109
|
+
const symbolOpenTag = `<symbol id="${symbolId}" viewBox="${viewBox}"${attrs}>`;
|
|
110
|
+
return svg.replace(/^\s*<svg\b[^>]*>/i, symbolOpenTag).replace(/<\/svg>\s*$/i, "</symbol>").trim();
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export { bakeIcon, bakeIcons };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "svg-icon-baker",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.1",
|
|
4
4
|
"description": "A delightful toolkit for baking raw SVG icons into delicious SVG symbol sprites",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"svg",
|
|
@@ -17,7 +17,8 @@
|
|
|
17
17
|
},
|
|
18
18
|
"repository": {
|
|
19
19
|
"type": "git",
|
|
20
|
-
"url": "git+https://github.com/yangxu52/svg-
|
|
20
|
+
"url": "git+https://github.com/yangxu52/vite-plugin-svg-icons-ng.git",
|
|
21
|
+
"directory": "packages/svg-icon-baker"
|
|
21
22
|
},
|
|
22
23
|
"license": "MIT",
|
|
23
24
|
"author": "yangxu52",
|
|
@@ -40,17 +41,19 @@
|
|
|
40
41
|
},
|
|
41
42
|
"devDependencies": {
|
|
42
43
|
"@vitest/coverage-v8": "^4.1.0",
|
|
44
|
+
"rimraf": "^6.1.3",
|
|
43
45
|
"unbuild": "^3.6.1",
|
|
44
46
|
"vitest": "^4.1.0"
|
|
45
47
|
},
|
|
46
48
|
"engines": {
|
|
47
|
-
"node": "^
|
|
48
|
-
"pnpm": ">=10.0.0"
|
|
49
|
+
"node": "^18.0.0 || ^20.0.0 || >=22.0.0"
|
|
49
50
|
},
|
|
50
51
|
"scripts": {
|
|
51
|
-
"build": "unbuild",
|
|
52
52
|
"dev": "unbuild --stub",
|
|
53
|
-
"
|
|
54
|
-
"test
|
|
53
|
+
"build": "unbuild",
|
|
54
|
+
"test": "vitest run",
|
|
55
|
+
"coverage": "vitest run --coverage",
|
|
56
|
+
"clean": "rimraf dist",
|
|
57
|
+
"log": "conventional-changelog -p angular --commit-path . -t svg-icon-baker@v"
|
|
55
58
|
}
|
|
56
59
|
}
|