@menapo/icons 0.0.0-stage → 0.1.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/dist/vite.js ADDED
@@ -0,0 +1,2624 @@
1
+ import { createRequire } from "node:module";
2
+ import { dirname, join, relative, resolve, sep } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import { parseSync } from "vite";
5
+ import { existsSync, mkdirSync, readFileSync, readdirSync, statSync, writeFileSync } from "node:fs";
6
+ //#region ../glue/src/detect.ts
7
+ /**
8
+ * Which framework a module renders with (machine PLAN §5.5), the way vicss
9
+ * decides it: `.vue` and `.svelte` (with `.svelte.js`/`.svelte.ts` rune
10
+ * modules) by extension; JSX by its `@jsxImportSource` pragma, else the
11
+ * project's JSX framework ({@link jsxFrameworkOf}); plain scripts by the
12
+ * plugin's `framework` option, else the framework the root `package.json`
13
+ * depends on, else none (vanilla). Plain data in and out, so it is
14
+ * unit-tested without Vite.
15
+ *
16
+ * vi18n has a detection of its own (its `vite/glue/detect.ts`, by plugin
17
+ * names); it is published, so moving it onto this module waits for its
18
+ * next minor (machine PLAN §11).
19
+ */
20
+ /** Root dependencies that name a project's framework, the first found winning. */
21
+ const DEPENDENCIES = [
22
+ ["vue", "vue"],
23
+ ["svelte", "svelte"],
24
+ ["solid-js", "solid"],
25
+ ["preact", "preact"],
26
+ ["react", "react"]
27
+ ];
28
+ /** `preact`, `solid-js` and `vue` (and their subpaths) by name; any other JSX source takes React's. */
29
+ function jsxFramework(source) {
30
+ const name = source.split("/")[0];
31
+ if (name === "preact") return "preact";
32
+ if (name === "solid-js") return "solid";
33
+ if (name === "vue") return "vue";
34
+ return "react";
35
+ }
36
+ /** The framework of module `id` with source `code`. */
37
+ function frameworkOf(id, code, settings) {
38
+ const file = id.replace(/[?#].*$/, "").toLowerCase();
39
+ if (file.endsWith(".vue")) return "vue";
40
+ if (file.endsWith(".svelte") || /\.svelte\.[cm]?[jt]s$/.test(file)) return "svelte";
41
+ if (/\.[jt]sx$/.test(file)) {
42
+ const pragma = /@jsxImportSource\s+([^\s*]+)/.exec(code)?.[1];
43
+ return pragma ? jsxFramework(pragma) : settings.jsx;
44
+ }
45
+ return settings.scripts;
46
+ }
47
+ /** The names a `package.json` depends on, if it can be read. */
48
+ function dependencies(root) {
49
+ const file = join(root, "package.json");
50
+ if (!existsSync(file)) return void 0;
51
+ try {
52
+ const pkg = JSON.parse(readFileSync(file, "utf8"));
53
+ return /* @__PURE__ */ new Set([...Object.keys(pkg.dependencies ?? {}), ...Object.keys(pkg.devDependencies ?? {})]);
54
+ } catch {
55
+ return;
56
+ }
57
+ }
58
+ /** The framework the `package.json` in `root` depends on, if a known one. */
59
+ function rootFramework(root) {
60
+ const names = dependencies(root);
61
+ return names && DEPENDENCIES.find(([name]) => names.has(name))?.[1];
62
+ }
63
+ /**
64
+ * JSX frameworks by the names of the Vite plugins that compile them, as
65
+ * vi18n recognises them: a prefix up to a separator, or the exact name.
66
+ */
67
+ const JSX_PLUGINS = [
68
+ ["react", /^(?:vite:react|@vitejs\/plugin-react)(?:[:/-]|$)/],
69
+ ["preact", /^(?:preact:|vite:preact(?:[:/-]|$)|@preact\/|prefresh(?:[:/-]|$)|preact$)/],
70
+ ["solid", /^(?:solid:|vite-plugin-solid(?:[:/-]|$)|solid-start(?:[:/-]|$)|solid$)/],
71
+ ["vue", /^(?:vite:vue-jsx|@vitejs\/plugin-vue-jsx)(?:[:/-]|$)/]
72
+ ];
73
+ /** The one JSX framework whose Vite plugin is in `plugins`; none when there are none or several. */
74
+ function pluginFramework(plugins) {
75
+ const found = /* @__PURE__ */ new Set();
76
+ for (const plugin of plugins) {
77
+ const name = plugin?.name;
78
+ if (typeof name !== "string") continue;
79
+ for (const [framework, pattern] of JSX_PLUGINS) if (pattern.test(name)) found.add(framework);
80
+ }
81
+ return found.size === 1 ? [...found][0] : void 0;
82
+ }
83
+ /** tsconfig's JSON with comments and trailing commas, as TypeScript reads it. */
84
+ function parseJsonc(text) {
85
+ let out = "";
86
+ for (let i = 0; i < text.length; i++) {
87
+ const c = text[i];
88
+ if (c === "\"") {
89
+ const end = /"(?:[^"\\]|\\.)*"/y;
90
+ end.lastIndex = i;
91
+ const string = end.exec(text)?.[0] ?? c;
92
+ out += string;
93
+ i += string.length - 1;
94
+ } else if (c === "/" && text[i + 1] === "/") {
95
+ while (i < text.length && text[i] !== "\n") i++;
96
+ out += "\n";
97
+ } else if (c === "/" && text[i + 1] === "*") {
98
+ const end = text.indexOf("*/", i + 2);
99
+ i = end < 0 ? text.length : end + 1;
100
+ } else out += c;
101
+ }
102
+ return JSON.parse(out.replace(/,(\s*[}\]])/g, "$1"));
103
+ }
104
+ /** A tsconfig named by `extends` or a reference: a file, a directory's `tsconfig.json`, or a package's. */
105
+ function tsconfigPath(from, name) {
106
+ const local = name.startsWith(".") || name.startsWith("/");
107
+ let path;
108
+ try {
109
+ path = local ? resolve(dirname(from), name) : createRequire(from).resolve(name);
110
+ } catch {
111
+ return;
112
+ }
113
+ if (existsSync(path) && statSync(path).isDirectory()) path = join(path, "tsconfig.json");
114
+ else if (!existsSync(path) && existsSync(`${path}.json`)) path = `${path}.json`;
115
+ return existsSync(path) ? path : void 0;
116
+ }
117
+ /**
118
+ * `compilerOptions.jsxImportSource` as TypeScript resolves it for `file`:
119
+ * its own, else its `extends`' (the last one first); then, for a solution
120
+ * file (`references`, as create-vite writes), the first referenced project
121
+ * that sets one.
122
+ */
123
+ function tsconfigJsxSource(file, seen = /* @__PURE__ */ new Set()) {
124
+ if (seen.has(file) || !existsSync(file)) return void 0;
125
+ seen.add(file);
126
+ let config;
127
+ try {
128
+ config = parseJsonc(readFileSync(file, "utf8"));
129
+ } catch {
130
+ return;
131
+ }
132
+ const own = config.compilerOptions?.jsxImportSource;
133
+ if (typeof own === "string") return own;
134
+ const bases = typeof config.extends === "string" ? [config.extends] : config.extends ?? [];
135
+ for (const base of [...bases].reverse()) {
136
+ const path = tsconfigPath(file, base);
137
+ const found = path && tsconfigJsxSource(path, seen);
138
+ if (found) return found;
139
+ }
140
+ for (const reference of config.references ?? []) {
141
+ const path = tsconfigPath(file, reference.path);
142
+ const found = path && tsconfigJsxSource(path, seen);
143
+ if (found) return found;
144
+ }
145
+ }
146
+ /**
147
+ * The framework of JSX without a pragma: the JSX import source the Vite
148
+ * config gives Oxc or esbuild; else the one JSX framework whose Vite plugin
149
+ * is installed (`vite-plugin-solid`, the Preact preset); else the root
150
+ * tsconfig's `jsxImportSource`, through `extends` and `references`; else
151
+ * Preact, Solid or Vue when the root `package.json` depends on it; else React.
152
+ */
153
+ function jsxFrameworkOf(config, root) {
154
+ const oxc = config.oxc;
155
+ const esbuild = config.esbuild;
156
+ const fromVite = (oxc && oxc.jsx?.importSource) ?? (esbuild && esbuild.jsxImportSource);
157
+ if (typeof fromVite === "string") return jsxFramework(fromVite);
158
+ const plugin = pluginFramework(config.plugins ?? []);
159
+ if (plugin) return plugin;
160
+ const fromTsconfig = tsconfigJsxSource(join(root, "tsconfig.json"));
161
+ if (fromTsconfig) return jsxFramework(fromTsconfig);
162
+ const names = dependencies(root);
163
+ if (names?.has("preact")) return "preact";
164
+ if (names?.has("solid-js")) return "solid";
165
+ if (names?.has("vue") && !names.has("react")) return "vue";
166
+ return "react";
167
+ }
168
+ //#endregion
169
+ //#region ../glue/src/vite.ts
170
+ /**
171
+ * The build side of the shared glue (machine PLAN §5.1, §5.5): a Vite
172
+ * plugin that resolves a package's hooks (`useMachine` from
173
+ * `@menapo/machine`) per module to that module's framework, so one import
174
+ * works in React, Preact, Vue, Svelte, Solid and plain scripts, and no
175
+ * package has a `/react` or `/vue` entry (repo rule: entries by role).
176
+ *
177
+ * - **Per module:** each module importing a hook gets the hook from
178
+ * `virtual:<package>/glue/<framework>`, which resolves to the package's
179
+ * glue module for that framework; the rest of the import stays. Every
180
+ * form that reaches a hook is rewritten: named imports (string names
181
+ * too), a namespace import's members, re-exports, `export *` and
182
+ * `import()`.
183
+ * - **The app's framework:** a glue module and the adapters it uses import
184
+ * `react`, `vue`… by name. Those imports resolve from the project root, as
185
+ * the app's own do, so the app's single copy is used wherever the glue
186
+ * module lives (a workspace package, `node_modules`); one that does not
187
+ * resolve there fails the build, naming the fix.
188
+ */
189
+ /**
190
+ * A path as Vite writes ids, with forward slashes on every platform:
191
+ * `fileURLToPath` gives backslashes on Windows, and a prefix test of one
192
+ * against the other never matches.
193
+ */
194
+ const posix = (path) => path.replace(/\\/g, "/");
195
+ /** Whether `id` is inside one of `dirs`, both compared as Vite writes them. */
196
+ const within = (dirs, id) => dirs.some((dir) => posix(id).startsWith(posix(dir)));
197
+ dirname(fileURLToPath(import.meta.url));
198
+ //#endregion
199
+ //#region ../../node_modules/.pnpm/@jridgewell+sourcemap-codec@1.6.0/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.mjs
200
+ var comma = ",".charCodeAt(0);
201
+ var semicolon = ";".charCodeAt(0);
202
+ var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
203
+ var intToChar$1 = /* @__PURE__ */ new Uint8Array(64);
204
+ var charToInt = /* @__PURE__ */ new Uint8Array(128);
205
+ for (let i = 0; i < chars.length; i++) {
206
+ const c = chars.charCodeAt(i);
207
+ intToChar$1[i] = c;
208
+ charToInt[c] = i;
209
+ }
210
+ function encodeInteger(builder, num) {
211
+ do {
212
+ let clamped = num & 31;
213
+ num >>>= 5;
214
+ if (num > 0) clamped |= 32;
215
+ builder.write(intToChar$1[clamped]);
216
+ } while (num > 0);
217
+ }
218
+ function encodeSign(num) {
219
+ return num < 0 ? -num << 1 | 1 : num << 1;
220
+ }
221
+ var bufLength = 16384;
222
+ var td = typeof TextDecoder !== "undefined" ? /* @__PURE__ */ new TextDecoder() : typeof Buffer !== "undefined" ? { decode(buf) {
223
+ return Buffer.from(buf.buffer, buf.byteOffset, buf.byteLength).toString();
224
+ } } : { decode(buf) {
225
+ let out = "";
226
+ for (let i = 0; i < buf.length; i++) out += String.fromCharCode(buf[i]);
227
+ return out;
228
+ } };
229
+ var StringWriter = class {
230
+ constructor() {
231
+ this.pos = 0;
232
+ this.out = "";
233
+ this.buffer = new Uint8Array(bufLength);
234
+ }
235
+ write(v) {
236
+ const { buffer } = this;
237
+ buffer[this.pos++] = v;
238
+ if (this.pos === bufLength) {
239
+ this.out += td.decode(buffer);
240
+ this.pos = 0;
241
+ }
242
+ }
243
+ flush() {
244
+ const { buffer, out, pos } = this;
245
+ return pos > 0 ? out + td.decode(buffer.subarray(0, pos)) : out;
246
+ }
247
+ };
248
+ function encodeRangeMappings(decoded) {
249
+ if (decoded.length === 0) return "";
250
+ const writer = new StringWriter();
251
+ for (let i = 0; i < decoded.length; i++) {
252
+ const indices = decoded[i];
253
+ if (i > 0) writer.write(semicolon);
254
+ let index = 0;
255
+ for (let j = 0; j < indices.length; j++) {
256
+ const offset = indices[j];
257
+ encodeInteger(writer, offset - index);
258
+ index = offset;
259
+ }
260
+ }
261
+ return writer.flush();
262
+ }
263
+ function encode(decoded) {
264
+ const writer = new StringWriter();
265
+ let sourcesIndex = 0;
266
+ let sourceLine = 0;
267
+ let sourceColumn = 0;
268
+ let namesIndex = 0;
269
+ for (let i = 0; i < decoded.length; i++) {
270
+ const line = decoded[i];
271
+ if (i > 0) writer.write(semicolon);
272
+ if (line.length === 0) continue;
273
+ let genColumn = 0;
274
+ for (let j = 0; j < line.length; j++) {
275
+ const segment = line[j];
276
+ if (j > 0) writer.write(comma);
277
+ encodeInteger(writer, encodeSign(segment[0] - genColumn));
278
+ genColumn = segment[0];
279
+ if (segment.length === 1) continue;
280
+ encodeInteger(writer, encodeSign(segment[1] - sourcesIndex));
281
+ encodeInteger(writer, encodeSign(segment[2] - sourceLine));
282
+ encodeInteger(writer, encodeSign(segment[3] - sourceColumn));
283
+ sourcesIndex = segment[1];
284
+ sourceLine = segment[2];
285
+ sourceColumn = segment[3];
286
+ if (segment.length === 4) continue;
287
+ encodeInteger(writer, encodeSign(segment[4] - namesIndex));
288
+ namesIndex = segment[4];
289
+ }
290
+ }
291
+ return writer.flush();
292
+ }
293
+ //#endregion
294
+ //#region ../../node_modules/.pnpm/magic-string@1.4.3/node_modules/magic-string/dist/index.mjs
295
+ var BitSet = class BitSet {
296
+ constructor(arg) {
297
+ this.bits = arg instanceof BitSet ? arg.bits.slice() : [];
298
+ }
299
+ add(n) {
300
+ this.bits[n >> 5] |= 1 << (n & 31);
301
+ }
302
+ has(n) {
303
+ return !!(this.bits[n >> 5] & 1 << (n & 31));
304
+ }
305
+ };
306
+ var Chunk = class Chunk {
307
+ constructor(start, end, content) {
308
+ this.start = start;
309
+ this.end = end;
310
+ this.original = content;
311
+ this.intro = "";
312
+ this.outro = "";
313
+ this.content = content;
314
+ this.storeName = false;
315
+ this.edited = false;
316
+ this.previous = null;
317
+ this.next = null;
318
+ }
319
+ appendLeft(content) {
320
+ this.outro += content;
321
+ }
322
+ appendRight(content) {
323
+ this.intro = this.intro + content;
324
+ }
325
+ clone() {
326
+ const chunk = new Chunk(this.start, this.end, this.original);
327
+ chunk.intro = this.intro;
328
+ chunk.outro = this.outro;
329
+ chunk.content = this.content;
330
+ chunk.storeName = this.storeName;
331
+ chunk.edited = this.edited;
332
+ return chunk;
333
+ }
334
+ contains(index) {
335
+ return this.start < index && index < this.end;
336
+ }
337
+ eachNext(fn) {
338
+ fn(this);
339
+ let chunk = this.next;
340
+ while (chunk) {
341
+ fn(chunk);
342
+ chunk = chunk.next;
343
+ }
344
+ }
345
+ eachPrevious(fn) {
346
+ fn(this);
347
+ let chunk = this.previous;
348
+ while (chunk) {
349
+ fn(chunk);
350
+ chunk = chunk.previous;
351
+ }
352
+ }
353
+ edit(content, storeName, contentOnly) {
354
+ this.content = content;
355
+ if (!contentOnly) {
356
+ this.intro = "";
357
+ this.outro = "";
358
+ }
359
+ this.storeName = storeName;
360
+ this.edited = true;
361
+ return this;
362
+ }
363
+ prependLeft(content) {
364
+ this.outro = content + this.outro;
365
+ }
366
+ prependRight(content) {
367
+ this.intro = content + this.intro;
368
+ }
369
+ reset() {
370
+ this.intro = "";
371
+ this.outro = "";
372
+ if (this.edited) {
373
+ this.content = this.original;
374
+ this.storeName = false;
375
+ this.edited = false;
376
+ }
377
+ }
378
+ split(index) {
379
+ const sliceIndex = index - this.start;
380
+ const originalBefore = this.original.slice(0, sliceIndex);
381
+ const originalAfter = this.original.slice(sliceIndex);
382
+ this.original = originalBefore;
383
+ const newChunk = new Chunk(index, this.end, originalAfter);
384
+ newChunk.outro = this.outro;
385
+ this.outro = "";
386
+ this.end = index;
387
+ if (this.edited) {
388
+ newChunk.edit("", false, true);
389
+ this.content = "";
390
+ } else this.content = originalBefore;
391
+ newChunk.next = this.next;
392
+ if (newChunk.next) newChunk.next.previous = newChunk;
393
+ newChunk.previous = this;
394
+ this.next = newChunk;
395
+ return newChunk;
396
+ }
397
+ toString() {
398
+ return this.intro + this.content + this.outro;
399
+ }
400
+ trimEnd(rx) {
401
+ this.outro = this.outro.replace(rx, "");
402
+ if (this.outro.length) return true;
403
+ const trimmed = this.content.replace(rx, "");
404
+ if (trimmed.length) {
405
+ if (trimmed !== this.content) {
406
+ if (this.edited) this.edit(trimmed, this.storeName, true);
407
+ else this.split(this.start + trimmed.length).edit("", void 0, true);
408
+ }
409
+ return true;
410
+ } else {
411
+ this.edit("", void 0, true);
412
+ this.intro = this.intro.replace(rx, "");
413
+ if (this.intro.length) return true;
414
+ }
415
+ }
416
+ trimStart(rx) {
417
+ this.intro = this.intro.replace(rx, "");
418
+ if (this.intro.length) return true;
419
+ const trimmed = this.content.replace(rx, "");
420
+ if (trimmed.length) {
421
+ if (trimmed !== this.content) {
422
+ if (this.edited) this.edit(trimmed, this.storeName, true);
423
+ else {
424
+ this.split(this.end - trimmed.length);
425
+ this.edit("", void 0, true);
426
+ }
427
+ }
428
+ return true;
429
+ } else {
430
+ this.edit("", void 0, true);
431
+ this.outro = this.outro.replace(rx, "");
432
+ if (this.outro.length) return true;
433
+ }
434
+ }
435
+ };
436
+ /**
437
+ * The single error type thrown by MagicString.
438
+ *
439
+ * Every message is prefixed with `[MagicString]` so its source is obvious at a
440
+ * glance, and is kept short and consistent in tone.
441
+ */
442
+ var MagicStringError = class extends Error {
443
+ name = "MagicStringError";
444
+ constructor(message, options) {
445
+ super(`[MagicString] ${message}`, options);
446
+ }
447
+ };
448
+ function getBtoa() {
449
+ /* v8 ignore next -- environment fallback, unreachable when `btoa` is present */
450
+ if (typeof globalThis !== "undefined" && typeof globalThis.btoa === "function") return (str) => globalThis.btoa(unescape(encodeURIComponent(str)));
451
+ const buffer = globalThis["Buffer"];
452
+ if (buffer) return (str) => buffer.from(str, "utf-8").toString("base64");
453
+ return () => {
454
+ throw new MagicStringError("unsupported environment: `btoa` or `Buffer` is required");
455
+ };
456
+ /* v8 ignore stop */
457
+ }
458
+ const btoa = /* #__PURE__ */ getBtoa();
459
+ var SourceMap = class {
460
+ constructor(properties) {
461
+ this.version = 3;
462
+ this.file = properties.file;
463
+ this.sources = properties.sources;
464
+ this.sourcesContent = properties.sourcesContent;
465
+ this.names = properties.names;
466
+ this.mappings = typeof properties.mappings === "string" ? properties.mappings : encode(properties.mappings);
467
+ if (typeof properties.x_google_ignoreList !== "undefined") this.x_google_ignoreList = properties.x_google_ignoreList;
468
+ if (typeof properties.debugId !== "undefined") this.debugId = properties.debugId;
469
+ if (typeof properties.rangeMappings !== "undefined") {
470
+ let shouldOutputRangeMapping = false;
471
+ for (const line of properties.rangeMappings) if (line.length !== 0) {
472
+ shouldOutputRangeMapping = true;
473
+ break;
474
+ }
475
+ if (shouldOutputRangeMapping) this.rangeMappings = encodeRangeMappings(properties.rangeMappings);
476
+ }
477
+ }
478
+ /**
479
+ * Returns the equivalent of `JSON.stringify(map)`
480
+ */
481
+ toString() {
482
+ return JSON.stringify(this);
483
+ }
484
+ /**
485
+ * Returns a DataURI containing the sourcemap. Useful for doing this sort of thing:
486
+ * `generateMap(options?: SourceMapOptions): SourceMap;`
487
+ */
488
+ toUrl() {
489
+ return `data:application/json;charset=utf-8;base64,${btoa(this.toString())}`;
490
+ }
491
+ };
492
+ function getLocator(source) {
493
+ const lineOffsets = [0];
494
+ for (let i = source.indexOf("\n"); i !== -1; i = source.indexOf("\n", i + 1)) lineOffsets.push(i + 1);
495
+ return function locate(index) {
496
+ let i = 0;
497
+ let j = lineOffsets.length;
498
+ while (i < j) {
499
+ const m = i + j >> 1;
500
+ if (index < lineOffsets[m]) j = m;
501
+ else i = m + 1;
502
+ }
503
+ const line = i - 1;
504
+ return {
505
+ line,
506
+ column: index - lineOffsets[line]
507
+ };
508
+ };
509
+ }
510
+ function getRelativePath(from, to) {
511
+ const fromParts = from.split(/[/\\]/);
512
+ const toParts = to.split(/[/\\]/);
513
+ fromParts.pop();
514
+ while (fromParts[0] === toParts[0]) {
515
+ fromParts.shift();
516
+ toParts.shift();
517
+ }
518
+ if (fromParts.length) {
519
+ let i = fromParts.length;
520
+ while (i--) fromParts[i] = "..";
521
+ }
522
+ return fromParts.concat(toParts).join("/");
523
+ }
524
+ function guessIndent(code) {
525
+ const lines = code.split("\n");
526
+ const tabbed = lines.filter((line) => /^\t+/.test(line));
527
+ const spaced = lines.filter((line) => /^ {2,}/.test(line));
528
+ if (tabbed.length === 0 && spaced.length === 0) return null;
529
+ if (tabbed.length >= spaced.length) return " ";
530
+ const min = spaced.reduce((previous, current) => {
531
+ const numSpaces = /^ +/.exec(current)[0].length;
532
+ return Math.min(numSpaces, previous);
533
+ }, Infinity);
534
+ return " ".repeat(min);
535
+ }
536
+ const toString = Object.prototype.toString;
537
+ function isObject(thing) {
538
+ return toString.call(thing) === "[object Object]";
539
+ }
540
+ const BASE64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
541
+ const intToChar = /* #__PURE__ */ (() => {
542
+ const chars = /* @__PURE__ */ new Uint8Array(64);
543
+ for (let i = 0; i < 64; i++) chars[i] = BASE64_CHARS.charCodeAt(i);
544
+ return chars;
545
+ })();
546
+ const COMMA = 44;
547
+ const SEMICOLON = 59;
548
+ const BUFFER_SIZE = 16384;
549
+ const FLUSH_THRESHOLD = 16348;
550
+ const scratch = /* #__PURE__ */ new Uint8Array(BUFFER_SIZE);
551
+ function writeVlq(pos, num) {
552
+ num = num < 0 ? -num << 1 | 1 : num << 1;
553
+ do {
554
+ let clamped = num & 31;
555
+ num >>>= 5;
556
+ if (num > 0) clamped |= 32;
557
+ scratch[pos++] = intToChar[clamped];
558
+ } while (num > 0);
559
+ return pos;
560
+ }
561
+ const decoder = /* #__PURE__ */ new TextDecoder();
562
+ var MappingsEncoder = class {
563
+ constructor() {
564
+ this.out = "";
565
+ this.pos = 0;
566
+ this.lines = [];
567
+ this.buffered = 0;
568
+ this.needsComma = false;
569
+ this.prevGenColumn = 0;
570
+ this.prevSourceIndex = 0;
571
+ this.prevSourceLine = 0;
572
+ this.prevSourceColumn = 0;
573
+ this.prevNameIndex = 0;
574
+ }
575
+ endLine(segments) {
576
+ this.lines.push(segments);
577
+ this.buffered += segments.length + 1;
578
+ if (this.buffered >= 4096) this.drain(null);
579
+ }
580
+ segments(segments) {
581
+ this.drain(segments);
582
+ }
583
+ finish(segments) {
584
+ this.drain(segments);
585
+ this.flush();
586
+ return this.out;
587
+ }
588
+ drain(trailing) {
589
+ const lines = this.lines;
590
+ const lineCount = lines.length;
591
+ for (let l = 0; l <= lineCount; l++) {
592
+ const line = l < lineCount ? lines[l] : trailing;
593
+ if (line === null) break;
594
+ for (let i = 0; i < line.length; i++) {
595
+ if (this.pos > FLUSH_THRESHOLD) this.flush();
596
+ const segment = line[i];
597
+ if (this.needsComma) scratch[this.pos++] = COMMA;
598
+ this.needsComma = true;
599
+ this.pos = writeVlq(this.pos, segment[0] - this.prevGenColumn);
600
+ this.prevGenColumn = segment[0];
601
+ this.pos = writeVlq(this.pos, segment[1] - this.prevSourceIndex);
602
+ this.prevSourceIndex = segment[1];
603
+ this.pos = writeVlq(this.pos, segment[2] - this.prevSourceLine);
604
+ this.prevSourceLine = segment[2];
605
+ this.pos = writeVlq(this.pos, segment[3] - this.prevSourceColumn);
606
+ this.prevSourceColumn = segment[3];
607
+ if (segment.length === 5) {
608
+ this.pos = writeVlq(this.pos, segment[4] - this.prevNameIndex);
609
+ this.prevNameIndex = segment[4];
610
+ }
611
+ }
612
+ if (l < lineCount) {
613
+ if (this.pos > FLUSH_THRESHOLD) this.flush();
614
+ scratch[this.pos++] = SEMICOLON;
615
+ this.needsComma = false;
616
+ this.prevGenColumn = 0;
617
+ }
618
+ }
619
+ lines.length = 0;
620
+ this.buffered = 0;
621
+ this.flush();
622
+ }
623
+ flush() {
624
+ this.out += decoder.decode(scratch.subarray(0, this.pos));
625
+ this.pos = 0;
626
+ }
627
+ };
628
+ const NEWLINE_CHAR$1 = 10;
629
+ function isWordCode(code) {
630
+ return code >= 97 && code <= 122 || code >= 65 && code <= 90 || code >= 48 && code <= 57 || code === 95;
631
+ }
632
+ var Mappings = class {
633
+ constructor(hires, encoder = null) {
634
+ this.hires = hires;
635
+ this.generatedCodeLine = 0;
636
+ this.generatedCodeColumn = 0;
637
+ this.raw = [];
638
+ this.rawSegments = this.raw[this.generatedCodeLine] = [];
639
+ this.rawRangeMappings = [];
640
+ this.rawRangeMappingsIndices = this.rawRangeMappings[this.generatedCodeLine] = [];
641
+ this.encoder = encoder;
642
+ }
643
+ nextLine() {
644
+ if (this.encoder === null) {
645
+ this.generatedCodeLine += 1;
646
+ this.raw[this.generatedCodeLine] = this.rawSegments = [];
647
+ } else {
648
+ this.encoder.endLine(this.rawSegments);
649
+ this.rawSegments = [];
650
+ this.generatedCodeLine += 1;
651
+ }
652
+ this.generatedCodeColumn = 0;
653
+ this.rawRangeMappings[this.generatedCodeLine] = this.rawRangeMappingsIndices = [];
654
+ }
655
+ addEdit(sourceIndex, content, loc, nameIndex) {
656
+ if (content.length) {
657
+ const contentLengthMinusOne = content.length - 1;
658
+ let contentLineEnd = content.indexOf("\n", 0);
659
+ let previousContentLineEnd = -1;
660
+ while (contentLineEnd >= 0 && contentLengthMinusOne > contentLineEnd) {
661
+ const segment = [
662
+ this.generatedCodeColumn,
663
+ sourceIndex,
664
+ loc.line,
665
+ loc.column
666
+ ];
667
+ if (nameIndex >= 0) segment.push(nameIndex);
668
+ this.rawSegments.push(segment);
669
+ this.nextLine();
670
+ previousContentLineEnd = contentLineEnd;
671
+ contentLineEnd = content.indexOf("\n", contentLineEnd + 1);
672
+ }
673
+ const segment = [
674
+ this.generatedCodeColumn,
675
+ sourceIndex,
676
+ loc.line,
677
+ loc.column
678
+ ];
679
+ if (nameIndex >= 0) segment.push(nameIndex);
680
+ this.rawSegments.push(segment);
681
+ this.advance(content.slice(previousContentLineEnd + 1));
682
+ }
683
+ }
684
+ addUneditedChunk(sourceIndex, chunk, original, loc, sourcemapLocations) {
685
+ const end = chunk.end;
686
+ let i = chunk.start;
687
+ if (this.hires) {
688
+ const boundary = this.hires === "boundary";
689
+ const experimentalRange = this.hires === "experimental-range";
690
+ const encoder = experimentalRange ? null : this.encoder;
691
+ let charInHiresBoundary = false;
692
+ while (i < end) {
693
+ if (encoder !== null && this.rawSegments.length >= 4096) {
694
+ encoder.segments(this.rawSegments);
695
+ this.rawSegments.length = 0;
696
+ }
697
+ if (experimentalRange && i + 1 >= end) this.rawSegments.push([
698
+ this.generatedCodeColumn,
699
+ sourceIndex,
700
+ loc.line,
701
+ loc.column
702
+ ]);
703
+ const code = original.charCodeAt(i);
704
+ if (code === NEWLINE_CHAR$1) {
705
+ loc.line += 1;
706
+ loc.column = 0;
707
+ this.nextLine();
708
+ charInHiresBoundary = false;
709
+ } else {
710
+ if (boundary) {
711
+ if (isWordCode(code)) {
712
+ if (!charInHiresBoundary) {
713
+ this.rawSegments.push([
714
+ this.generatedCodeColumn,
715
+ sourceIndex,
716
+ loc.line,
717
+ loc.column
718
+ ]);
719
+ charInHiresBoundary = true;
720
+ }
721
+ } else {
722
+ this.rawSegments.push([
723
+ this.generatedCodeColumn,
724
+ sourceIndex,
725
+ loc.line,
726
+ loc.column
727
+ ]);
728
+ charInHiresBoundary = false;
729
+ }
730
+ } else if (experimentalRange) {
731
+ if (i === chunk.start) {
732
+ this.rawRangeMappingsIndices.push(this.rawSegments.length);
733
+ this.rawSegments.push([
734
+ this.generatedCodeColumn,
735
+ sourceIndex,
736
+ loc.line,
737
+ loc.column
738
+ ]);
739
+ }
740
+ } else this.rawSegments.push([
741
+ this.generatedCodeColumn,
742
+ sourceIndex,
743
+ loc.line,
744
+ loc.column
745
+ ]);
746
+ loc.column += 1;
747
+ this.generatedCodeColumn += 1;
748
+ }
749
+ i += 1;
750
+ }
751
+ } else {
752
+ const bits = sourcemapLocations.bits;
753
+ while (i < end) {
754
+ let newline = original.indexOf("\n", i);
755
+ if (newline === -1 || newline > end) newline = end;
756
+ if (newline > i) {
757
+ this.rawSegments.push([
758
+ this.generatedCodeColumn,
759
+ sourceIndex,
760
+ loc.line,
761
+ loc.column
762
+ ]);
763
+ for (let w = i + 1 >> 5, last = newline - 1 >> 5; w <= last; w++) {
764
+ let word = bits[w];
765
+ if (!word) continue;
766
+ const base = w << 5;
767
+ while (word) {
768
+ const lowest = word & -word;
769
+ const index = base + 31 - Math.clz32(lowest);
770
+ if (index > i && index < newline) {
771
+ const offset = index - i;
772
+ this.rawSegments.push([
773
+ this.generatedCodeColumn + offset,
774
+ sourceIndex,
775
+ loc.line,
776
+ loc.column + offset
777
+ ]);
778
+ }
779
+ word ^= lowest;
780
+ }
781
+ }
782
+ loc.column += newline - i;
783
+ this.generatedCodeColumn += newline - i;
784
+ }
785
+ if (newline === end) break;
786
+ loc.line += 1;
787
+ loc.column = 0;
788
+ this.nextLine();
789
+ i = newline + 1;
790
+ }
791
+ }
792
+ }
793
+ advance(str) {
794
+ if (!str) return;
795
+ const lastNewline = str.lastIndexOf("\n");
796
+ for (let i = str.indexOf("\n"); i !== -1; i = str.indexOf("\n", i + 1)) this.nextLine();
797
+ this.generatedCodeColumn += str.length - lastNewline - 1;
798
+ }
799
+ };
800
+ const n = "\n";
801
+ const NEWLINE_CHAR = "\n".charCodeAt(0);
802
+ const CR_CHAR = "\r".charCodeAt(0);
803
+ const warned = {
804
+ insertLeft: false,
805
+ insertRight: false,
806
+ storeName: false
807
+ };
808
+ /**
809
+ * Expands the `$` substitution patterns that `String.prototype.replace` accepts
810
+ * in a string replacement.
811
+ * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace#specifying_a_string_as_a_parameter
812
+ *
813
+ * `captures` holds the capture groups in order, so `captures[0]` is `$1`.
814
+ * `namedCaptures` is `undefined` when the pattern has no named groups, and
815
+ * `$<name>` is then literal text - which is also the case for a string search
816
+ * value, where there are no groups of either kind.
817
+ */
818
+ function expandReplacement(replacement, matched, position, str, captures, namedCaptures) {
819
+ if (!replacement.includes("$")) return replacement;
820
+ let result = "";
821
+ let index = 0;
822
+ while (index < replacement.length) {
823
+ const dollar = replacement.indexOf("$", index);
824
+ if (dollar === -1) {
825
+ result += replacement.slice(index);
826
+ break;
827
+ }
828
+ result += replacement.slice(index, dollar);
829
+ const char = replacement[dollar + 1];
830
+ let expansion = "$";
831
+ let consumed = 1;
832
+ if (char === "$") consumed = 2;
833
+ else if (char === "&") {
834
+ expansion = matched;
835
+ consumed = 2;
836
+ } else if (char === "`") {
837
+ expansion = str.slice(0, position);
838
+ consumed = 2;
839
+ } else if (char === "'") {
840
+ expansion = str.slice(position + matched.length);
841
+ consumed = 2;
842
+ } else if (char === "<" && namedCaptures !== void 0) {
843
+ const close = replacement.indexOf(">", dollar + 2);
844
+ if (close !== -1) {
845
+ expansion = namedCaptures[replacement.slice(dollar + 2, close)] ?? "";
846
+ consumed = close + 1 - dollar;
847
+ }
848
+ } else if (char >= "0" && char <= "9") {
849
+ const second = replacement[dollar + 2];
850
+ const double = second >= "0" && second <= "9" ? Number(char + second) : NaN;
851
+ const single = Number(char);
852
+ if (double >= 1 && double <= captures.length) {
853
+ expansion = captures[double - 1] ?? "";
854
+ consumed = 3;
855
+ } else if (single >= 1 && single <= captures.length) {
856
+ expansion = captures[single - 1] ?? "";
857
+ consumed = 2;
858
+ }
859
+ }
860
+ result += expansion;
861
+ index = dollar + consumed;
862
+ }
863
+ return result;
864
+ }
865
+ var MagicString = class MagicString {
866
+ constructor(string, options = {}) {
867
+ const chunk = new Chunk(0, string.length, string);
868
+ Object.defineProperties(this, {
869
+ original: {
870
+ writable: true,
871
+ value: string
872
+ },
873
+ outro: {
874
+ writable: true,
875
+ value: ""
876
+ },
877
+ intro: {
878
+ writable: true,
879
+ value: ""
880
+ },
881
+ firstChunk: {
882
+ writable: true,
883
+ value: chunk
884
+ },
885
+ lastChunk: {
886
+ writable: true,
887
+ value: chunk
888
+ },
889
+ lastSearchedChunk: {
890
+ writable: true,
891
+ value: chunk
892
+ },
893
+ byStart: {
894
+ writable: true,
895
+ value: /* @__PURE__ */ new Map([[0, chunk]])
896
+ },
897
+ byEnd: {
898
+ writable: true,
899
+ value: /* @__PURE__ */ new Map([[string.length, chunk]])
900
+ },
901
+ filename: {
902
+ writable: true,
903
+ value: options.filename
904
+ },
905
+ indentExclusionRanges: {
906
+ writable: true,
907
+ value: options.indentExclusionRanges
908
+ },
909
+ sourcemapLocations: {
910
+ writable: true,
911
+ value: new BitSet()
912
+ },
913
+ storedNames: {
914
+ writable: true,
915
+ value: {}
916
+ },
917
+ indentStr: {
918
+ writable: true,
919
+ value: void 0
920
+ },
921
+ ignoreList: {
922
+ writable: true,
923
+ value: options.ignoreList
924
+ },
925
+ offset: {
926
+ writable: true,
927
+ value: options.offset || 0
928
+ },
929
+ hasMovedChunks: {
930
+ writable: true,
931
+ value: false
932
+ }
933
+ });
934
+ }
935
+ /**
936
+ * Adds the specified character index (with respect to the original string) to sourcemap mappings, if `hires` is false.
937
+ */
938
+ addSourcemapLocation(char) {
939
+ this.sourcemapLocations.add(char);
940
+ }
941
+ /**
942
+ * Appends the specified content to the end of the string.
943
+ */
944
+ append(content) {
945
+ if (typeof content !== "string") throw new MagicStringError(`content must be a string, got ${typeof content}`);
946
+ this.outro += content;
947
+ return this;
948
+ }
949
+ /**
950
+ * Appends the specified content at the index in the original string.
951
+ * If a range *ending* with index is subsequently moved, the insert will be moved with it.
952
+ * See also `s.prependLeft(...)`.
953
+ */
954
+ appendLeft(index, content) {
955
+ index = index + this.offset;
956
+ if (typeof content !== "string") throw new MagicStringError(`content must be a string, got ${typeof content}`);
957
+ this._split(index);
958
+ const chunk = this.byEnd.get(index);
959
+ if (chunk) chunk.appendLeft(content);
960
+ else this.intro += content;
961
+ return this;
962
+ }
963
+ /**
964
+ * Appends the specified content at the index in the original string.
965
+ * If a range *starting* with index is subsequently moved, the insert will be moved with it.
966
+ * See also `s.prependRight(...)`.
967
+ */
968
+ appendRight(index, content) {
969
+ index = index + this.offset;
970
+ if (typeof content !== "string") throw new MagicStringError(`content must be a string, got ${typeof content}`);
971
+ this._split(index);
972
+ const chunk = this.byStart.get(index);
973
+ if (chunk) chunk.appendRight(content);
974
+ else this.outro += content;
975
+ return this;
976
+ }
977
+ /**
978
+ * Does what you'd expect.
979
+ */
980
+ clone() {
981
+ const cloned = new MagicString(this.original, {
982
+ filename: this.filename,
983
+ ignoreList: this.ignoreList,
984
+ offset: this.offset
985
+ });
986
+ let originalChunk = this.firstChunk;
987
+ let clonedChunk = cloned.firstChunk = cloned.lastSearchedChunk = originalChunk.clone();
988
+ while (originalChunk) {
989
+ cloned.byStart.set(clonedChunk.start, clonedChunk);
990
+ cloned.byEnd.set(clonedChunk.end, clonedChunk);
991
+ const nextOriginalChunk = originalChunk.next;
992
+ const nextClonedChunk = nextOriginalChunk && nextOriginalChunk.clone();
993
+ if (nextClonedChunk) {
994
+ clonedChunk.next = nextClonedChunk;
995
+ nextClonedChunk.previous = clonedChunk;
996
+ clonedChunk = nextClonedChunk;
997
+ }
998
+ originalChunk = nextOriginalChunk;
999
+ }
1000
+ cloned.lastChunk = clonedChunk;
1001
+ if (this.indentExclusionRanges) cloned.indentExclusionRanges = this.indentExclusionRanges.slice();
1002
+ cloned.sourcemapLocations = new BitSet(this.sourcemapLocations);
1003
+ cloned.storedNames = { ...this.storedNames };
1004
+ cloned.intro = this.intro;
1005
+ cloned.outro = this.outro;
1006
+ cloned.hasMovedChunks = this.hasMovedChunks;
1007
+ return cloned;
1008
+ }
1009
+ /**
1010
+ * Generates a sourcemap object with raw mappings in array form, rather than encoded as a string.
1011
+ * Useful if you need to manipulate the sourcemap further, but most of the time you will use `generateMap` instead.
1012
+ */
1013
+ generateDecodedMap(options) {
1014
+ options = options || {};
1015
+ const mappings = new Mappings(options.hires);
1016
+ const names = this._generateMappings(mappings);
1017
+ return {
1018
+ ...this._mapProperties(options, names),
1019
+ mappings: mappings.raw,
1020
+ rangeMappings: mappings.rawRangeMappings
1021
+ };
1022
+ }
1023
+ /**
1024
+ * Generates a version 3 sourcemap.
1025
+ */
1026
+ generateMap(options) {
1027
+ options = options || {};
1028
+ const encoder = new MappingsEncoder();
1029
+ const mappings = new Mappings(options.hires, encoder);
1030
+ const names = this._generateMappings(mappings);
1031
+ return new SourceMap({
1032
+ ...this._mapProperties(options, names),
1033
+ mappings: encoder.finish(mappings.rawSegments),
1034
+ rangeMappings: mappings.rawRangeMappings
1035
+ });
1036
+ }
1037
+ /** @internal */
1038
+ _generateMappings(mappings) {
1039
+ const sourceIndex = 0;
1040
+ const names = Object.keys(this.storedNames);
1041
+ const locate = getLocator(this.original);
1042
+ if (this.intro) mappings.advance(this.intro);
1043
+ this.firstChunk.eachNext((chunk) => {
1044
+ const loc = locate(chunk.start);
1045
+ if (chunk.intro.length) mappings.advance(chunk.intro);
1046
+ if (chunk.edited) mappings.addEdit(sourceIndex, chunk.content, loc, chunk.storeName ? names.indexOf(chunk.original) : -1);
1047
+ else mappings.addUneditedChunk(sourceIndex, chunk, this.original, loc, this.sourcemapLocations);
1048
+ if (chunk.outro.length) mappings.advance(chunk.outro);
1049
+ });
1050
+ if (this.outro) mappings.advance(this.outro);
1051
+ return names;
1052
+ }
1053
+ /** @internal */
1054
+ _mapProperties(options, names) {
1055
+ return {
1056
+ file: options.file ? options.file.split(/[/\\]/).pop() : void 0,
1057
+ sources: [options.source ? getRelativePath(options.file || "", options.source) : options.file || ""],
1058
+ sourcesContent: options.includeContent ? [this.original] : void 0,
1059
+ names,
1060
+ x_google_ignoreList: this.ignoreList ? [0] : void 0
1061
+ };
1062
+ }
1063
+ /** @internal */
1064
+ _ensureindentStr() {
1065
+ if (this.indentStr === void 0) this.indentStr = guessIndent(this.original);
1066
+ }
1067
+ /** @internal */
1068
+ _getRawIndentString() {
1069
+ this._ensureindentStr();
1070
+ return this.indentStr;
1071
+ }
1072
+ getIndentString() {
1073
+ this._ensureindentStr();
1074
+ return this.indentStr === null ? " " : this.indentStr;
1075
+ }
1076
+ indent(indentStr, options) {
1077
+ const pattern = /^[^\r\n]/gm;
1078
+ if (isObject(indentStr)) {
1079
+ options = indentStr;
1080
+ indentStr = void 0;
1081
+ }
1082
+ if (indentStr === void 0) {
1083
+ this._ensureindentStr();
1084
+ indentStr = this.indentStr || " ";
1085
+ }
1086
+ if (indentStr === "") return this;
1087
+ const resolvedIndentStr = indentStr;
1088
+ options = options || {};
1089
+ const isExcluded = {};
1090
+ if (options.exclude) (typeof options.exclude[0] === "number" ? [options.exclude] : options.exclude).forEach((exclusion) => {
1091
+ for (let i = exclusion[0]; i < exclusion[1]; i += 1) isExcluded[i] = true;
1092
+ });
1093
+ let shouldIndentNextCharacter = options.indentStart !== false;
1094
+ const indentPiece = (str) => {
1095
+ if (str === "") return str;
1096
+ const indented = str.replace(pattern, (match, offset) => offset > 0 || shouldIndentNextCharacter ? `${resolvedIndentStr}${match}` : match);
1097
+ shouldIndentNextCharacter = str[str.length - 1] === "\n";
1098
+ return indented;
1099
+ };
1100
+ this.intro = indentPiece(this.intro);
1101
+ let charIndex = 0;
1102
+ let chunk = this.firstChunk;
1103
+ const indentAt = (index) => {
1104
+ shouldIndentNextCharacter = false;
1105
+ if (index === chunk.start) chunk.appendRight(resolvedIndentStr);
1106
+ else {
1107
+ this._splitChunk(chunk, index);
1108
+ chunk = chunk.next;
1109
+ chunk.prependRight(resolvedIndentStr);
1110
+ }
1111
+ };
1112
+ while (chunk) {
1113
+ const end = chunk.end;
1114
+ if (!isExcluded[chunk.start]) chunk.intro = indentPiece(chunk.intro);
1115
+ if (chunk.edited) {
1116
+ if (!isExcluded[charIndex]) chunk.content = indentPiece(chunk.content);
1117
+ } else if (options.exclude) {
1118
+ charIndex = chunk.start;
1119
+ while (charIndex < end) {
1120
+ if (!isExcluded[charIndex]) {
1121
+ const char = this.original.charCodeAt(charIndex);
1122
+ if (char === NEWLINE_CHAR) shouldIndentNextCharacter = true;
1123
+ else if (char !== CR_CHAR && shouldIndentNextCharacter) indentAt(charIndex);
1124
+ }
1125
+ charIndex += 1;
1126
+ }
1127
+ } else {
1128
+ charIndex = chunk.start;
1129
+ while (charIndex < end) {
1130
+ if (!shouldIndentNextCharacter) {
1131
+ const nextLine = this.original.indexOf(n, charIndex);
1132
+ if (nextLine === -1 || nextLine >= end) break;
1133
+ shouldIndentNextCharacter = true;
1134
+ charIndex = nextLine + 1;
1135
+ continue;
1136
+ }
1137
+ const char = this.original.charCodeAt(charIndex);
1138
+ if (char === NEWLINE_CHAR || char === CR_CHAR) {
1139
+ charIndex += 1;
1140
+ continue;
1141
+ }
1142
+ indentAt(charIndex);
1143
+ charIndex += 1;
1144
+ }
1145
+ }
1146
+ if (!isExcluded[chunk.end - 1]) chunk.outro = indentPiece(chunk.outro);
1147
+ charIndex = chunk.end;
1148
+ chunk = chunk.next;
1149
+ }
1150
+ this.outro = indentPiece(this.outro);
1151
+ return this;
1152
+ }
1153
+ /** @internal */
1154
+ insert() {
1155
+ throw new MagicStringError("insert() is deprecated, use appendLeft() or prependRight()");
1156
+ }
1157
+ /** @internal */
1158
+ insertLeft(index, content) {
1159
+ if (!warned.insertLeft) {
1160
+ console.warn("magicString.insertLeft(...) is deprecated. Use magicString.appendLeft(...) instead");
1161
+ warned.insertLeft = true;
1162
+ }
1163
+ return this.appendLeft(index, content);
1164
+ }
1165
+ /** @internal */
1166
+ insertRight(index, content) {
1167
+ if (!warned.insertRight) {
1168
+ console.warn("magicString.insertRight(...) is deprecated. Use magicString.prependRight(...) instead");
1169
+ warned.insertRight = true;
1170
+ }
1171
+ return this.prependRight(index, content);
1172
+ }
1173
+ /**
1174
+ * Moves the characters from `start` and `end` to `index`.
1175
+ *
1176
+ * `affinity` controls where the range is anchored at `index`. With the
1177
+ * default `'right'`, it is inserted before the content that starts at `index`;
1178
+ * with `'left'`, it is inserted after the content that ends at `index`. The
1179
+ * two differ only when other content has already been moved to that boundary,
1180
+ * mirroring the `appendLeft`/`appendRight` distinction.
1181
+ */
1182
+ move(start, end, index, affinity = "right") {
1183
+ start = start + this.offset;
1184
+ end = end + this.offset;
1185
+ index = index + this.offset;
1186
+ if (start === end) return this;
1187
+ if (index >= start && index <= end) throw new MagicStringError("cannot move a selection inside itself");
1188
+ this._split(start);
1189
+ this._split(end);
1190
+ this._split(index);
1191
+ const first = this.byStart.get(start);
1192
+ const last = this.byEnd.get(end);
1193
+ if (this.hasMovedChunks) {
1194
+ let cursor = first;
1195
+ while (cursor !== last) {
1196
+ cursor = cursor.next;
1197
+ if (!cursor || cursor.start < start || cursor.end > end) throw new MagicStringError(`cannot move ${start} to ${end} because an earlier move split that range`);
1198
+ }
1199
+ }
1200
+ const oldLeft = first.previous;
1201
+ const oldRight = last.next;
1202
+ let newLeft;
1203
+ let newRight;
1204
+ if (affinity === "left") {
1205
+ newLeft = this.byEnd.get(index) ?? null;
1206
+ if (!newLeft) {
1207
+ if (first === this.firstChunk) return this;
1208
+ newRight = this.firstChunk;
1209
+ } else {
1210
+ if (newLeft.next === first) return this;
1211
+ newRight = newLeft.next;
1212
+ }
1213
+ } else {
1214
+ newRight = this.byStart.get(index) ?? null;
1215
+ if (!newRight) {
1216
+ if (last === this.lastChunk) return this;
1217
+ newLeft = this.lastChunk;
1218
+ } else {
1219
+ if (newRight.previous === last) return this;
1220
+ newLeft = newRight.previous;
1221
+ }
1222
+ }
1223
+ if (oldLeft) oldLeft.next = oldRight;
1224
+ if (oldRight) oldRight.previous = oldLeft;
1225
+ if (newLeft) newLeft.next = first;
1226
+ if (newRight) newRight.previous = last;
1227
+ if (!first.previous) this.firstChunk = last.next;
1228
+ if (!last.next) {
1229
+ this.lastChunk = first.previous;
1230
+ this.lastChunk.next = null;
1231
+ }
1232
+ first.previous = newLeft;
1233
+ last.next = newRight || null;
1234
+ if (!newLeft) this.firstChunk = first;
1235
+ if (!newRight) this.lastChunk = last;
1236
+ this.hasMovedChunks = true;
1237
+ return this;
1238
+ }
1239
+ /**
1240
+ * Replaces the characters from `start` to `end` with `content`, along with the appended/prepended content in
1241
+ * that range. The same restrictions as `s.remove()` apply.
1242
+ *
1243
+ * The fourth argument is optional. It can have a storeName property - if true, the original name will be stored
1244
+ * for later inclusion in a sourcemap's names array - and a contentOnly property which determines whether only
1245
+ * the content is overwritten, or anything that was appended/prepended to the range as well.
1246
+ *
1247
+ * It may be preferred to use `s.update(...)` instead if you wish to avoid overwriting the appended/prepended content.
1248
+ */
1249
+ overwrite(start, end, content, options) {
1250
+ const optionObject = typeof options === "object" && options ? options : {};
1251
+ return this.update(start, end, content, {
1252
+ ...optionObject,
1253
+ overwrite: !optionObject.contentOnly
1254
+ });
1255
+ }
1256
+ /**
1257
+ * Replaces the characters from `start` to `end` with `content`. The same restrictions as `s.remove()` apply.
1258
+ *
1259
+ * The fourth argument is optional. It can have a storeName property - if true, the original name will be stored
1260
+ * for later inclusion in a sourcemap's names array - and an overwrite property which determines whether only
1261
+ * the content is overwritten, or anything that was appended/prepended to the range as well.
1262
+ */
1263
+ update(start, end, content, options) {
1264
+ start = start + this.offset;
1265
+ end = end + this.offset;
1266
+ if (typeof content !== "string") throw new MagicStringError(`content must be a string, got ${typeof content}`);
1267
+ if (this.original.length !== 0) {
1268
+ if (start < 0) start = Math.max(0, start + this.original.length);
1269
+ if (end < 0) end = Math.max(0, end + this.original.length);
1270
+ }
1271
+ if (start < 0) throw new MagicStringError(`start ${start} is out of bounds`);
1272
+ if (end > this.original.length) throw new MagicStringError(`end ${end} is out of bounds`);
1273
+ if (start === end) throw new MagicStringError(`cannot overwrite a zero-length range at ${start}, use appendLeft() or prependRight()`);
1274
+ if (start > end) throw new MagicStringError(`end must be greater than start (start: ${start}, end: ${end})`);
1275
+ this._split(start);
1276
+ this._split(end);
1277
+ if (options === true) {
1278
+ if (!warned.storeName) {
1279
+ console.warn("The final argument to magicString.overwrite(...) should be an options object. See https://github.com/rich-harris/magic-string");
1280
+ warned.storeName = true;
1281
+ }
1282
+ options = { storeName: true };
1283
+ }
1284
+ const optionObject = typeof options === "object" && options ? options : {};
1285
+ const storeName = optionObject.storeName || false;
1286
+ const overwrite = optionObject.overwrite || false;
1287
+ if (storeName) {
1288
+ const original = this.original.slice(start, end);
1289
+ Object.defineProperty(this.storedNames, original, {
1290
+ writable: true,
1291
+ value: true,
1292
+ enumerable: true
1293
+ });
1294
+ }
1295
+ const first = this.byStart.get(start);
1296
+ const last = this.byEnd.get(end);
1297
+ /* v8 ignore else -- unreachable: a valid start/end always yields a `first` chunk */
1298
+ if (first) {
1299
+ let chunk = first;
1300
+ while (chunk !== last) {
1301
+ if (chunk.next !== this.byStart.get(chunk.end)) throw new MagicStringError("cannot overwrite across a split point");
1302
+ chunk = chunk.next;
1303
+ chunk.edit("", false, !overwrite);
1304
+ }
1305
+ first.edit(content, storeName, !overwrite);
1306
+ } else {
1307
+ const newChunk = new Chunk(start, end, "").edit(content, storeName);
1308
+ last.next = newChunk;
1309
+ newChunk.previous = last;
1310
+ }
1311
+ return this;
1312
+ }
1313
+ /**
1314
+ * Prepends the string with the specified content.
1315
+ */
1316
+ prepend(content) {
1317
+ if (typeof content !== "string") throw new MagicStringError(`content must be a string, got ${typeof content}`);
1318
+ this.intro = content + this.intro;
1319
+ return this;
1320
+ }
1321
+ /**
1322
+ * Same as `s.appendLeft(...)`, except that the inserted content will go *before* any previous appends or prepends at index
1323
+ */
1324
+ prependLeft(index, content) {
1325
+ index = index + this.offset;
1326
+ if (typeof content !== "string") throw new MagicStringError(`content must be a string, got ${typeof content}`);
1327
+ this._split(index);
1328
+ const chunk = this.byEnd.get(index);
1329
+ if (chunk) chunk.prependLeft(content);
1330
+ else this.intro = content + this.intro;
1331
+ return this;
1332
+ }
1333
+ /**
1334
+ * Same as `s.appendRight(...)`, except that the inserted content will go *before* any previous appends or prepends at `index`
1335
+ */
1336
+ prependRight(index, content) {
1337
+ index = index + this.offset;
1338
+ if (typeof content !== "string") throw new MagicStringError(`content must be a string, got ${typeof content}`);
1339
+ this._split(index);
1340
+ const chunk = this.byStart.get(index);
1341
+ if (chunk) chunk.prependRight(content);
1342
+ else this.outro = content + this.outro;
1343
+ return this;
1344
+ }
1345
+ /**
1346
+ * Removes the characters from `start` to `end` (of the original string, **not** the generated string).
1347
+ * Content appended or prepended at positions strictly inside the range is removed with it, while
1348
+ * content attached at `start` or `end` is preserved — use `s.overwrite(start, end, '')` to remove
1349
+ * the range including its edge inserts.
1350
+ * Repeated removals and removals with partially overlapping ranges are allowed.
1351
+ */
1352
+ remove(start, end) {
1353
+ start = start + this.offset;
1354
+ end = end + this.offset;
1355
+ if (this.original.length !== 0) {
1356
+ if (start < 0) start = Math.max(0, start + this.original.length);
1357
+ if (end < 0) end = Math.max(0, end + this.original.length);
1358
+ }
1359
+ if (start === end) return this;
1360
+ if (start < 0 || end > this.original.length) throw new MagicStringError(`range ${start}–${end} is out of bounds`);
1361
+ if (start > end) throw new MagicStringError(`end must be greater than start (start: ${start}, end: ${end})`);
1362
+ this._split(start);
1363
+ this._split(end);
1364
+ let chunk = this.byStart.get(start);
1365
+ while (chunk) {
1366
+ if (chunk.start > start) chunk.intro = "";
1367
+ if (chunk.end < end) chunk.outro = "";
1368
+ chunk.edit("", false, true);
1369
+ chunk = end > chunk.end ? this.byStart.get(chunk.end) : null;
1370
+ }
1371
+ return this;
1372
+ }
1373
+ /**
1374
+ * Reset the modified characters from `start` to `end` (of the original string, **not** the generated string).
1375
+ */
1376
+ reset(start, end) {
1377
+ start = start + this.offset;
1378
+ end = end + this.offset;
1379
+ if (this.original.length !== 0) {
1380
+ if (start < 0) start = Math.max(0, start + this.original.length);
1381
+ if (end < 0) end = Math.max(0, end + this.original.length);
1382
+ }
1383
+ if (start === end) return this;
1384
+ if (start < 0 || end > this.original.length) throw new MagicStringError(`range ${start}–${end} is out of bounds`);
1385
+ if (start > end) throw new MagicStringError(`end must be greater than start (start: ${start}, end: ${end})`);
1386
+ this._split(start);
1387
+ this._split(end);
1388
+ let chunk = this.byStart.get(start);
1389
+ while (chunk) {
1390
+ chunk.reset();
1391
+ chunk = end > chunk.end ? this.byStart.get(chunk.end) : null;
1392
+ }
1393
+ return this;
1394
+ }
1395
+ lastChar() {
1396
+ if (this.outro.length) return this.outro[this.outro.length - 1];
1397
+ let chunk = this.lastChunk;
1398
+ while (chunk) {
1399
+ if (chunk.outro.length) return chunk.outro[chunk.outro.length - 1];
1400
+ if (chunk.content.length) return chunk.content[chunk.content.length - 1];
1401
+ if (chunk.intro.length) return chunk.intro[chunk.intro.length - 1];
1402
+ chunk = chunk.previous;
1403
+ }
1404
+ if (this.intro.length) return this.intro[this.intro.length - 1];
1405
+ return "";
1406
+ }
1407
+ lastLine() {
1408
+ let lineIndex = this.outro.lastIndexOf(n);
1409
+ if (lineIndex !== -1) return this.outro.substr(lineIndex + 1);
1410
+ let lineStr = this.outro;
1411
+ let chunk = this.lastChunk;
1412
+ while (chunk) {
1413
+ if (chunk.outro.length > 0) {
1414
+ lineIndex = chunk.outro.lastIndexOf(n);
1415
+ if (lineIndex !== -1) return chunk.outro.substr(lineIndex + 1) + lineStr;
1416
+ lineStr = chunk.outro + lineStr;
1417
+ }
1418
+ if (chunk.content.length > 0) {
1419
+ lineIndex = chunk.content.lastIndexOf(n);
1420
+ if (lineIndex !== -1) return chunk.content.substr(lineIndex + 1) + lineStr;
1421
+ lineStr = chunk.content + lineStr;
1422
+ }
1423
+ if (chunk.intro.length > 0) {
1424
+ lineIndex = chunk.intro.lastIndexOf(n);
1425
+ if (lineIndex !== -1) return chunk.intro.substr(lineIndex + 1) + lineStr;
1426
+ lineStr = chunk.intro + lineStr;
1427
+ }
1428
+ chunk = chunk.previous;
1429
+ }
1430
+ lineIndex = this.intro.lastIndexOf(n);
1431
+ if (lineIndex !== -1) return this.intro.substr(lineIndex + 1) + lineStr;
1432
+ return this.intro + lineStr;
1433
+ }
1434
+ /**
1435
+ * Returns the content of the generated string that corresponds to the slice between `start` and `end` of the original string.
1436
+ * Throws error if the indices are for characters that were already removed.
1437
+ */
1438
+ slice(start = 0, end = this.original.length - this.offset) {
1439
+ start = start + this.offset;
1440
+ end = end + this.offset;
1441
+ if (this.original.length !== 0) {
1442
+ if (start < 0) start = Math.max(0, start + this.original.length);
1443
+ if (end < 0) end = Math.max(0, end + this.original.length);
1444
+ }
1445
+ let result = "";
1446
+ let chunk = this.firstChunk;
1447
+ while (chunk && (chunk.start > start || chunk.end <= start)) {
1448
+ if (chunk.start < end && chunk.end >= end || end === 0 && chunk.start === 0) return result;
1449
+ chunk = chunk.next;
1450
+ }
1451
+ if (chunk && chunk.edited && chunk.start !== start) throw new MagicStringError(`cannot use edited character ${start} as slice start anchor`);
1452
+ const startChunk = chunk;
1453
+ while (chunk) {
1454
+ if (end === 0 && chunk.start === 0) break;
1455
+ if (chunk.intro && (startChunk !== chunk || chunk.start === start)) result += chunk.intro;
1456
+ const containsEnd = chunk.start < end && chunk.end >= end;
1457
+ if (containsEnd && chunk.edited && chunk.end !== end) throw new MagicStringError(`cannot use edited character ${end} as slice end anchor`);
1458
+ const sliceStart = startChunk === chunk ? start - chunk.start : 0;
1459
+ const sliceEnd = containsEnd ? chunk.content.length + end - chunk.end : chunk.content.length;
1460
+ result += chunk.content.slice(sliceStart, sliceEnd);
1461
+ if (chunk.outro && (!containsEnd || chunk.end === end)) result += chunk.outro;
1462
+ if (containsEnd) break;
1463
+ chunk = chunk.next;
1464
+ }
1465
+ return result;
1466
+ }
1467
+ /**
1468
+ * Returns a clone of `s`, with all content before the `start` and `end` characters of the original string removed.
1469
+ */
1470
+ snip(start, end) {
1471
+ const clone = this.clone();
1472
+ clone.remove(0, start);
1473
+ clone.remove(end, clone.original.length);
1474
+ return clone;
1475
+ }
1476
+ /** @internal */
1477
+ _split(index) {
1478
+ if (this.byStart.get(index) || this.byEnd.get(index)) return;
1479
+ let chunk = this.lastSearchedChunk;
1480
+ let previousChunk = chunk;
1481
+ const searchForward = index > chunk.end;
1482
+ while (chunk) {
1483
+ if (chunk.contains(index)) return this._splitChunk(chunk, index);
1484
+ chunk = searchForward ? this.byStart.get(chunk.end) : this.byEnd.get(chunk.start);
1485
+ if (chunk === previousChunk) return;
1486
+ previousChunk = chunk;
1487
+ }
1488
+ }
1489
+ /** @internal */
1490
+ _splitChunk(chunk, index) {
1491
+ if (chunk.edited && chunk.content.length) {
1492
+ const loc = getLocator(this.original)(index);
1493
+ throw new MagicStringError(`cannot split a chunk that has already been edited (${loc.line}:${loc.column} – "${chunk.original}")`);
1494
+ }
1495
+ const newChunk = chunk.split(index);
1496
+ this.byEnd.set(index, chunk);
1497
+ this.byStart.set(index, newChunk);
1498
+ this.byEnd.set(newChunk.end, newChunk);
1499
+ if (chunk === this.lastChunk) this.lastChunk = newChunk;
1500
+ this.lastSearchedChunk = chunk;
1501
+ return true;
1502
+ }
1503
+ /**
1504
+ * Returns the generated string.
1505
+ */
1506
+ toString() {
1507
+ let str = this.intro;
1508
+ let chunk = this.firstChunk;
1509
+ while (chunk) {
1510
+ str += chunk.toString();
1511
+ chunk = chunk.next;
1512
+ }
1513
+ return str + this.outro;
1514
+ }
1515
+ /**
1516
+ * Returns true if the resulting source is empty (disregarding white space).
1517
+ */
1518
+ isEmpty() {
1519
+ if (this.intro.length && this.intro.trim()) return false;
1520
+ let chunk = this.firstChunk;
1521
+ while (chunk) {
1522
+ if (chunk.intro.length && chunk.intro.trim() || chunk.content.length && chunk.content.trim() || chunk.outro.length && chunk.outro.trim()) return false;
1523
+ chunk = chunk.next;
1524
+ }
1525
+ if (this.outro.length && this.outro.trim()) return false;
1526
+ return true;
1527
+ }
1528
+ length() {
1529
+ let chunk = this.firstChunk;
1530
+ let length = 0;
1531
+ while (chunk) {
1532
+ length += chunk.intro.length + chunk.content.length + chunk.outro.length;
1533
+ chunk = chunk.next;
1534
+ }
1535
+ return length;
1536
+ }
1537
+ /**
1538
+ * Removes empty lines from the start and end.
1539
+ */
1540
+ trimLines() {
1541
+ return this.trim("[\\r\\n]");
1542
+ }
1543
+ /**
1544
+ * Trims content matching `charType` (defaults to `\s`, i.e. whitespace) from the start and end.
1545
+ */
1546
+ trim(charType) {
1547
+ return this.trimStart(charType).trimEnd(charType);
1548
+ }
1549
+ /** @internal */
1550
+ trimEndAborted(charType) {
1551
+ const rx = new RegExp(`${charType || "\\s"}+$`);
1552
+ this.outro = this.outro.replace(rx, "");
1553
+ if (this.outro.length) return true;
1554
+ let chunk = this.lastChunk;
1555
+ do {
1556
+ const end = chunk.end;
1557
+ const aborted = chunk.trimEnd(rx);
1558
+ if (chunk.end !== end) {
1559
+ if (this.lastChunk === chunk) this.lastChunk = chunk.next;
1560
+ this.byEnd.set(chunk.end, chunk);
1561
+ this.byStart.set(chunk.next.start, chunk.next);
1562
+ this.byEnd.set(chunk.next.end, chunk.next);
1563
+ }
1564
+ if (aborted) return true;
1565
+ chunk = chunk.previous;
1566
+ } while (chunk);
1567
+ this.intro = this.intro.replace(rx, "");
1568
+ return this.intro.length > 0;
1569
+ }
1570
+ /**
1571
+ * Trims content matching `charType` (defaults to `\s`, i.e. whitespace) from the end.
1572
+ */
1573
+ trimEnd(charType) {
1574
+ this.trimEndAborted(charType);
1575
+ return this;
1576
+ }
1577
+ /** @internal */
1578
+ trimStartAborted(charType) {
1579
+ const rx = new RegExp(`^${charType || "\\s"}+`);
1580
+ this.intro = this.intro.replace(rx, "");
1581
+ if (this.intro.length) return true;
1582
+ let chunk = this.firstChunk;
1583
+ do {
1584
+ const end = chunk.end;
1585
+ const aborted = chunk.trimStart(rx);
1586
+ if (chunk.end !== end) {
1587
+ if (chunk === this.lastChunk) this.lastChunk = chunk.next;
1588
+ this.byEnd.set(chunk.end, chunk);
1589
+ this.byStart.set(chunk.next.start, chunk.next);
1590
+ this.byEnd.set(chunk.next.end, chunk.next);
1591
+ }
1592
+ if (aborted) return true;
1593
+ chunk = chunk.next;
1594
+ } while (chunk);
1595
+ this.outro = this.outro.replace(rx, "");
1596
+ return this.outro.length > 0;
1597
+ }
1598
+ /**
1599
+ * Trims content matching `charType` (defaults to `\s`, i.e. whitespace) from the start.
1600
+ */
1601
+ trimStart(charType) {
1602
+ this.trimStartAborted(charType);
1603
+ return this;
1604
+ }
1605
+ /**
1606
+ * Indicates if the string has been changed.
1607
+ */
1608
+ hasChanged() {
1609
+ if (this.intro || this.outro) return true;
1610
+ let outputIndex = 0;
1611
+ let chunk = this.firstChunk;
1612
+ while (chunk) {
1613
+ if (chunk.intro || chunk.outro) return true;
1614
+ if (!chunk.edited && chunk.start === outputIndex) outputIndex = chunk.end;
1615
+ else {
1616
+ if (!this.original.startsWith(chunk.content, outputIndex)) return true;
1617
+ outputIndex += chunk.content.length;
1618
+ }
1619
+ chunk = chunk.next;
1620
+ }
1621
+ return outputIndex !== this.original.length;
1622
+ }
1623
+ /**
1624
+ * Whether the original range [start, end) has had any of its characters
1625
+ * removed. `replace`/`replaceAll` search `original`, so a match can land on
1626
+ * text that is no longer in the output - overwriting it would resurrect the
1627
+ * removed characters, so such matches are skipped instead.
1628
+ *
1629
+ * @internal
1630
+ */
1631
+ _hasRemovedContent(start, end) {
1632
+ let chunk = this.byStart.get(start);
1633
+ if (!chunk) {
1634
+ chunk = this.lastSearchedChunk;
1635
+ const searchForward = start >= chunk.end;
1636
+ while (chunk && !chunk.contains(start)) chunk = searchForward ? this.byStart.get(chunk.end) : this.byEnd.get(chunk.start);
1637
+ if (chunk) this.lastSearchedChunk = chunk;
1638
+ }
1639
+ while (chunk && chunk.start < end) {
1640
+ if (chunk.content === "") return true;
1641
+ chunk = this.byStart.get(chunk.end);
1642
+ }
1643
+ return false;
1644
+ }
1645
+ /** @internal */
1646
+ _replaceRegexp(searchValue, replacement) {
1647
+ function getReplacement(match, str) {
1648
+ if (typeof replacement === "string") return expandReplacement(replacement, match[0], match.index, str, match.slice(1), match.groups);
1649
+ else return match.groups === void 0 ? replacement(match[0], ...match.slice(1), match.index, str) : replacement(match[0], ...match.slice(1), match.index, str, match.groups);
1650
+ }
1651
+ const replaceMatch = (match) => {
1652
+ /* v8 ignore next 2 -- `match.index` is always defined for matches from `matchAll` */
1653
+ if (match.index == null) return false;
1654
+ if (this._hasRemovedContent(match.index, match.index + match[0].length)) return false;
1655
+ const replacement = getReplacement(match, this.original);
1656
+ if (replacement === match[0]) return true;
1657
+ if (match[0].length === 0) this.appendRight(match.index - this.offset, replacement);
1658
+ else this.overwrite(match.index - this.offset, match.index + match[0].length - this.offset, replacement);
1659
+ return true;
1660
+ };
1661
+ if (searchValue.global) {
1662
+ searchValue.lastIndex = 0;
1663
+ for (const match of this.original.matchAll(searchValue)) replaceMatch(match);
1664
+ } else {
1665
+ const match = this.original.match(searchValue);
1666
+ if (match && !replaceMatch(match)) {
1667
+ const global = new RegExp(searchValue.source, `${searchValue.flags}g`);
1668
+ for (const next of this.original.matchAll(global)) if (replaceMatch(next)) break;
1669
+ }
1670
+ }
1671
+ return this;
1672
+ }
1673
+ /** @internal */
1674
+ _replaceString(string, replacement) {
1675
+ const { original } = this;
1676
+ let index = original.indexOf(string);
1677
+ while (index !== -1) {
1678
+ if (this._hasRemovedContent(index, index + string.length)) {
1679
+ index = original.indexOf(string, index + string.length);
1680
+ continue;
1681
+ }
1682
+ if (typeof replacement === "function") replacement = replacement(string, index, original);
1683
+ else replacement = expandReplacement(replacement, string, index, original, [], void 0);
1684
+ if (string !== replacement) {
1685
+ if (string.length === 0) this.appendRight(index - this.offset, replacement);
1686
+ else this.overwrite(index - this.offset, index + string.length - this.offset, replacement);
1687
+ }
1688
+ break;
1689
+ }
1690
+ return this;
1691
+ }
1692
+ /**
1693
+ * String replacement with RegExp or string.
1694
+ */
1695
+ replace(searchValue, replacement) {
1696
+ if (typeof searchValue === "string") return this._replaceString(searchValue, replacement);
1697
+ return this._replaceRegexp(searchValue, replacement);
1698
+ }
1699
+ /** @internal */
1700
+ _replaceAllString(string, replacement) {
1701
+ const { original } = this;
1702
+ const stringLength = string.length;
1703
+ if (stringLength === 0) {
1704
+ for (let index = 0; index <= original.length; index += 1) {
1705
+ if (this._hasRemovedContent(index, index)) continue;
1706
+ const _replacement = typeof replacement === "function" ? replacement("", index, original) : expandReplacement(replacement, "", index, original, [], void 0);
1707
+ if (_replacement !== "") this.appendRight(index - this.offset, _replacement);
1708
+ }
1709
+ return this;
1710
+ }
1711
+ for (let index = original.indexOf(string); index !== -1; index = original.indexOf(string, index + stringLength)) {
1712
+ if (this._hasRemovedContent(index, index + stringLength)) continue;
1713
+ const previous = original.slice(index, index + stringLength);
1714
+ const _replacement = typeof replacement === "function" ? replacement(previous, index, original) : expandReplacement(replacement, previous, index, original, [], void 0);
1715
+ if (previous !== _replacement) this.overwrite(index - this.offset, index + stringLength - this.offset, _replacement);
1716
+ }
1717
+ return this;
1718
+ }
1719
+ /**
1720
+ * Same as `s.replace`, but replace all matched strings instead of just one.
1721
+ */
1722
+ replaceAll(searchValue, replacement) {
1723
+ if (typeof searchValue === "string") return this._replaceAllString(searchValue, replacement);
1724
+ if (!searchValue.global) throw new MagicStringError("replaceAll() requires a global RegExp");
1725
+ return this._replaceRegexp(searchValue, replacement);
1726
+ }
1727
+ };
1728
+ //#endregion
1729
+ //#region ../../node_modules/.pnpm/@iconify+utils@3.1.7/node_modules/@iconify/utils/lib/svg/url.js
1730
+ /**
1731
+ * Encode SVG for use in url()
1732
+ *
1733
+ * Short alternative to encodeURIComponent() that encodes only stuff used in SVG, generating
1734
+ * smaller code.
1735
+ */
1736
+ function encodeSVGforURL(svg) {
1737
+ return svg.replace(/"/g, "'").replace(/%/g, "%25").replace(/#/g, "%23").replace(/</g, "%3C").replace(/>/g, "%3E").replace(/\s+/g, " ");
1738
+ }
1739
+ //#endregion
1740
+ //#region ../../node_modules/.pnpm/@iconify+utils@3.1.7/node_modules/@iconify/utils/lib/svg/encode-svg-for-css.js
1741
+ /**
1742
+ * Encode the `SVG` to be used on `CSS`: https://bl.ocks.org/jennyknuth/222825e315d45a738ed9d6e04c7a88d0.
1743
+ *
1744
+ * @param svg The `SVG` source.
1745
+ */
1746
+ function encodeSvgForCss(svg) {
1747
+ let useSvg = svg.startsWith("<svg>") ? svg.replace("<svg>", "<svg >") : svg;
1748
+ if (!useSvg.includes(" xmlns:xlink=") && useSvg.includes(" xlink:")) useSvg = useSvg.replace("<svg ", "<svg xmlns:xlink=\"http://www.w3.org/1999/xlink\" ");
1749
+ if (!useSvg.includes(" xmlns=")) useSvg = useSvg.replace("<svg ", "<svg xmlns=\"http://www.w3.org/2000/svg\" ");
1750
+ return encodeSVGforURL(useSvg);
1751
+ }
1752
+ /** `lucide:check` → `mi-lucide--check`: `--` never occurs in a name, so the class reads back (D4). */
1753
+ function iconClass(name) {
1754
+ return `mi-${name.replace(":", "--")}`;
1755
+ }
1756
+ /** `mi-lucide--check` (among other classes) → `lucide:check`, the inverse of `iconClass`. */
1757
+ function nameOfClass(classes) {
1758
+ for (const c of classes.split(/\s+/)) {
1759
+ const match = /^mi-([a-z0-9-]+?)--([a-z0-9-]+)$/.exec(c);
1760
+ if (match) return `${match[1]}:${match[2]}`;
1761
+ }
1762
+ }
1763
+ const FILL = "50%/100% 100% no-repeat";
1764
+ function baseCss(layer) {
1765
+ return `@layer ${layer}{.mi{display:inline-block;width:1em;height:1em;flex-shrink:0;vertical-align:-.125em;background:currentColor;mask:var(--mi) ${FILL};forced-color-adjust:none}}\n`;
1766
+ }
1767
+ /** One icon's rule. A wider or taller icon keeps its ratio at `1em` high. */
1768
+ function iconCss(name, icon, layer) {
1769
+ const body = icon.mono ? icon.body.replaceAll("currentColor", "black") : icon.body;
1770
+ let rule = `--mi:url("data:image/svg+xml,${encodeSvgForCss(`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${icon.width} ${icon.height}">${body}</svg>`)}");`;
1771
+ if (!icon.mono) rule += `background:var(--mi) ${FILL};mask:none;`;
1772
+ if (icon.width !== icon.height) rule += `width:${round(icon.width / icon.height)}em;`;
1773
+ return `@layer ${layer}{${rule.indexOf(";") === rule.length - 1 ? `.${iconClass(name)}` : `.mi.${iconClass(name)}`}{${rule.slice(0, -1)}}}\n`;
1774
+ }
1775
+ function round(n) {
1776
+ return Math.round(n * 1e3) / 1e3;
1777
+ }
1778
+ //#endregion
1779
+ //#region src/vite/compile.ts
1780
+ /**
1781
+ * The transform (D2, D3, D6): every `icon("set:name", { label, class })`
1782
+ * of a module becomes a literal attribute object, and the module imports
1783
+ * the base CSS and one CSS module per icon it names. It runs on JavaScript,
1784
+ * after the framework compilers, so `.vue`, `.svelte`, `.astro` and JSX
1785
+ * are one case; Vue's templates call the import through `$setup` or `_unref`.
1786
+ */
1787
+ const PACKAGE$1 = "@menapo/icons";
1788
+ /** The virtual CSS modules, `virtual:menapo-icons/base.css` and `…/lucide--check.css`. */
1789
+ const VIRTUAL = "virtual:menapo-icons/";
1790
+ /** A message for a call the plugin cannot compile, at `start` in the module. */
1791
+ var CompileError = class extends Error {
1792
+ name = "CompileError";
1793
+ start;
1794
+ constructor(message, start) {
1795
+ super(message);
1796
+ this.start = start;
1797
+ }
1798
+ };
1799
+ const RUNTIME_NAME = `icon() takes the name as a string literal: icon("lucide:check"). For a name chosen at runtime, pick from compiled calls: { pdf: icon("lucide:file-text"), other: icon("lucide:file") }`;
1800
+ /** `null` when the module calls no `icon()`. */
1801
+ function compile(code, id, options) {
1802
+ const { program, errors } = parseSync(`${id.replace(/[?#].*$/, "")}.js`, code);
1803
+ if (errors.length) return null;
1804
+ const locals = /* @__PURE__ */ new Set();
1805
+ for (const node of program.body) {
1806
+ if (node.type !== "ImportDeclaration" || node.source.value !== "@menapo/icons") continue;
1807
+ for (const specifier of node.specifiers) if (specifier.type === "ImportSpecifier" && specifier.imported.type === "Identifier" && specifier.imported.name === "icon") locals.add(specifier.local.name);
1808
+ }
1809
+ if (!locals.size) return null;
1810
+ const s = new MagicString(code);
1811
+ const icons = [];
1812
+ walk(program, (node) => {
1813
+ if (node.type !== "CallExpression" || !isIconCallee(node.callee, locals)) return;
1814
+ const [nameArg, optionsArg, extra] = node.arguments;
1815
+ const name = literal(nameArg);
1816
+ if (name === void 0 || extra) throw new CompileError(RUNTIME_NAME, node.start);
1817
+ options.check(name, nameArg.start);
1818
+ if (!icons.includes(name)) icons.push(name);
1819
+ const { label, extraClass } = readOptions(code, optionsArg);
1820
+ const classes = JSON.stringify(`mi ${iconClass(name)}`);
1821
+ const classValue = extraClass ? `${classes.slice(0, -1)} "+((${extraClass})??"")` : classes;
1822
+ const rest = label ? `role:"img","aria-label":(${label})` : `"aria-hidden":"true"`;
1823
+ s.overwrite(node.start, node.end, `({${options.classAttribute}:${classValue},${rest}})`);
1824
+ });
1825
+ if (!icons.length) return null;
1826
+ const imports = [`${VIRTUAL}base.css`, ...icons.map((n) => `${VIRTUAL}${n.replace(":", "--")}.css`)].map((source) => `import ${JSON.stringify(source)};`).join("");
1827
+ let at = 0;
1828
+ for (const node of program.body) if (node.type === "ExpressionStatement" && "directive" in node && node.directive) at = node.end;
1829
+ else break;
1830
+ if (at) s.appendLeft(at, `\n${imports}`);
1831
+ else s.prepend(`${imports}\n`);
1832
+ return {
1833
+ code: s.toString(),
1834
+ map: s.generateMap({
1835
+ hires: "boundary",
1836
+ source: id
1837
+ }),
1838
+ icons
1839
+ };
1840
+ }
1841
+ /** `icon(…)`, or Vue's `$setup.icon(…)` / `$setup["icon"](…)` (dev) and `_unref(icon)(…)` (build) in a template. */
1842
+ function isIconCallee(callee, locals) {
1843
+ if (callee.type === "Identifier") return locals.has(callee.name);
1844
+ if (callee.type === "CallExpression") {
1845
+ const [arg] = callee.arguments;
1846
+ return callee.callee.type === "Identifier" && callee.callee.name === "_unref" && callee.arguments.length === 1 && arg?.type === "Identifier" && locals.has(arg.name);
1847
+ }
1848
+ if (callee.type !== "MemberExpression" || callee.object.type !== "Identifier") return false;
1849
+ if (callee.object.name !== "$setup") return false;
1850
+ const property = callee.property;
1851
+ const key = callee.computed ? literal(property) : property.type === "Identifier" ? property.name : void 0;
1852
+ return key !== void 0 && locals.has(key);
1853
+ }
1854
+ /** A string literal's value, or an expression-free template literal's. */
1855
+ function literal(node) {
1856
+ if (!node) return void 0;
1857
+ if (node.type === "Literal" && typeof node.value === "string") return node.value;
1858
+ if (node.type === "TemplateLiteral" && node.expressions.length === 0) return node.quasis[0]?.value.cooked ?? void 0;
1859
+ }
1860
+ /** The source text of `label` and `class`, kept as written. */
1861
+ function readOptions(code, node) {
1862
+ if (!node) return {};
1863
+ if (node.type !== "ObjectExpression") throw new CompileError("icon()'s options are an object literal: icon(\"lucide:x\", { label: t(\"Close\") })", node.start);
1864
+ const out = {};
1865
+ for (const property of node.properties) {
1866
+ const key = property.type === "Property" && !property.computed ? property.key.type === "Identifier" ? property.key.name : literal(property.key) : void 0;
1867
+ if (property.type !== "Property" || key !== "label" && key !== "class") throw new CompileError("icon() takes two options, label and class: icon(name, { label, class })", property.start);
1868
+ const text = code.slice(property.value.start, property.value.end);
1869
+ if (key === "label") out.label = text;
1870
+ else out.extraClass = text;
1871
+ }
1872
+ return out;
1873
+ }
1874
+ /** Visits every node, parents first. */
1875
+ function walk(node, visit) {
1876
+ if (Array.isArray(node)) {
1877
+ for (const child of node) walk(child, visit);
1878
+ return;
1879
+ }
1880
+ if (node === null || typeof node !== "object") return;
1881
+ const n = node;
1882
+ if (typeof n.type === "string") visit(n);
1883
+ for (const key in n) {
1884
+ if (key === "type" || key === "start" || key === "end" || key === "range" || key === "loc") continue;
1885
+ const value = n[key];
1886
+ if (value !== null && typeof value === "object") walk(value, visit);
1887
+ }
1888
+ }
1889
+ //#endregion
1890
+ //#region ../../node_modules/.pnpm/@iconify+utils@3.1.7/node_modules/@iconify/utils/lib/icon/defaults.js
1891
+ /** Default values for dimensions */
1892
+ const defaultIconDimensions = Object.freeze({
1893
+ left: 0,
1894
+ top: 0,
1895
+ width: 16,
1896
+ height: 16
1897
+ });
1898
+ /** Default values for transformations */
1899
+ const defaultIconTransformations = Object.freeze({
1900
+ rotate: 0,
1901
+ vFlip: false,
1902
+ hFlip: false
1903
+ });
1904
+ /** Default values for all optional IconifyIcon properties */
1905
+ const defaultIconProps = Object.freeze({
1906
+ ...defaultIconDimensions,
1907
+ ...defaultIconTransformations
1908
+ });
1909
+ /** Default values for all properties used in ExtendedIconifyIcon */
1910
+ const defaultExtendedIconProps = Object.freeze({
1911
+ ...defaultIconProps,
1912
+ body: "",
1913
+ hidden: false
1914
+ });
1915
+ //#endregion
1916
+ //#region ../../node_modules/.pnpm/@iconify+utils@3.1.7/node_modules/@iconify/utils/lib/icon/transformations.js
1917
+ /**
1918
+ * Merge transformations
1919
+ */
1920
+ function mergeIconTransformations(obj1, obj2) {
1921
+ const result = {};
1922
+ if (!obj1.hFlip !== !obj2.hFlip) result.hFlip = true;
1923
+ if (!obj1.vFlip !== !obj2.vFlip) result.vFlip = true;
1924
+ const rotate = ((obj1.rotate || 0) + (obj2.rotate || 0)) % 4;
1925
+ if (rotate) result.rotate = rotate;
1926
+ return result;
1927
+ }
1928
+ //#endregion
1929
+ //#region ../../node_modules/.pnpm/@iconify+utils@3.1.7/node_modules/@iconify/utils/lib/icon/merge.js
1930
+ /**
1931
+ * Merge icon and alias
1932
+ *
1933
+ * Can also be used to merge default values and icon
1934
+ */
1935
+ function mergeIconData(parent, child) {
1936
+ const result = mergeIconTransformations(parent, child);
1937
+ for (const key in defaultExtendedIconProps) if (key in defaultIconTransformations) {
1938
+ if (key in parent && !(key in result)) result[key] = defaultIconTransformations[key];
1939
+ } else if (key in child) result[key] = child[key];
1940
+ else if (key in parent) result[key] = parent[key];
1941
+ return result;
1942
+ }
1943
+ //#endregion
1944
+ //#region ../../node_modules/.pnpm/@iconify+utils@3.1.7/node_modules/@iconify/utils/lib/icon-set/tree.js
1945
+ /**
1946
+ * Resolve icon set icons
1947
+ *
1948
+ * Returns parent icon for each icon
1949
+ */
1950
+ function getIconsTree(data, names) {
1951
+ const icons = data.icons;
1952
+ const aliases = data.aliases || Object.create(null);
1953
+ const resolved = Object.create(null);
1954
+ function resolve(name) {
1955
+ if (icons[name]) return resolved[name] = [];
1956
+ if (!(name in resolved)) {
1957
+ resolved[name] = null;
1958
+ const parent = aliases[name] && aliases[name].parent;
1959
+ const value = parent && resolve(parent);
1960
+ if (value) resolved[name] = [parent].concat(value);
1961
+ }
1962
+ return resolved[name];
1963
+ }
1964
+ (names || Object.keys(icons).concat(Object.keys(aliases))).forEach(resolve);
1965
+ return resolved;
1966
+ }
1967
+ //#endregion
1968
+ //#region ../../node_modules/.pnpm/@iconify+utils@3.1.7/node_modules/@iconify/utils/lib/icon-set/get-icon.js
1969
+ /**
1970
+ * Get icon data, using prepared aliases tree
1971
+ */
1972
+ function internalGetIconData(data, name, tree) {
1973
+ const icons = data.icons;
1974
+ const aliases = data.aliases || Object.create(null);
1975
+ let currentProps = {};
1976
+ function parse(name) {
1977
+ currentProps = mergeIconData(icons[name] || aliases[name], currentProps);
1978
+ }
1979
+ parse(name);
1980
+ tree.forEach(parse);
1981
+ return mergeIconData(data, currentProps);
1982
+ }
1983
+ /**
1984
+ * Get data for icon
1985
+ */
1986
+ function getIconData(data, name) {
1987
+ if (data.icons[name]) return internalGetIconData(data, name, []);
1988
+ const tree = getIconsTree(data, [name])[name];
1989
+ return tree ? internalGetIconData(data, name, tree) : null;
1990
+ }
1991
+ //#endregion
1992
+ //#region ../../node_modules/.pnpm/@iconify+utils@3.1.7/node_modules/@iconify/utils/lib/customisations/defaults.js
1993
+ /**
1994
+ * Default icon customisations values
1995
+ */
1996
+ const defaultIconSizeCustomisations = Object.freeze({
1997
+ width: null,
1998
+ height: null
1999
+ });
2000
+ const defaultIconCustomisations = Object.freeze({
2001
+ ...defaultIconSizeCustomisations,
2002
+ ...defaultIconTransformations
2003
+ });
2004
+ //#endregion
2005
+ //#region ../../node_modules/.pnpm/@iconify+utils@3.1.7/node_modules/@iconify/utils/lib/svg/size.js
2006
+ /**
2007
+ * Regular expressions for calculating dimensions
2008
+ */
2009
+ const unitsSplit = /(-?[0-9.]*[0-9]+[0-9.]*)/g;
2010
+ const unitsTest = /^-?[0-9.]*[0-9]+[0-9.]*$/g;
2011
+ function calculateSize(size, ratio, precision) {
2012
+ if (ratio === 1) return size;
2013
+ precision = precision || 100;
2014
+ if (typeof size === "number") return Math.ceil(size * ratio * precision) / precision;
2015
+ if (typeof size !== "string") return size;
2016
+ const oldParts = size.split(unitsSplit);
2017
+ if (oldParts === null || !oldParts.length) return size;
2018
+ const newParts = [];
2019
+ let code = oldParts.shift();
2020
+ let isNumber = unitsTest.test(code);
2021
+ while (true) {
2022
+ if (isNumber) {
2023
+ const num = parseFloat(code);
2024
+ if (isNaN(num)) newParts.push(code);
2025
+ else newParts.push(Math.ceil(num * ratio * precision) / precision);
2026
+ } else newParts.push(code);
2027
+ code = oldParts.shift();
2028
+ if (code === void 0) return newParts.join("");
2029
+ isNumber = !isNumber;
2030
+ }
2031
+ }
2032
+ //#endregion
2033
+ //#region ../../node_modules/.pnpm/@iconify+utils@3.1.7/node_modules/@iconify/utils/lib/svg/defs.js
2034
+ function splitSVGDefs(content, tag = "defs") {
2035
+ let defs = "";
2036
+ const index = content.indexOf("<" + tag);
2037
+ while (index >= 0) {
2038
+ const start = content.indexOf(">", index);
2039
+ const end = content.indexOf("</" + tag);
2040
+ if (start === -1 || end === -1) break;
2041
+ const endEnd = content.indexOf(">", end);
2042
+ if (endEnd === -1) break;
2043
+ defs += content.slice(start + 1, end).trim();
2044
+ content = content.slice(0, index).trim() + content.slice(endEnd + 1);
2045
+ }
2046
+ return {
2047
+ defs,
2048
+ content
2049
+ };
2050
+ }
2051
+ /**
2052
+ * Merge defs and content
2053
+ */
2054
+ function mergeDefsAndContent(defs, content) {
2055
+ return defs ? "<defs>" + defs + "</defs>" + content : content;
2056
+ }
2057
+ /**
2058
+ * Wrap SVG content, without wrapping definitions
2059
+ */
2060
+ function wrapSVGContent(body, start, end) {
2061
+ const split = splitSVGDefs(body);
2062
+ return mergeDefsAndContent(split.defs, start + split.content + end);
2063
+ }
2064
+ //#endregion
2065
+ //#region ../../node_modules/.pnpm/@iconify+utils@3.1.7/node_modules/@iconify/utils/lib/svg/build.js
2066
+ /**
2067
+ * Check if value should be unset. Allows multiple keywords
2068
+ */
2069
+ const isUnsetKeyword = (value) => value === "unset" || value === "undefined" || value === "none";
2070
+ /**
2071
+ * Get SVG attributes and content from icon + customisations
2072
+ *
2073
+ * Does not generate style to make it compatible with frameworks that use objects for style, such as React.
2074
+ * Instead, it generates 'inline' value. If true, rendering engine should add verticalAlign: -0.125em to icon.
2075
+ *
2076
+ * Customisations should be normalised by platform specific parser.
2077
+ * Result should be converted to <svg> by platform specific parser.
2078
+ * Use replaceIDs to generate unique IDs for body.
2079
+ */
2080
+ function iconToSVG(icon, customisations) {
2081
+ const fullIcon = {
2082
+ ...defaultIconProps,
2083
+ ...icon
2084
+ };
2085
+ const fullCustomisations = {
2086
+ ...defaultIconCustomisations,
2087
+ ...customisations
2088
+ };
2089
+ const box = {
2090
+ left: fullIcon.left,
2091
+ top: fullIcon.top,
2092
+ width: fullIcon.width,
2093
+ height: fullIcon.height
2094
+ };
2095
+ let body = fullIcon.body;
2096
+ [fullIcon, fullCustomisations].forEach((props) => {
2097
+ const transformations = [];
2098
+ const hFlip = props.hFlip;
2099
+ const vFlip = props.vFlip;
2100
+ let rotation = props.rotate;
2101
+ if (hFlip) {
2102
+ if (vFlip) rotation += 2;
2103
+ else {
2104
+ transformations.push("translate(" + (box.width + box.left).toString() + " " + (0 - box.top).toString() + ")");
2105
+ transformations.push("scale(-1 1)");
2106
+ box.top = box.left = 0;
2107
+ }
2108
+ } else if (vFlip) {
2109
+ transformations.push("translate(" + (0 - box.left).toString() + " " + (box.height + box.top).toString() + ")");
2110
+ transformations.push("scale(1 -1)");
2111
+ box.top = box.left = 0;
2112
+ }
2113
+ let tempValue;
2114
+ if (rotation < 0) rotation -= Math.floor(rotation / 4) * 4;
2115
+ rotation = rotation % 4;
2116
+ switch (rotation) {
2117
+ case 1:
2118
+ tempValue = box.height / 2 + box.top;
2119
+ transformations.unshift("rotate(90 " + tempValue.toString() + " " + tempValue.toString() + ")");
2120
+ break;
2121
+ case 2:
2122
+ transformations.unshift("rotate(180 " + (box.width / 2 + box.left).toString() + " " + (box.height / 2 + box.top).toString() + ")");
2123
+ break;
2124
+ case 3:
2125
+ tempValue = box.width / 2 + box.left;
2126
+ transformations.unshift("rotate(-90 " + tempValue.toString() + " " + tempValue.toString() + ")");
2127
+ }
2128
+ if (rotation % 2 === 1) {
2129
+ if (box.left !== box.top) {
2130
+ tempValue = box.left;
2131
+ box.left = box.top;
2132
+ box.top = tempValue;
2133
+ }
2134
+ if (box.width !== box.height) {
2135
+ tempValue = box.width;
2136
+ box.width = box.height;
2137
+ box.height = tempValue;
2138
+ }
2139
+ }
2140
+ if (transformations.length) body = wrapSVGContent(body, "<g transform=\"" + transformations.join(" ") + "\">", "</g>");
2141
+ });
2142
+ const customisationsWidth = fullCustomisations.width;
2143
+ const customisationsHeight = fullCustomisations.height;
2144
+ const boxWidth = box.width;
2145
+ const boxHeight = box.height;
2146
+ let width;
2147
+ let height;
2148
+ if (customisationsWidth === null) {
2149
+ height = customisationsHeight === null ? "1em" : customisationsHeight === "auto" ? boxHeight : customisationsHeight;
2150
+ width = calculateSize(height, boxWidth / boxHeight);
2151
+ } else {
2152
+ width = customisationsWidth === "auto" ? boxWidth : customisationsWidth;
2153
+ height = customisationsHeight === null ? calculateSize(width, boxHeight / boxWidth) : customisationsHeight === "auto" ? boxHeight : customisationsHeight;
2154
+ }
2155
+ const attributes = {};
2156
+ const setAttr = (prop, value) => {
2157
+ if (!isUnsetKeyword(value)) attributes[prop] = value.toString();
2158
+ };
2159
+ setAttr("width", width);
2160
+ setAttr("height", height);
2161
+ const viewBox = [
2162
+ box.left,
2163
+ box.top,
2164
+ boxWidth,
2165
+ boxHeight
2166
+ ];
2167
+ attributes.viewBox = viewBox.join(" ");
2168
+ return {
2169
+ attributes,
2170
+ viewBox,
2171
+ body
2172
+ };
2173
+ }
2174
+ //#endregion
2175
+ //#region src/vite/suggest.ts
2176
+ /**
2177
+ * "Did you mean": the closest names by edit distance, as vicss and vi18n
2178
+ * suggest theirs. A set holds a few thousand names, which this scans in
2179
+ * well under a millisecond.
2180
+ */
2181
+ /** Up to three names within a third of `name`'s length (at least two edits). */
2182
+ function closest(name, names) {
2183
+ const limit = Math.max(2, Math.floor(name.length / 3));
2184
+ const scored = [];
2185
+ for (const candidate of names) {
2186
+ if (Math.abs(candidate.length - name.length) > limit) continue;
2187
+ const d = distance(name, candidate, limit);
2188
+ if (d <= limit) scored.push([d, candidate]);
2189
+ }
2190
+ scored.sort((a, b) => a[0] - b[0] || a[1].localeCompare(b[1]));
2191
+ return scored.slice(0, 3).map(([, candidate]) => candidate);
2192
+ }
2193
+ /** Levenshtein distance, stopping once every path exceeds `limit`. */
2194
+ function distance(a, b, limit) {
2195
+ let previous = Array.from({ length: b.length + 1 }, (_, i) => i);
2196
+ for (let i = 1; i <= a.length; i++) {
2197
+ const row = [i];
2198
+ let best = i;
2199
+ for (let j = 1; j <= b.length; j++) {
2200
+ const cost = a[i - 1] === b[j - 1] ? 0 : 1;
2201
+ const value = Math.min(previous[j] + 1, row[j - 1] + 1, previous[j - 1] + cost);
2202
+ row.push(value);
2203
+ if (value < best) best = value;
2204
+ }
2205
+ if (best > limit) return limit + 1;
2206
+ previous = row;
2207
+ }
2208
+ return previous[b.length];
2209
+ }
2210
+ //#endregion
2211
+ //#region src/vite/svg.ts
2212
+ /** The whole `<svg>` element: what a data URL holds and what og inlines. */
2213
+ function svgElement(icon) {
2214
+ const { width, height, body } = icon;
2215
+ return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${width} ${height}" width="${width}" height="${height}">${body}</svg>`;
2216
+ }
2217
+ const BLACK = /^(?:black|#000|#000000|#000f|#000000ff|rgb\(0,\s*0,\s*0\))$/i;
2218
+ const NO_PAINT = /^(?:none|transparent|currentcolor|inherit|unset|initial|context-fill|context-stroke)$/i;
2219
+ const PAINT_ATTRIBUTE = /\b(?:fill|stroke|stop-color|flood-color|lighting-color|color)\s*[=:]\s*["']?([^"';)>\s]+(?:\([^)]*\))?)/gi;
2220
+ /**
2221
+ * Whether `body` paints in one colour: only `currentColor`, black (the
2222
+ * default fill, and what Figma exports hard-code) or no paint. A gradient
2223
+ * or a `url(#…)` paint counts as a colour.
2224
+ */
2225
+ function isMonochrome(body) {
2226
+ for (const match of body.matchAll(PAINT_ATTRIBUTE)) {
2227
+ const value = match[1];
2228
+ if (!NO_PAINT.test(value) && !BLACK.test(value)) return false;
2229
+ }
2230
+ return !/<(?:linear|radial)Gradient\b|<pattern\b|<image\b/i.test(body);
2231
+ }
2232
+ /** Black paints become `currentColor`, so an inlined monochrome icon follows `color` like the mask does. */
2233
+ function paintCurrentColor(body) {
2234
+ return body.replace(PAINT_ATTRIBUTE, (all, value) => BLACK.test(value) ? all.replace(value, "currentColor") : all);
2235
+ }
2236
+ /**
2237
+ * A local SVG file as an icon. The clean-up removes what a CSS image never
2238
+ * uses and what would be active content inlined (D13); it is not an
2239
+ * optimiser. Throws a message for a file that is not an SVG or has no size.
2240
+ */
2241
+ function parseSvg(source) {
2242
+ const text = source.replace(/<\?xml[\s\S]*?\?>/gi, "").replace(/<!DOCTYPE[\s\S]*?>/gi, "").replace(/<!--[\s\S]*?-->/g, "").replace(/<(script|metadata|foreignObject|title|desc)\b[\s\S]*?<\/\1\s*>/gi, "").replace(/<(script|metadata|foreignObject)\b[^>]*\/>/gi, "").replace(/\s+on[a-z]+\s*=\s*(?:"[^"]*"|'[^']*'|[^\s>]+)/gi, "").replace(/\s+(?:xlink:)?href\s*=\s*(?:"(?!#)[^"]*"|'(?!#)[^']*')/gi, "");
2243
+ const open = /<svg\b([^>]*)>/i.exec(text);
2244
+ const close = text.lastIndexOf("</svg>");
2245
+ if (!open || close < open.index) throw new Error("is not an <svg> element");
2246
+ const attributes = open[1];
2247
+ const body = text.slice(open.index + open[0].length, close).trim();
2248
+ const viewBox = /\bviewBox\s*=\s*["']([^"']+)["']/i.exec(attributes)?.[1];
2249
+ let width;
2250
+ let height;
2251
+ if (viewBox) {
2252
+ const box = viewBox.trim().split(/[\s,]+/).map(Number);
2253
+ if (box.length !== 4 || box.some((n) => !Number.isFinite(n))) throw new Error(`has a viewBox "${viewBox}" that is not four numbers`);
2254
+ const [x, y] = box;
2255
+ width = box[2];
2256
+ height = box[3];
2257
+ return finish(x !== 0 || y !== 0 ? `<g transform="translate(${-x} ${-y})">${body}</g>` : body, width, height);
2258
+ }
2259
+ width = Number(/\bwidth\s*=\s*["']?([\d.]+)/i.exec(attributes)?.[1]);
2260
+ height = Number(/\bheight\s*=\s*["']?([\d.]+)/i.exec(attributes)?.[1]);
2261
+ if (!(width > 0 && height > 0)) throw new Error("has no viewBox and no width and height");
2262
+ return finish(body, width, height);
2263
+ function finish(inner, w, h) {
2264
+ const paint = [...attributes.matchAll(/\s(fill|stroke|stroke-width|stroke-linecap|stroke-linejoin)\s*=\s*("[^"]*"|'[^']*')/gi)].map((m) => ` ${m[1]}=${m[2]}`).join("");
2265
+ const wrapped = paint ? `<g${paint}>${inner}</g>` : inner;
2266
+ const mono = isMonochrome(wrapped);
2267
+ return {
2268
+ body: mono ? paintCurrentColor(wrapped) : wrapped,
2269
+ width: w,
2270
+ height: h,
2271
+ mono
2272
+ };
2273
+ }
2274
+ }
2275
+ //#endregion
2276
+ //#region src/vite/resolve.ts
2277
+ /**
2278
+ * Names to SVGs (PLAN §4): the `@iconify-json/*` sets the root
2279
+ * `package.json` lists (D9) and the app's folders. A set is parsed on first
2280
+ * use and kept for the process; a folder file is read on each resolve, so a
2281
+ * changed SVG is picked up when the plugin asks again.
2282
+ */
2283
+ /** A name that cannot be resolved; the message names the fix. */
2284
+ var IconError = class extends Error {
2285
+ name = "IconError";
2286
+ };
2287
+ /** Iconify's id grammar: lowercase words joined by single dashes. */
2288
+ const PART = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
2289
+ const PACKAGE = "@iconify-json/";
2290
+ /** Parsed sets by file, for the process: a dev server restart or a second build reuses them. */
2291
+ const parsed = /* @__PURE__ */ new Map();
2292
+ /** The icons one project can name. */
2293
+ var IconSource = class {
2294
+ root;
2295
+ /** Installed set prefixes, from `package.json`. */
2296
+ sets;
2297
+ /** Folder prefixes to absolute directories. */
2298
+ folders;
2299
+ #require;
2300
+ #built = /* @__PURE__ */ new Map();
2301
+ constructor(options) {
2302
+ this.root = options.root;
2303
+ this.#require = createRequire(join(options.root, "package.json"));
2304
+ this.sets = installedSets(options.root);
2305
+ const folders = /* @__PURE__ */ new Map();
2306
+ for (const [prefix, dir] of Object.entries(options.folders ?? {})) {
2307
+ if (!PART.test(prefix)) throw new IconError(`folders: "${prefix}" is not a set name: use lowercase words joined by dashes, like "brand"`);
2308
+ if (this.sets.includes(prefix)) throw new IconError(`folders: "${prefix}" is also the installed ${PACKAGE}${prefix}: give the folder another name`);
2309
+ const abs = resolve(options.root, dir);
2310
+ if (!existsSync(abs) || !statSync(abs).isDirectory()) throw new IconError(`folders: "${prefix}" points to ${dir}, which is not a directory`);
2311
+ folders.set(prefix, abs);
2312
+ }
2313
+ this.folders = folders;
2314
+ }
2315
+ /** Every name, sorted per set: the `IconName` union (D10). */
2316
+ names(skipped = []) {
2317
+ const out = [];
2318
+ for (const prefix of this.sets) for (const name of this.#set(prefix).names) out.push(`${prefix}:${name}`);
2319
+ for (const [prefix, dir] of this.folders) for (const name of folderNames(dir, skipped)) out.push(`${prefix}:${name}`);
2320
+ return out;
2321
+ }
2322
+ /** `prefix:name` to its SVG; throws an `IconError` naming the closest names. */
2323
+ resolve(id) {
2324
+ const colon = id.indexOf(":");
2325
+ const prefix = id.slice(0, colon);
2326
+ const name = id.slice(colon + 1);
2327
+ if (colon < 1 || !PART.test(prefix) || !PART.test(name)) throw new IconError(`"${id}" is not an icon name: write "set:name" in lowercase, like "lucide:check"`);
2328
+ const dir = this.folders.get(prefix);
2329
+ if (dir) return this.#fromFolder(id, prefix, name, dir);
2330
+ if (this.sets.includes(prefix)) return this.#fromSet(id, prefix, name);
2331
+ const known = [...this.sets, ...this.folders.keys()];
2332
+ throw new IconError(`no icon set "${prefix}" for "${id}". ${known.length ? `Installed: ${this.sets.join(", ") || "none"}; folders: ${[...this.folders.keys()].join(", ") || "none"}.` : "No set is installed and no folder is listed."}${hint(prefix, known)} To add it: vp add -D ${PACKAGE}${prefix}`);
2333
+ }
2334
+ #set(prefix) {
2335
+ const file = this.#require.resolve(`${PACKAGE}${prefix}/icons.json`);
2336
+ let set = parsed.get(file);
2337
+ if (!set) {
2338
+ const json = JSON.parse(readFileSync(file, "utf8"));
2339
+ set = {
2340
+ json,
2341
+ file,
2342
+ names: [...Object.keys(json.icons), ...Object.keys(json.aliases ?? {})].sort(),
2343
+ palette: palette(file.slice(0, -10))
2344
+ };
2345
+ parsed.set(file, set);
2346
+ }
2347
+ return set;
2348
+ }
2349
+ #fromSet(id, prefix, name) {
2350
+ let icon = this.#built.get(id);
2351
+ if (!icon) this.#built.set(id, icon = this.#buildFromSet(id, prefix, name));
2352
+ return icon;
2353
+ }
2354
+ #buildFromSet(id, prefix, name) {
2355
+ const set = this.#set(prefix);
2356
+ const data = getIconData(set.json, name);
2357
+ if (!data) throw new IconError(`icon "${id}" is not in ${PACKAGE}${prefix}.${hint(name, set.names, prefix)}`);
2358
+ const built = iconToSVG(data, { height: "auto" });
2359
+ const [x, y, width, height] = built.viewBox;
2360
+ const body = x || y ? `<g transform="translate(${-x} ${-y})">${built.body}</g>` : built.body;
2361
+ const mono = set.palette === void 0 ? isMonochrome(body) : !set.palette;
2362
+ return {
2363
+ name: id,
2364
+ file: set.file,
2365
+ body: mono ? paintCurrentColor(body) : body,
2366
+ width,
2367
+ height,
2368
+ mono
2369
+ };
2370
+ }
2371
+ #fromFolder(id, prefix, name, dir) {
2372
+ const file = folderFile(dir, name);
2373
+ if (!file) throw new IconError(`icon "${id}" has no file in ${relative(this.root, dir) || "."}.` + hint(name, folderNames(dir), prefix));
2374
+ try {
2375
+ return {
2376
+ name: id,
2377
+ file,
2378
+ ...parseSvg(readFileSync(file, "utf8"))
2379
+ };
2380
+ } catch (error) {
2381
+ throw new IconError(`${relative(this.root, file)} ${error.message}`);
2382
+ }
2383
+ }
2384
+ };
2385
+ /** A set's `info.json` palette; the packages ship it beside `icons.json`, which lacks `info`. */
2386
+ function palette(dir) {
2387
+ try {
2388
+ const info = JSON.parse(readFileSync(join(dir, "info.json"), "utf8"));
2389
+ return typeof info.palette === "boolean" ? info.palette : void 0;
2390
+ } catch {
2391
+ return;
2392
+ }
2393
+ }
2394
+ /** ` Did you mean "lucide:check"?`, or nothing. */
2395
+ function hint(name, names, prefix) {
2396
+ const found = closest(name, names);
2397
+ if (!found.length) return "";
2398
+ return ` Did you mean ${found.map((n) => `"${prefix ? `${prefix}:` : ""}${n}"`).join(", ")}?`;
2399
+ }
2400
+ /** The set prefixes of the `@iconify-json/*` packages `root/package.json` depends on. */
2401
+ function installedSets(root) {
2402
+ let pkg;
2403
+ try {
2404
+ pkg = JSON.parse(readFileSync(join(root, "package.json"), "utf8"));
2405
+ } catch {
2406
+ return [];
2407
+ }
2408
+ return [...Object.keys(pkg.dependencies ?? {}), ...Object.keys(pkg.devDependencies ?? {})].filter((name) => name.startsWith(PACKAGE)).map((name) => name.slice(14)).sort();
2409
+ }
2410
+ /** A folder's icon names: `arrows/left.svg` is `arrows-left` (D4). */
2411
+ function folderNames(dir, skipped = [], base = "") {
2412
+ const out = [];
2413
+ for (const entry of readdirSync(dir, { withFileTypes: true })) if (entry.isDirectory()) out.push(...folderNames(join(dir, entry.name), skipped, `${base}${entry.name}-`));
2414
+ else if (entry.name.endsWith(".svg")) {
2415
+ const name = base + entry.name.slice(0, -4);
2416
+ (PART.test(name) ? out : skipped).push(name);
2417
+ }
2418
+ return out.sort();
2419
+ }
2420
+ /** The file for `name` in `dir`, trying each dash as a folder separator. */
2421
+ function folderFile(dir, name) {
2422
+ const direct = join(dir, `${name}.svg`);
2423
+ if (existsSync(direct)) return direct;
2424
+ const dash = name.indexOf("-");
2425
+ for (let i = dash; i > 0; i = name.indexOf("-", i + 1)) {
2426
+ const sub = join(dir, name.slice(0, i));
2427
+ if (existsSync(sub) && statSync(sub).isDirectory()) {
2428
+ const found = folderFile(sub, name.slice(i + 1));
2429
+ if (found) return found;
2430
+ }
2431
+ }
2432
+ }
2433
+ //#endregion
2434
+ //#region src/vite/types.ts
2435
+ /**
2436
+ * The generated `icons.d.ts` (D10): the names and the framework, registered
2437
+ * on `@menapo/icons`'s `Register` the way vicss registers its tokens.
2438
+ */
2439
+ /** `src/icons.d.ts`, else `app/icons.d.ts`, else the root's: where a tsconfig's `include` looks. */
2440
+ function typesFile(root) {
2441
+ const dir = ["src", "app"].map((name) => join(root, name)).find((d) => existsSync(d));
2442
+ return join(dir ?? root, "icons.d.ts");
2443
+ }
2444
+ function typesText(names, framework) {
2445
+ const union = names.length ? names.map((n) => `\n | ${JSON.stringify(n)}`).join("") : " never";
2446
+ return `// Generated by @menapo/icons/vite from the installed sets and folders. Commit it; do not edit.
2447
+ import "@menapo/icons";
2448
+
2449
+ declare module "@menapo/icons" {
2450
+ interface Register {
2451
+ framework: ${JSON.stringify(framework)};\n names:${union};\n }
2452
+ }
2453
+ `;
2454
+ }
2455
+ /** Writes unless unchanged, so a type checker or watcher sees no edit for nothing. */
2456
+ function writeIfChanged(file, text) {
2457
+ try {
2458
+ if (readFileSync(file, "utf8") === text) return false;
2459
+ } catch {}
2460
+ mkdirSync(dirname(file), { recursive: true });
2461
+ writeFileSync(file, text);
2462
+ return true;
2463
+ }
2464
+ //#endregion
2465
+ //#region src/vite/index.ts
2466
+ /**
2467
+ * `@menapo/icons/vite`: `plugins: [icons()]` (PLAN §0). It compiles every
2468
+ * `icon()` call to a literal, serves each icon's CSS as a virtual module the
2469
+ * calling module imports, and writes `icons.d.ts`. `resolveIcon` and
2470
+ * `iconName` are the build-side door og's renderer uses (D11). The only
2471
+ * entry that imports from the build side.
2472
+ */
2473
+ const RESOLVED = `\0${VIRTUAL}`;
2474
+ const SCRIPT = /\.(?:[cm]?[jt]sx?|vue|svelte|astro)(?:[?#]|$)/;
2475
+ const OWN = posix(fileURLToPath(new URL(import.meta.url.endsWith(".ts") ? "../" : "./", import.meta.url)));
2476
+ /** `plugins: [icons()]` in a Vite config. */
2477
+ function icons(options = {}) {
2478
+ let config;
2479
+ let source;
2480
+ let settings;
2481
+ let layer = "base";
2482
+ /** Folder files to the virtual ids built from them, for dev updates. */
2483
+ const built = /* @__PURE__ */ new Map();
2484
+ function writeTypes() {
2485
+ const skipped = [];
2486
+ const names = source.names(skipped);
2487
+ for (const name of skipped) config.logger.warn(`[icons] ${name}.svg is skipped: name icon files in lowercase words joined by dashes`);
2488
+ const framework = rootFramework(config.root) ?? "vanilla";
2489
+ writeIfChanged(typesFile(config.root), typesText(names, framework));
2490
+ }
2491
+ return {
2492
+ name: "icons",
2493
+ api: { folders: options.folders },
2494
+ enforce: "post",
2495
+ configResolved(resolved) {
2496
+ config = resolved;
2497
+ source = new IconSource({
2498
+ root: resolved.root,
2499
+ folders: options.folders
2500
+ });
2501
+ settings = {
2502
+ scripts: rootFramework(resolved.root) ?? "vanilla",
2503
+ jsx: jsxFrameworkOf(resolved, resolved.root)
2504
+ };
2505
+ if (resolved.plugins.some((plugin) => plugin.name === "vicss")) layer = "vicss.global";
2506
+ writeTypes();
2507
+ },
2508
+ configureServer(server) {
2509
+ const dirs = [...source.folders.values()];
2510
+ if (!dirs.length) return;
2511
+ server.watcher.add(dirs);
2512
+ const changed = (file) => {
2513
+ if (file.endsWith(".svg") && dirs.some((dir) => file.startsWith(dir + sep))) writeTypes();
2514
+ };
2515
+ server.watcher.on("add", changed);
2516
+ server.watcher.on("unlink", changed);
2517
+ },
2518
+ hotUpdate({ file, modules }) {
2519
+ const ids = built.get(file);
2520
+ if (!ids) return;
2521
+ const updated = [...ids].flatMap((id) => {
2522
+ const module = this.environment.moduleGraph.getModuleById(id);
2523
+ if (!module) return [];
2524
+ this.environment.moduleGraph.invalidateModule(module);
2525
+ return [module];
2526
+ });
2527
+ return [...modules, ...updated];
2528
+ },
2529
+ resolveId: {
2530
+ filter: { id: new RegExp(`^${VIRTUAL}`) },
2531
+ handler: (id) => `\0${id}`
2532
+ },
2533
+ load: {
2534
+ filter: { id: new RegExp(`^${RESOLVED.replace("\0", "\\0")}`) },
2535
+ handler(id) {
2536
+ const file = id.slice(RESOLVED.length, -4);
2537
+ if (file === "base") return baseCss(layer);
2538
+ const name = file.replace("--", ":");
2539
+ let icon;
2540
+ try {
2541
+ icon = source.resolve(name);
2542
+ } catch (error) {
2543
+ if (error instanceof IconError) this.error(error.message);
2544
+ throw error;
2545
+ }
2546
+ if (source.folders.has(name.slice(0, name.indexOf(":")))) {
2547
+ this.addWatchFile(icon.file);
2548
+ let ids = built.get(icon.file);
2549
+ if (!ids) built.set(icon.file, ids = /* @__PURE__ */ new Set());
2550
+ ids.add(id);
2551
+ }
2552
+ return iconCss(name, icon, layer);
2553
+ }
2554
+ },
2555
+ transform: {
2556
+ filter: {
2557
+ id: {
2558
+ include: SCRIPT,
2559
+ exclude: /^\0/
2560
+ },
2561
+ code: PACKAGE$1
2562
+ },
2563
+ handler(code, id) {
2564
+ if (within([OWN], id)) return null;
2565
+ const framework = /\.astro(?:[?#]|$)/.test(id) ? "astro" : frameworkOf(id, code, settings);
2566
+ try {
2567
+ const out = compile(code, id, {
2568
+ classAttribute: framework === "react" ? "className" : "class",
2569
+ check: (name, start) => {
2570
+ try {
2571
+ source.resolve(name);
2572
+ } catch (error) {
2573
+ if (error instanceof IconError) throw new CompileError(error.message, start);
2574
+ throw error;
2575
+ }
2576
+ }
2577
+ });
2578
+ return out && {
2579
+ code: out.code,
2580
+ map: out.map
2581
+ };
2582
+ } catch (error) {
2583
+ if (error instanceof CompileError) {
2584
+ const file = posix(relative(config.root, id.replace(/[?#].*$/, "")));
2585
+ this.error({
2586
+ message: `${file}: ${error.message}`,
2587
+ pos: error.start
2588
+ });
2589
+ }
2590
+ throw error;
2591
+ }
2592
+ }
2593
+ }
2594
+ };
2595
+ }
2596
+ const sources = /* @__PURE__ */ new Map();
2597
+ /**
2598
+ * `lucide:check` to its SVG, from the sets and folders of the project at
2599
+ * `root`, as the plugin resolves it. Throws a message naming the fix for an
2600
+ * unknown name. Build side only: og calls it while it renders.
2601
+ */
2602
+ function resolveIcon(name, options) {
2603
+ const key = JSON.stringify([options.root, options.folders ?? {}]);
2604
+ let icons = sources.get(key);
2605
+ if (!icons) sources.set(key, icons = new IconSource(options));
2606
+ const icon = icons.resolve(name);
2607
+ const svg = svgElement(icon);
2608
+ return {
2609
+ ...icon,
2610
+ svg: icon.mono ? svg.replace("<svg ", "<svg fill=\"currentColor\" ") : svg
2611
+ };
2612
+ }
2613
+ /**
2614
+ * The name an `icon()` result stands for, read back from its classes:
2615
+ * `iconName({ class: "mi mi-lucide--x" })` is `"lucide:x"`. A spread in a
2616
+ * markup template is just attributes; this is how a renderer knows it is
2617
+ * an icon. Takes `class` or `className` (D3).
2618
+ */
2619
+ function iconName(attributes) {
2620
+ const classes = attributes.class ?? attributes.className;
2621
+ return typeof classes === "string" ? nameOfClass(classes) : void 0;
2622
+ }
2623
+ //#endregion
2624
+ export { iconName, icons, resolveIcon };