vite-awesome-svg-loader 1.3.5 → 1.4.0
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/index.d.ts +77 -3
- package/index.js +141 -35
- package/index.mjs +138 -32
- package/integration-utils/index.js +1 -1
- package/integration-utils/index.js.map +1 -1
- package/integration-utils/index.mjs +2 -4
- package/integration-utils/index.mjs.map +1 -1
- package/package.json +7 -7
- package/react-integration/index.cjs +17 -0
- package/react-integration/index.cjs.map +1 -0
- package/react-integration/index.d.ts +4 -3
- package/react-integration/index.js +182 -2
- package/react-integration/index.js.map +1 -1
- package/vanilla-integration/index.cjs +17 -0
- package/vanilla-integration/index.cjs.map +1 -0
- package/vanilla-integration/index.js +379 -2
- package/vanilla-integration/index.js.map +1 -1
- package/vue-integration/index.cjs +17 -0
- package/vue-integration/index.cjs.map +1 -0
- package/vue-integration/index.d.ts +4 -29
- package/vue-integration/index.js +194 -2
- package/vue-integration/index.js.map +1 -1
- package/react-integration/index.mjs +0 -179
- package/react-integration/index.mjs.map +0 -1
- package/vanilla-integration/index.mjs +0 -375
- package/vanilla-integration/index.mjs.map +0 -1
- package/vue-integration/index.mjs +0 -190
- package/vue-integration/index.mjs.map +0 -1
package/index.d.ts
CHANGED
|
@@ -48,6 +48,19 @@ export interface SvgLoaderOptions {
|
|
|
48
48
|
* This also can be done in an import: `import imageSrc from "./path/to/image.svg?preserve-line-width"`.
|
|
49
49
|
*/
|
|
50
50
|
preserveLineWidthList: (string | RegExp)[];
|
|
51
|
+
/**
|
|
52
|
+
* A list of files or directories to disable preserving line width of. Overrides {@link preserveLineWidthList}.
|
|
53
|
+
*/
|
|
54
|
+
skipPreserveLineWidthList: (string | RegExp)[];
|
|
55
|
+
/**
|
|
56
|
+
* A list of CSS selectors to disable {@link preserveLineWidthList} for. Use it to leave specific elements stroke
|
|
57
|
+
* width as-is.
|
|
58
|
+
*
|
|
59
|
+
* Can be a list of selectors or selectors-per-files specifiers.
|
|
60
|
+
*
|
|
61
|
+
* Unlike {@link skipSetCurrentColorSelectors} and {@link skipTransformsSelectors}, doesn't impact build performance.
|
|
62
|
+
*/
|
|
63
|
+
skipPreserveLineWidthSelectors: (string | SelectorsPerFiles)[];
|
|
51
64
|
/**
|
|
52
65
|
* A list of files or directories to replace fill, stroke and `<stop>` colors to `currentColor` of, i.e.:
|
|
53
66
|
*
|
|
@@ -65,6 +78,39 @@ export interface SvgLoaderOptions {
|
|
|
65
78
|
* This also can be done in an import: `import imageSrc from "./path/to/image.svg?set-current-color"`.
|
|
66
79
|
*/
|
|
67
80
|
setCurrentColorList: (string | RegExp)[];
|
|
81
|
+
/**
|
|
82
|
+
* A list of files or directories to disable setting current color of. Overrides {@link setCurrentColorList}.
|
|
83
|
+
*/
|
|
84
|
+
skipSetCurrentColorList: (string | RegExp)[];
|
|
85
|
+
/**
|
|
86
|
+
* A list of CSS selectors to disable {@link setCurrentColorList} for. Use it to leave specific elements colors as-is.
|
|
87
|
+
*
|
|
88
|
+
* Can be a list of selectors or selectors-per-files specifiers.
|
|
89
|
+
*
|
|
90
|
+
* **You probably don't need this option.**
|
|
91
|
+
*
|
|
92
|
+
* For example, if you're creating multi-colored icons, consider following:
|
|
93
|
+
*
|
|
94
|
+
* 1. Using SVG-symbols
|
|
95
|
+
* 1. Add data-attributes for different colors: `data-color-primary`, `data-color-secondary` or whatever fits your
|
|
96
|
+
* needs.
|
|
97
|
+
* 1. Colorize icon with CSS:
|
|
98
|
+
*
|
|
99
|
+
* ```css
|
|
100
|
+
* svg *[data-color-primary] {
|
|
101
|
+
* color: var(--icon-color-primary);
|
|
102
|
+
* }
|
|
103
|
+
*
|
|
104
|
+
* svg *[data-color-secondary] {
|
|
105
|
+
* color: var(--icon-color-secondary);
|
|
106
|
+
* }
|
|
107
|
+
* ```
|
|
108
|
+
*
|
|
109
|
+
* This way you'll get full extensibility.
|
|
110
|
+
*
|
|
111
|
+
* **Heavy usage may significantly slow down build time.** Limit selectors to specific files to improve performance.
|
|
112
|
+
*/
|
|
113
|
+
skipSetCurrentColorSelectors: (string | SelectorsPerFiles)[];
|
|
68
114
|
/**
|
|
69
115
|
* A list of files to skip while transforming.
|
|
70
116
|
*
|
|
@@ -74,6 +120,17 @@ export interface SvgLoaderOptions {
|
|
|
74
120
|
* SVGO is still applied to the added files.
|
|
75
121
|
*/
|
|
76
122
|
skipTransformsList: (string | RegExp)[];
|
|
123
|
+
/**
|
|
124
|
+
* A list of CSS selectors to disable all transforms for. Use it to leave specific elements as-is.
|
|
125
|
+
*
|
|
126
|
+
* Can be a list of selectors or selectors-per-files specifiers.
|
|
127
|
+
*
|
|
128
|
+
* You probably don't need this option. Try rethinking how you manage your assets (see example at
|
|
129
|
+
* {@link skipSetCurrentColorSelectors}). This option is for some very obscure edge cases only.
|
|
130
|
+
*
|
|
131
|
+
* **Heavy usage may significantly slow down build time.** Limit selectors to specific files to improve performance.
|
|
132
|
+
*/
|
|
133
|
+
skipTransformsSelectors: (string | SelectorsPerFiles)[];
|
|
77
134
|
/**
|
|
78
135
|
* A list of files to skip loading of. Useful for passing original files to another loader.
|
|
79
136
|
*
|
|
@@ -106,6 +163,19 @@ export interface SvgLoaderOptions {
|
|
|
106
163
|
*/
|
|
107
164
|
defaultImport: ImportType;
|
|
108
165
|
}
|
|
166
|
+
/**
|
|
167
|
+
* CSS selector per file or files
|
|
168
|
+
*/
|
|
169
|
+
export interface SelectorsPerFiles {
|
|
170
|
+
/**
|
|
171
|
+
* List of filenames and/or paths matchers
|
|
172
|
+
*/
|
|
173
|
+
files: (string | RegExp)[];
|
|
174
|
+
/**
|
|
175
|
+
* List of selectors
|
|
176
|
+
*/
|
|
177
|
+
selectors: string[];
|
|
178
|
+
}
|
|
109
179
|
/**
|
|
110
180
|
* A Vite plugin that:
|
|
111
181
|
*
|
|
@@ -115,8 +185,11 @@ export interface SvgLoaderOptions {
|
|
|
115
185
|
* 1. Source code data URI: `import imageSrcDataUri from "./path/to/image.svg?source-data-uri"`.
|
|
116
186
|
* 1. Source code Base64: `import imageBase64 from "./path/to/image.svg?base64"`.
|
|
117
187
|
* 1. Source code Base64 data URI: `import imageBase64DataUri from "./path/to/image.svg?base64-data-uri"`.
|
|
118
|
-
* 1. Can preserve line width (make icons and line art have same line width when scaling):
|
|
119
|
-
*
|
|
188
|
+
* 1. Can preserve line width (make icons and line art have same line width when scaling):
|
|
189
|
+
* `import imageSrc from "./path/to/image.svg?preserve-line-width"`.
|
|
190
|
+
* See also: {@link SvgLoaderOptions.preserveLineWidthList}.
|
|
191
|
+
* 1. Can replace colors with `currentColor`: `import imageSrc from "./path/to/image.svg?set-current-color"`.
|
|
192
|
+
* See also: {@link SvgLoaderOptions.setCurrentColorList}.
|
|
120
193
|
* 1. Will minimize your SVGs using [SVGO](https://github.com/svg/svgo).
|
|
121
194
|
*
|
|
122
195
|
* Parameters can be chained with an `&` symbol like in a normal URL:
|
|
@@ -147,7 +220,8 @@ export interface SvgLoaderOptions {
|
|
|
147
220
|
* import image from "./path/to/image.svg?skip-awesome-svg-loader";
|
|
148
221
|
* ```
|
|
149
222
|
*
|
|
150
|
-
* You can set filenames and regexes in {@link SvgLoaderOptions}, so you don't have to write such long urls for every
|
|
223
|
+
* You can set filenames and regexes in {@link SvgLoaderOptions}, so you don't have to write such long urls for every
|
|
224
|
+
* import.
|
|
151
225
|
*
|
|
152
226
|
* @param options Plugin options
|
|
153
227
|
*/
|
package/index.js
CHANGED
|
@@ -42,22 +42,28 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
42
42
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
43
43
|
|
|
44
44
|
// src/index.ts
|
|
45
|
-
var
|
|
46
|
-
__export(
|
|
45
|
+
var index_exports = {};
|
|
46
|
+
__export(index_exports, {
|
|
47
47
|
viteAwesomeSvgLoader: () => viteAwesomeSvgLoader
|
|
48
48
|
});
|
|
49
|
-
module.exports = __toCommonJS(
|
|
49
|
+
module.exports = __toCommonJS(index_exports);
|
|
50
50
|
var import_fs_extra = __toESM(require("fs-extra"));
|
|
51
51
|
var import_path = __toESM(require("path"));
|
|
52
52
|
var import_svgo = require("svgo");
|
|
53
|
+
var import_xast = require("svgo/lib/xast.js");
|
|
53
54
|
var csstree = __toESM(require("css-tree"));
|
|
54
55
|
var import_imurmurhash = __toESM(require("imurmurhash"));
|
|
55
56
|
var IMPORT_TYPES = ["url", "source", "source-data-uri", "base64", "base64-data-uri"];
|
|
56
57
|
var DEFAULT_OPTIONS = {
|
|
57
58
|
tempDir: ".temp",
|
|
58
59
|
preserveLineWidthList: [],
|
|
60
|
+
skipPreserveLineWidthList: [],
|
|
61
|
+
skipPreserveLineWidthSelectors: [],
|
|
59
62
|
setCurrentColorList: [],
|
|
63
|
+
skipSetCurrentColorList: [],
|
|
64
|
+
skipSetCurrentColorSelectors: [],
|
|
60
65
|
skipTransformsList: [],
|
|
66
|
+
skipTransformsSelectors: [],
|
|
61
67
|
skipFilesList: [],
|
|
62
68
|
defaultImport: "source"
|
|
63
69
|
};
|
|
@@ -136,18 +142,28 @@ function viteAwesomeSvgLoader(options = {}) {
|
|
|
136
142
|
const query = {};
|
|
137
143
|
for (const pair of queryKVPairs) {
|
|
138
144
|
const [key, value] = pair.split("=");
|
|
139
|
-
query[key.
|
|
145
|
+
query[key.toLowerCase()] = value || "1";
|
|
140
146
|
}
|
|
141
|
-
if (
|
|
147
|
+
if (matchesQueryOrList(relPathWithSlash, query["skip-awesome-svg-loader"], mergedOptions.skipFilesList)) {
|
|
142
148
|
return null;
|
|
143
149
|
}
|
|
144
|
-
const shouldSkipTransforms =
|
|
150
|
+
const shouldSkipTransforms = matchesQueryOrList(
|
|
145
151
|
relPathWithSlash,
|
|
146
152
|
query["skip-transforms"],
|
|
147
153
|
mergedOptions.skipTransformsList
|
|
148
154
|
);
|
|
149
|
-
const shouldPreserveLineWidth = !shouldSkipTransforms &&
|
|
150
|
-
const shouldSetCurrentColor = !shouldSkipTransforms &&
|
|
155
|
+
const shouldPreserveLineWidth = !shouldSkipTransforms && matchesQueryOrList(relPathWithSlash, query["preserve-line-width"], mergedOptions.preserveLineWidthList) && !matchesQueryOrList(relPathWithSlash, void 0, mergedOptions.skipPreserveLineWidthList);
|
|
156
|
+
const shouldSetCurrentColor = !shouldSkipTransforms && matchesQueryOrList(relPathWithSlash, query["set-current-color"], mergedOptions.setCurrentColorList) && !matchesQueryOrList(relPathWithSlash, void 0, mergedOptions.skipSetCurrentColorList);
|
|
157
|
+
const skipPreserveLineWidthSelectors = selectorsToList(
|
|
158
|
+
relPathWithSlash,
|
|
159
|
+
mergedOptions.skipPreserveLineWidthSelectors
|
|
160
|
+
);
|
|
161
|
+
const skipSetCurrentColorSelectors = selectorsToList(
|
|
162
|
+
relPathWithSlash,
|
|
163
|
+
mergedOptions.skipSetCurrentColorSelectors
|
|
164
|
+
);
|
|
165
|
+
const skipTransformsSelectors = selectorsToList(relPathWithSlash, mergedOptions.skipTransformsSelectors);
|
|
166
|
+
const nodesWithOrigColors = [];
|
|
151
167
|
let joinedParamsStr = "";
|
|
152
168
|
for (const param of [shouldSkipTransforms, shouldPreserveLineWidth, shouldSetCurrentColor]) {
|
|
153
169
|
joinedParamsStr += param ? "1" : "0";
|
|
@@ -174,13 +190,25 @@ function viteAwesomeSvgLoader(options = {}) {
|
|
|
174
190
|
name: "awesome-svg-loader",
|
|
175
191
|
fn: () => {
|
|
176
192
|
return {
|
|
193
|
+
root: {
|
|
194
|
+
enter: (root2) => {
|
|
195
|
+
for (const selectors of [skipSetCurrentColorSelectors, skipTransformsSelectors]) {
|
|
196
|
+
for (const selector of selectors) {
|
|
197
|
+
nodesWithOrigColors.push(...(0, import_xast.querySelectorAll)(root2, selector));
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
},
|
|
177
202
|
element: {
|
|
178
203
|
enter: (node) => {
|
|
179
|
-
if (
|
|
204
|
+
if (matchesSelectors(node, skipTransformsSelectors)) {
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
if (shouldPreserveLineWidth && !matchesSelectors(node, skipPreserveLineWidthSelectors)) {
|
|
180
208
|
preserveLineWidth(node, fullPath);
|
|
181
209
|
}
|
|
182
|
-
if (shouldSetCurrentColor) {
|
|
183
|
-
isFillSetOnRoot = setCurrentColor(node, isFillSetOnRoot);
|
|
210
|
+
if (shouldSetCurrentColor && !matchesSelectors(node, skipSetCurrentColorSelectors)) {
|
|
211
|
+
isFillSetOnRoot = setCurrentColor(node, isFillSetOnRoot, nodesWithOrigColors);
|
|
184
212
|
}
|
|
185
213
|
}
|
|
186
214
|
}
|
|
@@ -197,13 +225,13 @@ function viteAwesomeSvgLoader(options = {}) {
|
|
|
197
225
|
}
|
|
198
226
|
switch (importType) {
|
|
199
227
|
case "source":
|
|
200
|
-
return "export default `" + code
|
|
228
|
+
return "export default `" + escapeBackticks(code) + "`;";
|
|
201
229
|
case "source-data-uri":
|
|
202
|
-
return "export default `data:image/svg+xml," + encodeURIComponent(code
|
|
230
|
+
return "export default `data:image/svg+xml," + encodeURIComponent(code) + "`;";
|
|
203
231
|
case "base64":
|
|
204
|
-
return "export default `" + toBase64(code)
|
|
232
|
+
return "export default `" + escapeBackticks(toBase64(code)) + "`;";
|
|
205
233
|
case "base64-data-uri":
|
|
206
|
-
return "export default `data:image/svg+xml;base64," + encodeURIComponent(toBase64(code))
|
|
234
|
+
return "export default `data:image/svg+xml;base64," + encodeURIComponent(toBase64(code)) + "`;";
|
|
207
235
|
}
|
|
208
236
|
if (!isBuildMode) {
|
|
209
237
|
const assetUrl = mergedOptions.tempDir + assetRelPath;
|
|
@@ -223,23 +251,51 @@ function toBase64(str) {
|
|
|
223
251
|
const binString = String.fromCodePoint(...new TextEncoder().encode(str));
|
|
224
252
|
return btoa(binString);
|
|
225
253
|
}
|
|
226
|
-
function
|
|
227
|
-
|
|
254
|
+
function escapeBackticks(str) {
|
|
255
|
+
return str.replaceAll("`", "\\`");
|
|
256
|
+
}
|
|
257
|
+
function matchesQueryOrList(relPathWithSlash, queryValue, matchers) {
|
|
258
|
+
if ((queryValue == null ? void 0 : queryValue.toLowerCase()) === "false") {
|
|
228
259
|
return false;
|
|
229
260
|
}
|
|
230
261
|
if (queryValue) {
|
|
231
262
|
return true;
|
|
232
263
|
}
|
|
264
|
+
return matchesPath(relPathWithSlash, matchers);
|
|
265
|
+
}
|
|
266
|
+
function matchesPath(relPathWithSlash, matchers) {
|
|
233
267
|
const filename = import_path.default.basename(relPathWithSlash);
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
268
|
+
const toMatch = [filename, relPathWithSlash];
|
|
269
|
+
for (const matcher of matchers) {
|
|
270
|
+
for (const entry of toMatch) {
|
|
271
|
+
if (entry === matcher || matcher instanceof RegExp && matcher.exec(entry)) {
|
|
237
272
|
return true;
|
|
238
273
|
}
|
|
239
274
|
}
|
|
240
275
|
}
|
|
241
276
|
return false;
|
|
242
277
|
}
|
|
278
|
+
function selectorsToList(relPathWithSlash, selectors) {
|
|
279
|
+
const resolvedSelectors = [];
|
|
280
|
+
for (const selector of selectors) {
|
|
281
|
+
if (typeof selector === "string") {
|
|
282
|
+
resolvedSelectors.push(selector);
|
|
283
|
+
continue;
|
|
284
|
+
}
|
|
285
|
+
if (matchesPath(relPathWithSlash, selector.files)) {
|
|
286
|
+
resolvedSelectors.push(...selector.selectors);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
return resolvedSelectors;
|
|
290
|
+
}
|
|
291
|
+
function matchesSelectors(node, selectors) {
|
|
292
|
+
for (const selector of selectors) {
|
|
293
|
+
if ((0, import_xast.matches)(node, selector)) {
|
|
294
|
+
return true;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
return false;
|
|
298
|
+
}
|
|
243
299
|
var TAGS_TO_PRESERVE_LINE_WIDTH_OF = {
|
|
244
300
|
circle: true,
|
|
245
301
|
ellipse: true,
|
|
@@ -290,15 +346,15 @@ var IGNORE_COLORS = {
|
|
|
290
346
|
transparent: true,
|
|
291
347
|
currentColor: true
|
|
292
348
|
};
|
|
293
|
-
function setCurrentColor(node, isFillSetOnRoot) {
|
|
294
|
-
var _a;
|
|
349
|
+
function setCurrentColor(node, isFillSetOnRoot, nodesWithOrigColors) {
|
|
295
350
|
if (node.name === "style") {
|
|
296
|
-
const
|
|
351
|
+
const firstChild = node.children[0];
|
|
352
|
+
const newCss = setCurrentColorCss(firstChild == null ? void 0 : firstChild.value, nodesWithOrigColors, false);
|
|
297
353
|
if (newCss) {
|
|
298
|
-
|
|
354
|
+
firstChild.value = newCss;
|
|
299
355
|
}
|
|
300
356
|
} else {
|
|
301
|
-
const newCss = setCurrentColorCss(node.attributes.style, true);
|
|
357
|
+
const newCss = setCurrentColorCss(node.attributes.style, nodesWithOrigColors, true);
|
|
302
358
|
if (newCss) {
|
|
303
359
|
node.attributes.style = newCss;
|
|
304
360
|
}
|
|
@@ -319,7 +375,7 @@ function setCurrentColor(node, isFillSetOnRoot) {
|
|
|
319
375
|
}
|
|
320
376
|
return isFillSetOnRoot;
|
|
321
377
|
}
|
|
322
|
-
function setCurrentColorCss(css, isInline = false) {
|
|
378
|
+
function setCurrentColorCss(css, nodesWithOrigColors, isInline = false) {
|
|
323
379
|
if (!css || typeof css !== "string") {
|
|
324
380
|
return "";
|
|
325
381
|
}
|
|
@@ -328,20 +384,70 @@ function setCurrentColorCss(css, isInline = false) {
|
|
|
328
384
|
css = `{${css}}`;
|
|
329
385
|
context = "block";
|
|
330
386
|
}
|
|
387
|
+
const shouldPreserveColors = !isInline && nodesWithOrigColors.length;
|
|
388
|
+
let origColorSelectors = [];
|
|
389
|
+
let currentColorSelectors = [];
|
|
390
|
+
let didSplitSelectors = false;
|
|
331
391
|
const ast = csstree.parse(css, { context });
|
|
332
|
-
csstree.walk(ast, {
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
392
|
+
csstree.walk(ast, function(node) {
|
|
393
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
394
|
+
if (node.__SKIP_SVG_LOADER__ || ((_a = this.rule) == null ? void 0 : _a.__SKIP_SVG_LOADER__)) {
|
|
395
|
+
return;
|
|
396
|
+
}
|
|
397
|
+
if (shouldPreserveColors) {
|
|
398
|
+
if (node.type === "SelectorList") {
|
|
399
|
+
origColorSelectors = [];
|
|
400
|
+
currentColorSelectors = [];
|
|
401
|
+
didSplitSelectors = false;
|
|
337
402
|
return;
|
|
338
403
|
}
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
404
|
+
if (node.type === "Selector") {
|
|
405
|
+
const selector = csstree.generate(node);
|
|
406
|
+
let isOrigColor = false;
|
|
407
|
+
for (const svgNode of nodesWithOrigColors) {
|
|
408
|
+
if ((0, import_xast.matches)(svgNode, selector)) {
|
|
409
|
+
isOrigColor = true;
|
|
410
|
+
node.__ORIG_COLOR__ = true;
|
|
411
|
+
break;
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
(isOrigColor ? origColorSelectors : currentColorSelectors).push(selector);
|
|
415
|
+
return;
|
|
343
416
|
}
|
|
344
417
|
}
|
|
418
|
+
if (node.type !== "Declaration" || !COLOR_ATTRS_TO_REPLACE[node.property]) {
|
|
419
|
+
return;
|
|
420
|
+
}
|
|
421
|
+
const identifier = (_c = (_b = node.value) == null ? void 0 : _b.children) == null ? void 0 : _c.first;
|
|
422
|
+
const color = (identifier == null ? void 0 : identifier.value) || (identifier == null ? void 0 : identifier.name);
|
|
423
|
+
if (!color || IGNORE_COLORS[color]) {
|
|
424
|
+
return;
|
|
425
|
+
}
|
|
426
|
+
if (shouldPreserveColors && !didSplitSelectors && ((_d = this.rule) == null ? void 0 : _d.prelude.type) === "SelectorList") {
|
|
427
|
+
const origColorsRule = csstree.clone(this.rule);
|
|
428
|
+
origColorsRule.__SKIP_SVG_LOADER__ = true;
|
|
429
|
+
const origColorsSelectors = new csstree.List();
|
|
430
|
+
const selectors = this.rule.prelude.children;
|
|
431
|
+
selectors.forEach((node2, listItem) => {
|
|
432
|
+
if (node2.__ORIG_COLOR__) {
|
|
433
|
+
selectors.remove(listItem);
|
|
434
|
+
origColorsSelectors.push(node2);
|
|
435
|
+
}
|
|
436
|
+
});
|
|
437
|
+
origColorsRule.prelude.children = origColorsSelectors;
|
|
438
|
+
const parent = ((_f = (_e = this.atrule) == null ? void 0 : _e.block) == null ? void 0 : _f.children) || ((_g = this.stylesheet) == null ? void 0 : _g.children);
|
|
439
|
+
let insertBefore;
|
|
440
|
+
parent == null ? void 0 : parent.some((rule, listItem) => {
|
|
441
|
+
if (rule === this.rule) {
|
|
442
|
+
insertBefore = listItem;
|
|
443
|
+
return true;
|
|
444
|
+
}
|
|
445
|
+
return false;
|
|
446
|
+
});
|
|
447
|
+
insertBefore ? parent == null ? void 0 : parent.insertData(origColorsRule, insertBefore) : parent == null ? void 0 : parent.push(origColorsRule);
|
|
448
|
+
didSplitSelectors = true;
|
|
449
|
+
}
|
|
450
|
+
node.value = csstree.parse("currentColor", { context: "value" });
|
|
345
451
|
});
|
|
346
452
|
return csstree.generate(ast);
|
|
347
453
|
}
|
package/index.mjs
CHANGED
|
@@ -19,14 +19,20 @@ var __spreadValues = (a, b) => {
|
|
|
19
19
|
import fs from "fs-extra";
|
|
20
20
|
import path from "path";
|
|
21
21
|
import { optimize } from "svgo";
|
|
22
|
+
import { matches as matchesSelector, querySelectorAll } from "svgo/lib/xast.js";
|
|
22
23
|
import * as csstree from "css-tree";
|
|
23
24
|
import MurmurHash3 from "imurmurhash";
|
|
24
25
|
var IMPORT_TYPES = ["url", "source", "source-data-uri", "base64", "base64-data-uri"];
|
|
25
26
|
var DEFAULT_OPTIONS = {
|
|
26
27
|
tempDir: ".temp",
|
|
27
28
|
preserveLineWidthList: [],
|
|
29
|
+
skipPreserveLineWidthList: [],
|
|
30
|
+
skipPreserveLineWidthSelectors: [],
|
|
28
31
|
setCurrentColorList: [],
|
|
32
|
+
skipSetCurrentColorList: [],
|
|
33
|
+
skipSetCurrentColorSelectors: [],
|
|
29
34
|
skipTransformsList: [],
|
|
35
|
+
skipTransformsSelectors: [],
|
|
30
36
|
skipFilesList: [],
|
|
31
37
|
defaultImport: "source"
|
|
32
38
|
};
|
|
@@ -105,18 +111,28 @@ function viteAwesomeSvgLoader(options = {}) {
|
|
|
105
111
|
const query = {};
|
|
106
112
|
for (const pair of queryKVPairs) {
|
|
107
113
|
const [key, value] = pair.split("=");
|
|
108
|
-
query[key.
|
|
114
|
+
query[key.toLowerCase()] = value || "1";
|
|
109
115
|
}
|
|
110
|
-
if (
|
|
116
|
+
if (matchesQueryOrList(relPathWithSlash, query["skip-awesome-svg-loader"], mergedOptions.skipFilesList)) {
|
|
111
117
|
return null;
|
|
112
118
|
}
|
|
113
|
-
const shouldSkipTransforms =
|
|
119
|
+
const shouldSkipTransforms = matchesQueryOrList(
|
|
114
120
|
relPathWithSlash,
|
|
115
121
|
query["skip-transforms"],
|
|
116
122
|
mergedOptions.skipTransformsList
|
|
117
123
|
);
|
|
118
|
-
const shouldPreserveLineWidth = !shouldSkipTransforms &&
|
|
119
|
-
const shouldSetCurrentColor = !shouldSkipTransforms &&
|
|
124
|
+
const shouldPreserveLineWidth = !shouldSkipTransforms && matchesQueryOrList(relPathWithSlash, query["preserve-line-width"], mergedOptions.preserveLineWidthList) && !matchesQueryOrList(relPathWithSlash, void 0, mergedOptions.skipPreserveLineWidthList);
|
|
125
|
+
const shouldSetCurrentColor = !shouldSkipTransforms && matchesQueryOrList(relPathWithSlash, query["set-current-color"], mergedOptions.setCurrentColorList) && !matchesQueryOrList(relPathWithSlash, void 0, mergedOptions.skipSetCurrentColorList);
|
|
126
|
+
const skipPreserveLineWidthSelectors = selectorsToList(
|
|
127
|
+
relPathWithSlash,
|
|
128
|
+
mergedOptions.skipPreserveLineWidthSelectors
|
|
129
|
+
);
|
|
130
|
+
const skipSetCurrentColorSelectors = selectorsToList(
|
|
131
|
+
relPathWithSlash,
|
|
132
|
+
mergedOptions.skipSetCurrentColorSelectors
|
|
133
|
+
);
|
|
134
|
+
const skipTransformsSelectors = selectorsToList(relPathWithSlash, mergedOptions.skipTransformsSelectors);
|
|
135
|
+
const nodesWithOrigColors = [];
|
|
120
136
|
let joinedParamsStr = "";
|
|
121
137
|
for (const param of [shouldSkipTransforms, shouldPreserveLineWidth, shouldSetCurrentColor]) {
|
|
122
138
|
joinedParamsStr += param ? "1" : "0";
|
|
@@ -143,13 +159,25 @@ function viteAwesomeSvgLoader(options = {}) {
|
|
|
143
159
|
name: "awesome-svg-loader",
|
|
144
160
|
fn: () => {
|
|
145
161
|
return {
|
|
162
|
+
root: {
|
|
163
|
+
enter: (root2) => {
|
|
164
|
+
for (const selectors of [skipSetCurrentColorSelectors, skipTransformsSelectors]) {
|
|
165
|
+
for (const selector of selectors) {
|
|
166
|
+
nodesWithOrigColors.push(...querySelectorAll(root2, selector));
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
},
|
|
146
171
|
element: {
|
|
147
172
|
enter: (node) => {
|
|
148
|
-
if (
|
|
173
|
+
if (matchesSelectors(node, skipTransformsSelectors)) {
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
if (shouldPreserveLineWidth && !matchesSelectors(node, skipPreserveLineWidthSelectors)) {
|
|
149
177
|
preserveLineWidth(node, fullPath);
|
|
150
178
|
}
|
|
151
|
-
if (shouldSetCurrentColor) {
|
|
152
|
-
isFillSetOnRoot = setCurrentColor(node, isFillSetOnRoot);
|
|
179
|
+
if (shouldSetCurrentColor && !matchesSelectors(node, skipSetCurrentColorSelectors)) {
|
|
180
|
+
isFillSetOnRoot = setCurrentColor(node, isFillSetOnRoot, nodesWithOrigColors);
|
|
153
181
|
}
|
|
154
182
|
}
|
|
155
183
|
}
|
|
@@ -166,13 +194,13 @@ function viteAwesomeSvgLoader(options = {}) {
|
|
|
166
194
|
}
|
|
167
195
|
switch (importType) {
|
|
168
196
|
case "source":
|
|
169
|
-
return "export default `" + code
|
|
197
|
+
return "export default `" + escapeBackticks(code) + "`;";
|
|
170
198
|
case "source-data-uri":
|
|
171
|
-
return "export default `data:image/svg+xml," + encodeURIComponent(code
|
|
199
|
+
return "export default `data:image/svg+xml," + encodeURIComponent(code) + "`;";
|
|
172
200
|
case "base64":
|
|
173
|
-
return "export default `" + toBase64(code)
|
|
201
|
+
return "export default `" + escapeBackticks(toBase64(code)) + "`;";
|
|
174
202
|
case "base64-data-uri":
|
|
175
|
-
return "export default `data:image/svg+xml;base64," + encodeURIComponent(toBase64(code))
|
|
203
|
+
return "export default `data:image/svg+xml;base64," + encodeURIComponent(toBase64(code)) + "`;";
|
|
176
204
|
}
|
|
177
205
|
if (!isBuildMode) {
|
|
178
206
|
const assetUrl = mergedOptions.tempDir + assetRelPath;
|
|
@@ -192,23 +220,51 @@ function toBase64(str) {
|
|
|
192
220
|
const binString = String.fromCodePoint(...new TextEncoder().encode(str));
|
|
193
221
|
return btoa(binString);
|
|
194
222
|
}
|
|
195
|
-
function
|
|
196
|
-
|
|
223
|
+
function escapeBackticks(str) {
|
|
224
|
+
return str.replaceAll("`", "\\`");
|
|
225
|
+
}
|
|
226
|
+
function matchesQueryOrList(relPathWithSlash, queryValue, matchers) {
|
|
227
|
+
if ((queryValue == null ? void 0 : queryValue.toLowerCase()) === "false") {
|
|
197
228
|
return false;
|
|
198
229
|
}
|
|
199
230
|
if (queryValue) {
|
|
200
231
|
return true;
|
|
201
232
|
}
|
|
233
|
+
return matchesPath(relPathWithSlash, matchers);
|
|
234
|
+
}
|
|
235
|
+
function matchesPath(relPathWithSlash, matchers) {
|
|
202
236
|
const filename = path.basename(relPathWithSlash);
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
237
|
+
const toMatch = [filename, relPathWithSlash];
|
|
238
|
+
for (const matcher of matchers) {
|
|
239
|
+
for (const entry of toMatch) {
|
|
240
|
+
if (entry === matcher || matcher instanceof RegExp && matcher.exec(entry)) {
|
|
206
241
|
return true;
|
|
207
242
|
}
|
|
208
243
|
}
|
|
209
244
|
}
|
|
210
245
|
return false;
|
|
211
246
|
}
|
|
247
|
+
function selectorsToList(relPathWithSlash, selectors) {
|
|
248
|
+
const resolvedSelectors = [];
|
|
249
|
+
for (const selector of selectors) {
|
|
250
|
+
if (typeof selector === "string") {
|
|
251
|
+
resolvedSelectors.push(selector);
|
|
252
|
+
continue;
|
|
253
|
+
}
|
|
254
|
+
if (matchesPath(relPathWithSlash, selector.files)) {
|
|
255
|
+
resolvedSelectors.push(...selector.selectors);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
return resolvedSelectors;
|
|
259
|
+
}
|
|
260
|
+
function matchesSelectors(node, selectors) {
|
|
261
|
+
for (const selector of selectors) {
|
|
262
|
+
if (matchesSelector(node, selector)) {
|
|
263
|
+
return true;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
return false;
|
|
267
|
+
}
|
|
212
268
|
var TAGS_TO_PRESERVE_LINE_WIDTH_OF = {
|
|
213
269
|
circle: true,
|
|
214
270
|
ellipse: true,
|
|
@@ -259,15 +315,15 @@ var IGNORE_COLORS = {
|
|
|
259
315
|
transparent: true,
|
|
260
316
|
currentColor: true
|
|
261
317
|
};
|
|
262
|
-
function setCurrentColor(node, isFillSetOnRoot) {
|
|
263
|
-
var _a;
|
|
318
|
+
function setCurrentColor(node, isFillSetOnRoot, nodesWithOrigColors) {
|
|
264
319
|
if (node.name === "style") {
|
|
265
|
-
const
|
|
320
|
+
const firstChild = node.children[0];
|
|
321
|
+
const newCss = setCurrentColorCss(firstChild == null ? void 0 : firstChild.value, nodesWithOrigColors, false);
|
|
266
322
|
if (newCss) {
|
|
267
|
-
|
|
323
|
+
firstChild.value = newCss;
|
|
268
324
|
}
|
|
269
325
|
} else {
|
|
270
|
-
const newCss = setCurrentColorCss(node.attributes.style, true);
|
|
326
|
+
const newCss = setCurrentColorCss(node.attributes.style, nodesWithOrigColors, true);
|
|
271
327
|
if (newCss) {
|
|
272
328
|
node.attributes.style = newCss;
|
|
273
329
|
}
|
|
@@ -288,7 +344,7 @@ function setCurrentColor(node, isFillSetOnRoot) {
|
|
|
288
344
|
}
|
|
289
345
|
return isFillSetOnRoot;
|
|
290
346
|
}
|
|
291
|
-
function setCurrentColorCss(css, isInline = false) {
|
|
347
|
+
function setCurrentColorCss(css, nodesWithOrigColors, isInline = false) {
|
|
292
348
|
if (!css || typeof css !== "string") {
|
|
293
349
|
return "";
|
|
294
350
|
}
|
|
@@ -297,20 +353,70 @@ function setCurrentColorCss(css, isInline = false) {
|
|
|
297
353
|
css = `{${css}}`;
|
|
298
354
|
context = "block";
|
|
299
355
|
}
|
|
356
|
+
const shouldPreserveColors = !isInline && nodesWithOrigColors.length;
|
|
357
|
+
let origColorSelectors = [];
|
|
358
|
+
let currentColorSelectors = [];
|
|
359
|
+
let didSplitSelectors = false;
|
|
300
360
|
const ast = csstree.parse(css, { context });
|
|
301
|
-
csstree.walk(ast, {
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
361
|
+
csstree.walk(ast, function(node) {
|
|
362
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
363
|
+
if (node.__SKIP_SVG_LOADER__ || ((_a = this.rule) == null ? void 0 : _a.__SKIP_SVG_LOADER__)) {
|
|
364
|
+
return;
|
|
365
|
+
}
|
|
366
|
+
if (shouldPreserveColors) {
|
|
367
|
+
if (node.type === "SelectorList") {
|
|
368
|
+
origColorSelectors = [];
|
|
369
|
+
currentColorSelectors = [];
|
|
370
|
+
didSplitSelectors = false;
|
|
306
371
|
return;
|
|
307
372
|
}
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
373
|
+
if (node.type === "Selector") {
|
|
374
|
+
const selector = csstree.generate(node);
|
|
375
|
+
let isOrigColor = false;
|
|
376
|
+
for (const svgNode of nodesWithOrigColors) {
|
|
377
|
+
if (matchesSelector(svgNode, selector)) {
|
|
378
|
+
isOrigColor = true;
|
|
379
|
+
node.__ORIG_COLOR__ = true;
|
|
380
|
+
break;
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
(isOrigColor ? origColorSelectors : currentColorSelectors).push(selector);
|
|
384
|
+
return;
|
|
312
385
|
}
|
|
313
386
|
}
|
|
387
|
+
if (node.type !== "Declaration" || !COLOR_ATTRS_TO_REPLACE[node.property]) {
|
|
388
|
+
return;
|
|
389
|
+
}
|
|
390
|
+
const identifier = (_c = (_b = node.value) == null ? void 0 : _b.children) == null ? void 0 : _c.first;
|
|
391
|
+
const color = (identifier == null ? void 0 : identifier.value) || (identifier == null ? void 0 : identifier.name);
|
|
392
|
+
if (!color || IGNORE_COLORS[color]) {
|
|
393
|
+
return;
|
|
394
|
+
}
|
|
395
|
+
if (shouldPreserveColors && !didSplitSelectors && ((_d = this.rule) == null ? void 0 : _d.prelude.type) === "SelectorList") {
|
|
396
|
+
const origColorsRule = csstree.clone(this.rule);
|
|
397
|
+
origColorsRule.__SKIP_SVG_LOADER__ = true;
|
|
398
|
+
const origColorsSelectors = new csstree.List();
|
|
399
|
+
const selectors = this.rule.prelude.children;
|
|
400
|
+
selectors.forEach((node2, listItem) => {
|
|
401
|
+
if (node2.__ORIG_COLOR__) {
|
|
402
|
+
selectors.remove(listItem);
|
|
403
|
+
origColorsSelectors.push(node2);
|
|
404
|
+
}
|
|
405
|
+
});
|
|
406
|
+
origColorsRule.prelude.children = origColorsSelectors;
|
|
407
|
+
const parent = ((_f = (_e = this.atrule) == null ? void 0 : _e.block) == null ? void 0 : _f.children) || ((_g = this.stylesheet) == null ? void 0 : _g.children);
|
|
408
|
+
let insertBefore;
|
|
409
|
+
parent == null ? void 0 : parent.some((rule, listItem) => {
|
|
410
|
+
if (rule === this.rule) {
|
|
411
|
+
insertBefore = listItem;
|
|
412
|
+
return true;
|
|
413
|
+
}
|
|
414
|
+
return false;
|
|
415
|
+
});
|
|
416
|
+
insertBefore ? parent == null ? void 0 : parent.insertData(origColorsRule, insertBefore) : parent == null ? void 0 : parent.push(origColorsRule);
|
|
417
|
+
didSplitSelectors = true;
|
|
418
|
+
}
|
|
419
|
+
node.value = csstree.parse("currentColor", { context: "value" });
|
|
314
420
|
});
|
|
315
421
|
return csstree.generate(ast);
|
|
316
422
|
}
|