vite-plugin-svg-spritegen 2.0.7 → 2.0.9

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 CHANGED
@@ -36,6 +36,8 @@ export default {
36
36
  };
37
37
  ```
38
38
 
39
+ Relative paths (`baseDir`, `outputDir`) are resolved against Vite's `root`. The output directory is created if it doesn't exist.
40
+
39
41
  ### Generated Files
40
42
 
41
43
  The plugin writes two files to `outputDir`:
@@ -1,2 +1,7 @@
1
1
  import type { InputConfigWithDefaults, SvgMap } from './types';
2
- export declare const buildSvgMap: (inputConfigs: InputConfigWithDefaults[]) => Promise<SvgMap>;
2
+ /**
3
+ * Every input SVG by symbol id. `spritePath` is left out: when an input's `baseDir` is also the output directory, the
4
+ * generated sprite matches the input pattern too, and would otherwise turn up as an icon (in the types as well as the
5
+ * sprite) whenever it already exists from an earlier run.
6
+ */
7
+ export declare const buildSvgMap: (inputConfigs: InputConfigWithDefaults[], spritePath?: string) => Promise<SvgMap>;
package/dist/index.js CHANGED
@@ -24,23 +24,30 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
24
24
  enumerable: true
25
25
  }) : target, mod));
26
26
  //#endregion
27
+ let node_fs = require("node:fs");
27
28
  let node_path = require("node:path");
28
29
  node_path = __toESM(node_path);
29
30
  let chokidar = require("chokidar");
30
31
  let vite = require("vite");
31
- let node_fs = require("node:fs");
32
32
  let fast_glob = require("fast-glob");
33
33
  fast_glob = __toESM(fast_glob);
34
34
  let node_html_parser = require("node-html-parser");
35
35
  let svgo = require("svgo");
36
36
  //#region src/build-svg-map.ts
37
- var buildSvgMap = async (inputConfigs) => {
37
+ /**
38
+ * Every input SVG by symbol id. `spritePath` is left out: when an input's `baseDir` is also the output directory, the
39
+ * generated sprite matches the input pattern too, and would otherwise turn up as an icon (in the types as well as the
40
+ * sprite) whenever it already exists from an earlier run.
41
+ */
42
+ var buildSvgMap = async (inputConfigs, spritePath) => {
38
43
  const svgMap = /* @__PURE__ */ new Map();
44
+ const excluded = spritePath && node_path.default.resolve(spritePath);
39
45
  await Promise.all(inputConfigs.map(async (inputConfig) => {
40
46
  const { pattern, baseDir, getSymbolId } = inputConfig;
41
47
  const matchedPaths = await (0, fast_glob.default)(pattern, { cwd: baseDir });
42
48
  await Promise.all(matchedPaths.map(async (matchPath) => {
43
49
  const filePath = node_path.default.join(baseDir, matchPath);
50
+ if (node_path.default.resolve(filePath) === excluded) return;
44
51
  const content = await node_fs.promises.readFile(filePath, "utf8");
45
52
  const resolvedInputConfig = {
46
53
  ...inputConfig,
@@ -125,12 +132,11 @@ var writeGitignore = async (filePath, spriteName) => {
125
132
  };
126
133
  //#endregion
127
134
  //#region src/write-sprite.ts
128
- var buildSpriteContent = (svgMap, spritePath) => {
135
+ var buildSpriteContent = (svgMap) => {
129
136
  const symbols = [];
130
137
  const definitions = [];
131
138
  const svgSorted = [...svgMap].sort((a, b) => String(a[0]).localeCompare(b[0])).map(([_, svg]) => svg);
132
139
  for (const svg of svgSorted) {
133
- if (spritePath && spritePath === svg.filePath) continue;
134
140
  let content = svg.content;
135
141
  if (svg.svgo !== false) {
136
142
  const svgoDefault = { plugins: [
@@ -181,7 +187,7 @@ var buildSpriteContent = (svgMap, spritePath) => {
181
187
  return lines.join("\n");
182
188
  };
183
189
  var writeSprite = (spritePath, svgMap) => {
184
- const content = buildSpriteContent(svgMap, spritePath);
190
+ const content = buildSpriteContent(svgMap);
185
191
  writeIfChanged(spritePath, content);
186
192
  return content;
187
193
  };
@@ -218,22 +224,27 @@ var SPRITE_VIRTUAL_ID = "\0virtual:svg-spritegen-sprite";
218
224
  var SPRITE_URL_PLACEHOLDER = "__SVG_SPRITEGEN_SPRITE_URL_PLACEHOLDER__";
219
225
  var toFilterArray = (p) => [p].flat().filter((x) => x != null);
220
226
  function svgSpritegen(config) {
221
- const inputConfigsResolved = (Array.isArray(config.input) ? config.input : [config.input ?? inputConfigDefaults]).map((inputConfig) => {
222
- const baseDir = node_path.default.resolve(process.cwd(), inputConfig.baseDir ?? inputConfigDefaults.baseDir);
223
- return {
224
- ...inputConfigDefaults,
225
- ...inputConfig,
226
- baseDir
227
- };
228
- });
227
+ const inputConfigs = Array.isArray(config.input) ? config.input : [config.input ?? inputConfigDefaults];
228
+ const resolveInputs = (root) => inputConfigs.map((inputConfig) => ({
229
+ ...inputConfigDefaults,
230
+ ...inputConfig,
231
+ baseDir: node_path.default.resolve(root, inputConfig.baseDir ?? inputConfigDefaults.baseDir)
232
+ }));
233
+ let inputConfigsResolved = resolveInputs(process.cwd());
229
234
  const stripUnusedResolved = { ...stripUnusedDefaults };
230
235
  if (typeof config.stripUnused === "object") Object.assign(stripUnusedResolved, config.stripUnused);
231
236
  else if (config.stripUnused === false) stripUnusedResolved.enabled = false;
232
- const outputPath = node_path.default.resolve(process.cwd(), config.outputDir);
233
237
  const spriteNameResolved = config.spriteFileName ?? "sprite.svg";
234
- const typesFilePath = (0, vite.normalizePath)(node_path.default.join(outputPath, config.typesFileName ?? "types.ts"));
235
- const spriteFilePath = (0, vite.normalizePath)(node_path.default.join(outputPath, spriteNameResolved));
236
- const gitignoreFilePath = (0, vite.normalizePath)(node_path.default.join(outputPath, ".gitignore"));
238
+ const resolveOutput = (root) => {
239
+ const outputPath = node_path.default.resolve(root, config.outputDir);
240
+ return {
241
+ outputPath,
242
+ typesFilePath: (0, vite.normalizePath)(node_path.default.join(outputPath, config.typesFileName ?? "types.ts")),
243
+ spriteFilePath: (0, vite.normalizePath)(node_path.default.join(outputPath, spriteNameResolved)),
244
+ gitignoreFilePath: (0, vite.normalizePath)(node_path.default.join(outputPath, ".gitignore"))
245
+ };
246
+ };
247
+ let { outputPath, typesFilePath, spriteFilePath, gitignoreFilePath } = resolveOutput(process.cwd());
237
248
  const matchPatternRe = new RegExp(stripUnusedResolved.matchPattern, "g");
238
249
  const idIncludes = toFilterArray(stripUnusedResolved.srcInclude);
239
250
  const idExcludes = ["**/node_modules/**", ...toFilterArray(stripUnusedResolved.srcExclude)];
@@ -246,12 +257,15 @@ function svgSpritegen(config) {
246
257
  return {
247
258
  name: "svg-spritegen",
248
259
  enforce: "pre",
249
- configResolved(config) {
250
- isBuild = config.command === "build";
251
- viteBase = config.base ?? "/";
260
+ configResolved(viteConfig) {
261
+ isBuild = viteConfig.command === "build";
262
+ viteBase = viteConfig.base ?? "/";
263
+ inputConfigsResolved = resolveInputs(viteConfig.root);
264
+ ({outputPath, typesFilePath, spriteFilePath, gitignoreFilePath} = resolveOutput(viteConfig.root));
252
265
  },
253
266
  async buildStart() {
254
- allSvgs = await buildSvgMap(inputConfigsResolved);
267
+ (0, node_fs.mkdirSync)(outputPath, { recursive: true });
268
+ allSvgs = await buildSvgMap(inputConfigsResolved, spriteFilePath);
255
269
  await writeTypes(typesFilePath, allSvgs);
256
270
  if (config.gitignore !== false) await writeGitignore(gitignoreFilePath, spriteNameResolved);
257
271
  if (isBuild) {
@@ -261,7 +275,7 @@ function svgSpritegen(config) {
261
275
  writeSprite(spriteFilePath, allSvgs);
262
276
  const onWatch = (changedPath) => {
263
277
  if (changedPath === spriteFilePath) return;
264
- buildSvgMap(inputConfigsResolved).then((newAllSvgFiles) => {
278
+ buildSvgMap(inputConfigsResolved, spriteFilePath).then((newAllSvgFiles) => {
265
279
  writeSprite(spriteFilePath, newAllSvgFiles);
266
280
  });
267
281
  };
@@ -311,7 +325,7 @@ function svgSpritegen(config) {
311
325
  spriteRefId = this.emitFile({
312
326
  type: "asset",
313
327
  name: spriteNameResolved,
314
- source: buildSpriteContent(sourceMap, spriteFilePath)
328
+ source: buildSpriteContent(sourceMap)
315
329
  });
316
330
  },
317
331
  renderChunk: {
package/dist/index.mjs CHANGED
@@ -1,18 +1,25 @@
1
+ import { mkdirSync, promises, readFileSync, writeFileSync } from "node:fs";
1
2
  import path from "node:path";
2
3
  import { watch } from "chokidar";
3
4
  import { normalizePath } from "vite";
4
- import { promises, readFileSync, writeFileSync } from "node:fs";
5
5
  import fastGlob from "fast-glob";
6
6
  import { parse } from "node-html-parser";
7
7
  import { optimize } from "svgo";
8
8
  //#region src/build-svg-map.ts
9
- var buildSvgMap = async (inputConfigs) => {
9
+ /**
10
+ * Every input SVG by symbol id. `spritePath` is left out: when an input's `baseDir` is also the output directory, the
11
+ * generated sprite matches the input pattern too, and would otherwise turn up as an icon (in the types as well as the
12
+ * sprite) whenever it already exists from an earlier run.
13
+ */
14
+ var buildSvgMap = async (inputConfigs, spritePath) => {
10
15
  const svgMap = /* @__PURE__ */ new Map();
16
+ const excluded = spritePath && path.resolve(spritePath);
11
17
  await Promise.all(inputConfigs.map(async (inputConfig) => {
12
18
  const { pattern, baseDir, getSymbolId } = inputConfig;
13
19
  const matchedPaths = await fastGlob(pattern, { cwd: baseDir });
14
20
  await Promise.all(matchedPaths.map(async (matchPath) => {
15
21
  const filePath = path.join(baseDir, matchPath);
22
+ if (path.resolve(filePath) === excluded) return;
16
23
  const content = await promises.readFile(filePath, "utf8");
17
24
  const resolvedInputConfig = {
18
25
  ...inputConfig,
@@ -97,12 +104,11 @@ var writeGitignore = async (filePath, spriteName) => {
97
104
  };
98
105
  //#endregion
99
106
  //#region src/write-sprite.ts
100
- var buildSpriteContent = (svgMap, spritePath) => {
107
+ var buildSpriteContent = (svgMap) => {
101
108
  const symbols = [];
102
109
  const definitions = [];
103
110
  const svgSorted = [...svgMap].sort((a, b) => String(a[0]).localeCompare(b[0])).map(([_, svg]) => svg);
104
111
  for (const svg of svgSorted) {
105
- if (spritePath && spritePath === svg.filePath) continue;
106
112
  let content = svg.content;
107
113
  if (svg.svgo !== false) {
108
114
  const svgoDefault = { plugins: [
@@ -153,7 +159,7 @@ var buildSpriteContent = (svgMap, spritePath) => {
153
159
  return lines.join("\n");
154
160
  };
155
161
  var writeSprite = (spritePath, svgMap) => {
156
- const content = buildSpriteContent(svgMap, spritePath);
162
+ const content = buildSpriteContent(svgMap);
157
163
  writeIfChanged(spritePath, content);
158
164
  return content;
159
165
  };
@@ -190,22 +196,27 @@ var SPRITE_VIRTUAL_ID = "\0virtual:svg-spritegen-sprite";
190
196
  var SPRITE_URL_PLACEHOLDER = "__SVG_SPRITEGEN_SPRITE_URL_PLACEHOLDER__";
191
197
  var toFilterArray = (p) => [p].flat().filter((x) => x != null);
192
198
  function svgSpritegen(config) {
193
- const inputConfigsResolved = (Array.isArray(config.input) ? config.input : [config.input ?? inputConfigDefaults]).map((inputConfig) => {
194
- const baseDir = path.resolve(process.cwd(), inputConfig.baseDir ?? inputConfigDefaults.baseDir);
195
- return {
196
- ...inputConfigDefaults,
197
- ...inputConfig,
198
- baseDir
199
- };
200
- });
199
+ const inputConfigs = Array.isArray(config.input) ? config.input : [config.input ?? inputConfigDefaults];
200
+ const resolveInputs = (root) => inputConfigs.map((inputConfig) => ({
201
+ ...inputConfigDefaults,
202
+ ...inputConfig,
203
+ baseDir: path.resolve(root, inputConfig.baseDir ?? inputConfigDefaults.baseDir)
204
+ }));
205
+ let inputConfigsResolved = resolveInputs(process.cwd());
201
206
  const stripUnusedResolved = { ...stripUnusedDefaults };
202
207
  if (typeof config.stripUnused === "object") Object.assign(stripUnusedResolved, config.stripUnused);
203
208
  else if (config.stripUnused === false) stripUnusedResolved.enabled = false;
204
- const outputPath = path.resolve(process.cwd(), config.outputDir);
205
209
  const spriteNameResolved = config.spriteFileName ?? "sprite.svg";
206
- const typesFilePath = normalizePath(path.join(outputPath, config.typesFileName ?? "types.ts"));
207
- const spriteFilePath = normalizePath(path.join(outputPath, spriteNameResolved));
208
- const gitignoreFilePath = normalizePath(path.join(outputPath, ".gitignore"));
210
+ const resolveOutput = (root) => {
211
+ const outputPath = path.resolve(root, config.outputDir);
212
+ return {
213
+ outputPath,
214
+ typesFilePath: normalizePath(path.join(outputPath, config.typesFileName ?? "types.ts")),
215
+ spriteFilePath: normalizePath(path.join(outputPath, spriteNameResolved)),
216
+ gitignoreFilePath: normalizePath(path.join(outputPath, ".gitignore"))
217
+ };
218
+ };
219
+ let { outputPath, typesFilePath, spriteFilePath, gitignoreFilePath } = resolveOutput(process.cwd());
209
220
  const matchPatternRe = new RegExp(stripUnusedResolved.matchPattern, "g");
210
221
  const idIncludes = toFilterArray(stripUnusedResolved.srcInclude);
211
222
  const idExcludes = ["**/node_modules/**", ...toFilterArray(stripUnusedResolved.srcExclude)];
@@ -218,12 +229,15 @@ function svgSpritegen(config) {
218
229
  return {
219
230
  name: "svg-spritegen",
220
231
  enforce: "pre",
221
- configResolved(config) {
222
- isBuild = config.command === "build";
223
- viteBase = config.base ?? "/";
232
+ configResolved(viteConfig) {
233
+ isBuild = viteConfig.command === "build";
234
+ viteBase = viteConfig.base ?? "/";
235
+ inputConfigsResolved = resolveInputs(viteConfig.root);
236
+ ({outputPath, typesFilePath, spriteFilePath, gitignoreFilePath} = resolveOutput(viteConfig.root));
224
237
  },
225
238
  async buildStart() {
226
- allSvgs = await buildSvgMap(inputConfigsResolved);
239
+ mkdirSync(outputPath, { recursive: true });
240
+ allSvgs = await buildSvgMap(inputConfigsResolved, spriteFilePath);
227
241
  await writeTypes(typesFilePath, allSvgs);
228
242
  if (config.gitignore !== false) await writeGitignore(gitignoreFilePath, spriteNameResolved);
229
243
  if (isBuild) {
@@ -233,7 +247,7 @@ function svgSpritegen(config) {
233
247
  writeSprite(spriteFilePath, allSvgs);
234
248
  const onWatch = (changedPath) => {
235
249
  if (changedPath === spriteFilePath) return;
236
- buildSvgMap(inputConfigsResolved).then((newAllSvgFiles) => {
250
+ buildSvgMap(inputConfigsResolved, spriteFilePath).then((newAllSvgFiles) => {
237
251
  writeSprite(spriteFilePath, newAllSvgFiles);
238
252
  });
239
253
  };
@@ -283,7 +297,7 @@ function svgSpritegen(config) {
283
297
  spriteRefId = this.emitFile({
284
298
  type: "asset",
285
299
  name: spriteNameResolved,
286
- source: buildSpriteContent(sourceMap, spriteFilePath)
300
+ source: buildSpriteContent(sourceMap)
287
301
  });
288
302
  },
289
303
  renderChunk: {
@@ -1,3 +1,3 @@
1
1
  import type { SvgMap } from './types';
2
- export declare const buildSpriteContent: (svgMap: SvgMap, spritePath?: string) => string;
2
+ export declare const buildSpriteContent: (svgMap: SvgMap) => string;
3
3
  export declare const writeSprite: (spritePath: string, svgMap: SvgMap) => string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vite-plugin-svg-spritegen",
3
- "version": "2.0.7",
3
+ "version": "2.0.9",
4
4
  "description": "Vite plugin that generates an svg spritesheet, optionally removing unused svg files.",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",