@weasel-js/icons-plugin 0.0.0-stage → 1.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 orochi235
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,46 @@
1
- # Temporary Holding Version
1
+ # @weasel-js/icons-plugin
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ `weaselIcons`, the build plugin that ships only the glyphs a build names. It runs at build time, in
4
+ Node, and installs `oxc-parser`, `unplugin` and `magic-string`; the app itself never imports it.
5
+ Icon names and the registry are in `@weasel-js/icons`.
6
+
7
+ | Export | What it is |
8
+ |---|---|
9
+ | `weaselIcons` | The plugin: `weaselIcons.vite(…)`, `.rollup(…)`, `.rolldown(…)` or `.esbuild(…)` |
10
+ | `@weasel-js/icons-plugin/virtual` | Types for `virtual:weasel-icons` and its variants |
11
+
12
+ ## In an app
13
+
14
+ ```sh
15
+ npm install --save-dev @weasel-js/icons-plugin
16
+ ```
17
+
18
+ ```ts
19
+ // vite.config.ts
20
+ import { weaselIcons } from '@weasel-js/icons-plugin';
21
+
22
+ export default defineConfig({ plugins: [weaselIcons.vite({ mode: 'app' })] });
23
+ ```
24
+
25
+ ```tsx
26
+ /// <reference types="@weasel-js/icons-plugin/virtual" />
27
+ import { IconRegistryProvider } from '@weasel-js/core';
28
+ import icons from 'virtual:weasel-icons';
29
+
30
+ const VARIANTS = { all: () => import('virtual:weasel-icons/all') };
31
+
32
+ <IconRegistryProvider icons={icons} variants={VARIANTS}>…</IconRegistryProvider>;
33
+ ```
34
+
35
+ `virtual:weasel-icons` holds the glyphs the build names, in your code and in the weasel packages
36
+ it imports. `/all`, `/<namespace>`, and custom variants (`variants: { name: { namespaces, groups,
37
+ tags } }` in the plugin options) each load as their own chunk. A name the build cannot resolve
38
+ fails it.
39
+
40
+ App mode runs under vite, rollup or rolldown. Library mode, which only rewrites `icon()` calls,
41
+ also runs under esbuild. Any other bundler is refused with an error: when the plugin is created, or
42
+ under webpack and rspack when the compiler applies it.
43
+
44
+ To write icon names in app code, put `export const icon = scopedIcon<never>('my-app');` in a
45
+ module named `icons.gen.ts` and import `icon` from it: `icon('ui:close')`. The plugin sees only
46
+ calls to an `icon` imported from such a module.
@@ -0,0 +1,34 @@
1
+ import { UnpluginInstance } from 'unplugin';
2
+
3
+ /** Which glyphs a custom variant holds. Each listed field narrows; a glyph needs one of the listed tags. */
4
+ interface VariantFilter {
5
+ namespaces?: string[];
6
+ groups?: string[];
7
+ tags?: string[];
8
+ }
9
+
10
+ /**
11
+ * Every qualified ref the module names as a string literal led by an `@icon` block comment.
12
+ * A module that does not parse falls back to a plain scan, which can over-count but never drops one.
13
+ */
14
+ declare function collectIconRefs(code: string, id?: string): string[];
15
+
16
+ /** How {@link weaselIcons} treats the build it runs in. */
17
+ interface WeaselIconsOptions {
18
+ /**
19
+ * `library` only rewrites `icon()` calls, under vite, rollup, rolldown or esbuild. `app` also emits
20
+ * `virtual:weasel-icons` and its variants, and needs vite, rollup or rolldown: the others have no
21
+ * hook to fill them in once every module is seen.
22
+ */
23
+ mode: 'library' | 'app';
24
+ /** Extra variants, each loadable as `virtual:weasel-icons/<name>`. */
25
+ variants?: Record<string, VariantFilter>;
26
+ }
27
+ /**
28
+ * Rewrites each `icon('x')` imported from a generated `icons.gen` into an annotated, qualified
29
+ * literal. In `app` mode it also emits `virtual:weasel-icons`, holding only the glyphs the build
30
+ * names, plus `/all`, `/<namespace>` and each custom variant, every one its own chunk.
31
+ */
32
+ declare const weaselIcons: UnpluginInstance<WeaselIconsOptions, false>;
33
+
34
+ export { type VariantFilter, type WeaselIconsOptions, collectIconRefs, weaselIcons };
package/dist/index.js ADDED
@@ -0,0 +1,424 @@
1
+ import MagicString from 'magic-string';
2
+ import { createUnplugin } from 'unplugin';
3
+ import { Visitor, parseSync } from 'oxc-parser';
4
+ import { existsSync, readdirSync, lstatSync, readFileSync, realpathSync } from 'fs';
5
+ import { join, dirname, parse, resolve } from 'path';
6
+
7
+ // src/index.ts
8
+ function langOf(id) {
9
+ const m = /\.[cm]?([jt])s(x?)$/.exec(id);
10
+ if (!m) return "js";
11
+ return `${m[1]}s${m[2]}`;
12
+ }
13
+ function parseModule(code, id) {
14
+ const result = parseSync(id, code, { lang: langOf(id), sourceType: "module" });
15
+ return result.errors.length > 0 ? { error: result.errors[0].message } : result;
16
+ }
17
+
18
+ // src/collect.ts
19
+ var ANNOTATED = /\/\*\s*@icon\s*\*\/\s*(['"])([^'"]+)\1/g;
20
+ var ANNOTATION = /^\s*@icon\s*$/;
21
+ function stringLiterals(parsed) {
22
+ const literals = /* @__PURE__ */ new Map();
23
+ new Visitor({
24
+ Literal(node) {
25
+ if (typeof node.value === "string") literals.set(node.start, node.value);
26
+ },
27
+ TemplateLiteral(node) {
28
+ const cooked = node.expressions.length === 0 ? node.quasis[0]?.value.cooked : void 0;
29
+ if (typeof cooked === "string") literals.set(node.start, cooked);
30
+ }
31
+ }).visit(parsed.program);
32
+ return literals;
33
+ }
34
+ function annotatedLiterals(parsed, code, literals = stringLiterals(parsed)) {
35
+ const out = /* @__PURE__ */ new Map();
36
+ for (const c of parsed.comments) {
37
+ if (c.type !== "Block" || !ANNOTATION.test(c.value)) continue;
38
+ let at = c.end;
39
+ while (at < code.length && /\s/.test(code[at])) at++;
40
+ const ref = literals.get(at);
41
+ if (ref !== void 0) out.set(at, ref);
42
+ }
43
+ return out;
44
+ }
45
+ function collectIconRefs(code, id = "module.js") {
46
+ if (!code.includes("@icon")) return [];
47
+ const parsed = parseModule(code, id);
48
+ if ("error" in parsed) return [...code.matchAll(ANNOTATED)].map((m) => m[2]);
49
+ return [...annotatedLiterals(parsed, code).values()];
50
+ }
51
+
52
+ // src/annotate.ts
53
+ function unannotated(code, id, refs) {
54
+ if (![...refs].some((r) => code.includes(r))) return [];
55
+ const parsed = parseModule(code, id);
56
+ if ("error" in parsed) throw new Error(`${id}: cannot check its @icon annotations, the chunk did not parse: ${parsed.error}`);
57
+ const literals = stringLiterals(parsed);
58
+ const done = annotatedLiterals(parsed, code, literals);
59
+ return [...literals].filter(([start, value]) => refs.has(value) && !done.has(start));
60
+ }
61
+ function annotateRefs(code, id, refs) {
62
+ const bare = unannotated(code, id, refs);
63
+ if (bare.length === 0) return null;
64
+ const s = new MagicString(code);
65
+ for (const [start] of bare) s.prependLeft(start, "/* @icon */ ");
66
+ return { code: s.toString(), map: s.generateMap({ hires: true }).toString() };
67
+ }
68
+ function libraryAnnotations() {
69
+ const moduleRefs = /* @__PURE__ */ new Map();
70
+ const all = () => new Set([...moduleRefs.values()].flat());
71
+ return {
72
+ record(id, refs) {
73
+ if (refs.length > 0) moduleRefs.set(id, refs);
74
+ else moduleRefs.delete(id);
75
+ },
76
+ /** Drop the modules a rebuild no longer holds. */
77
+ keep(ids) {
78
+ for (const id of moduleRefs.keys()) if (!ids.has(id)) moduleRefs.delete(id);
79
+ },
80
+ renderChunk(code, chunk) {
81
+ const named2 = all();
82
+ return named2.size > 0 ? annotateRefs(code, chunk.fileName, named2) : null;
83
+ },
84
+ /** Why the bundle is wrong, when a chunk holds a recorded ref with its annotation stripped. */
85
+ stripped(bundle) {
86
+ const named2 = all();
87
+ if (named2.size === 0) return void 0;
88
+ const lost = /* @__PURE__ */ new Set();
89
+ for (const [file, c] of Object.entries(bundle)) {
90
+ if (c.type === "chunk" && c.code) for (const [, ref] of unannotated(c.code, file, named2)) lost.add(ref);
91
+ }
92
+ if (lost.size === 0) return void 0;
93
+ return `the library build stripped the @icon annotation from ${[...lost].join(", ")}; set both build.minify and the bundler output's minify to false`;
94
+ }
95
+ };
96
+ }
97
+
98
+ // src/bundlers.ts
99
+ var BUNDLERS = {
100
+ app: ["vite", "rollup", "rolldown"],
101
+ library: ["vite", "rollup", "rolldown", "esbuild"]
102
+ };
103
+ function assertBundler(mode, framework) {
104
+ const allowed = BUNDLERS[mode];
105
+ if (!allowed) throw new Error(`weaselIcons: mode must be 'library' or 'app', not ${JSON.stringify(mode)}`);
106
+ if (allowed.includes(framework)) return;
107
+ const why = mode === "app" ? "; its virtual modules would ship as unfilled placeholders" : "";
108
+ throw new Error(`weaselIcons: ${mode} mode runs under ${allowed.join(", ")}, not ${framework}${why}`);
109
+ }
110
+
111
+ // ../icons/src/names.ts
112
+ var QUALIFIED = /^([^:\s]+):([^:\s]+)$/;
113
+ function qualify(namespace, name) {
114
+ return name.includes(":") ? name : `${namespace}:${name}`;
115
+ }
116
+ function splitIconRef(ref) {
117
+ const m = QUALIFIED.exec(ref);
118
+ return m ? { namespace: m[1], name: m[2] } : void 0;
119
+ }
120
+ var read = (file) => JSON.parse(readFileSync(file, "utf8"));
121
+ function tableBeside(genFile2) {
122
+ const file = join(dirname(genFile2), "icons.table.json");
123
+ return existsSync(file) ? read(file) : void 0;
124
+ }
125
+ function namespaceIn(genFile2) {
126
+ return /scopedIcon<[^>]*>\(\s*['"]([^'"]+)['"]\s*\)/.exec(readFileSync(genFile2, "utf8"))?.[1];
127
+ }
128
+ function declaredTable(pkgDir) {
129
+ const pkgFile = join(pkgDir, "package.json");
130
+ if (!existsSync(pkgFile)) return void 0;
131
+ const table = JSON.parse(readFileSync(pkgFile, "utf8")).weaselIcons?.table;
132
+ return table && existsSync(join(pkgDir, table)) ? read(join(pkgDir, table)) : void 0;
133
+ }
134
+ var named = (file) => existsSync(file) && typeof JSON.parse(readFileSync(file, "utf8")).name === "string";
135
+ function packageDirFinder() {
136
+ const cache = /* @__PURE__ */ new Map();
137
+ const find = (dir) => {
138
+ if (cache.has(dir)) return cache.get(dir);
139
+ const parent = dirname(dir);
140
+ const out = named(join(dir, "package.json")) ? dir : parent === dir ? void 0 : find(parent);
141
+ cache.set(dir, out);
142
+ return out;
143
+ };
144
+ return (file) => find(dirname(file));
145
+ }
146
+ var GEN = /^icons\.gen\.[cm]?[jt]sx?$/;
147
+ var SKIP = /* @__PURE__ */ new Set(["node_modules", "dist"]);
148
+ var OWN_FIXTURES = join(import.meta.dirname, "fixtures");
149
+ function sourceTablesUnder(dir) {
150
+ const out = [];
151
+ const walk = (d) => {
152
+ const entries = readdirSync(d, { withFileTypes: true });
153
+ if (entries.some((e) => e.isFile() && GEN.test(e.name)) && existsSync(join(d, "icons.table.json"))) {
154
+ out.push(read(join(d, "icons.table.json")));
155
+ }
156
+ for (const e of entries) {
157
+ const path = join(d, e.name);
158
+ if (e.isDirectory() && !SKIP.has(e.name) && !e.name.startsWith(".") && path !== OWN_FIXTURES) walk(path);
159
+ }
160
+ };
161
+ if (existsSync(dir)) walk(dir);
162
+ return out;
163
+ }
164
+ function packageTables(pkg) {
165
+ const declared = declaredTable(pkg);
166
+ if (declared) return [declared];
167
+ const linked = lstatSync(pkg).isSymbolicLink();
168
+ const declares = existsSync(join(pkg, "package.json")) && readFileSync(join(pkg, "package.json"), "utf8").includes('"weaselIcons"');
169
+ if (!linked && !declares) return [];
170
+ const real = realpathSync(pkg);
171
+ return sourceTablesUnder(existsSync(join(real, "src")) ? join(real, "src") : real);
172
+ }
173
+ function reachableTables(root) {
174
+ const out = sourceTablesUnder(root);
175
+ for (let dir = root; ; dir = dirname(dir)) {
176
+ const nm = join(dir, "node_modules");
177
+ if (existsSync(nm)) {
178
+ const dirs = readdirSync(nm).flatMap(
179
+ (d) => d.startsWith("@") ? readdirSync(join(nm, d)).map((s) => join(nm, d, s)) : d.startsWith(".") ? [] : [join(nm, d)]
180
+ );
181
+ for (const pkg of dirs) if (existsSync(join(pkg, "package.json"))) out.push(...packageTables(pkg));
182
+ }
183
+ if (dir === parse(dir).root) return out;
184
+ }
185
+ }
186
+ function genFile(specifier, importer) {
187
+ const base = resolve(dirname(importer), specifier);
188
+ return [".ts", ".js", ""].map((e) => base + e).find((f) => existsSync(f) && /\.[cm]?[jt]sx?$/.test(f));
189
+ }
190
+
191
+ // src/virtual.ts
192
+ var PREFIX = "virtual:weasel-icons";
193
+ var RESOLVED = "\0" + PREFIX;
194
+ var USED = "";
195
+ function variantOf(id) {
196
+ if (id === RESOLVED) return USED;
197
+ return id.startsWith(RESOLVED + "/") ? id.slice(RESOLVED.length + 1) : void 0;
198
+ }
199
+ var moduleFor = (variant) => `export default JSON.parse("__WEASEL_ICONS__:${variant}");`;
200
+ var MARKER = /(["'`])__WEASEL_ICONS__:([^"'`]*)\1/g;
201
+ function subset(tables, keep) {
202
+ return tables.map((t) => ({
203
+ ...t,
204
+ icons: Object.fromEntries(Object.entries(t.icons).filter(([n, g]) => keep(t.namespace, n, g.tags, g.group)))
205
+ })).filter((t) => Object.keys(t.icons).length > 0);
206
+ }
207
+ function admits(f) {
208
+ return (ns, _name, tags, group) => (!f.namespaces || f.namespaces.includes(ns)) && (!f.groups || f.groups.includes(group)) && (!f.tags || f.tags.some((t) => tags.includes(t)));
209
+ }
210
+
211
+ // src/catalog.ts
212
+ function fail(ctx, message) {
213
+ if ("error" in ctx && typeof ctx.error === "function") ctx.error(message);
214
+ throw new Error(message);
215
+ }
216
+ function tablesFrom(gens, pkgs) {
217
+ return [...[...gens].map(tableBeside), ...[...pkgs].map(declaredTable)].filter((t) => t !== void 0);
218
+ }
219
+ function iconCatalog(variants) {
220
+ const refs = /* @__PURE__ */ new Map();
221
+ const tables = /* @__PURE__ */ new Map();
222
+ const uses = /* @__PURE__ */ new Map();
223
+ const add = (ctx, table) => {
224
+ const held = tables.get(table.namespace);
225
+ if (held && held.owner !== table.owner) {
226
+ fail(ctx, `the icon namespace "${table.namespace}" is claimed by both ${held.owner} and ${table.owner}`);
227
+ }
228
+ if (table.namespace in variants) {
229
+ fail(ctx, `the custom icon variant "${table.namespace}" has the name of ${table.owner}'s icon namespace`);
230
+ }
231
+ tables.set(table.namespace, held ? { ...table, icons: { ...held.icons, ...table.icons } } : table);
232
+ };
233
+ return {
234
+ add,
235
+ record: (id, use) => void uses.set(id, use),
236
+ /** Drop the modules a rebuild no longer holds. */
237
+ keep(live) {
238
+ for (const id of uses.keys()) if (!live.has(id)) uses.delete(id);
239
+ },
240
+ /** Read every table afresh from the recorded uses, and fail on a ref no table holds. */
241
+ settle(ctx) {
242
+ tables.clear();
243
+ refs.clear();
244
+ const all = [...uses.values()];
245
+ const pkgs = new Set(all.flatMap((u) => u.pkg ? [u.pkg] : []));
246
+ for (const t of tablesFrom(new Set(all.flatMap((u) => u.gens)), pkgs)) add(ctx, t);
247
+ for (const u of all) for (const ref of u.refs) if (!refs.has(ref)) refs.set(ref, u.file);
248
+ for (const [ref, from] of refs) {
249
+ const parts = splitIconRef(ref);
250
+ const table = parts && tables.get(parts.namespace);
251
+ if (!parts || !table) fail(ctx, `no package in this build provides the icon namespace "${parts?.namespace ?? ref}" (named in ${from})`);
252
+ if (!table.icons[parts.name]) fail(ctx, `icon "${ref}" is not in ${table.owner}'s table (named in ${from})`);
253
+ }
254
+ },
255
+ /** The tables a variant holds; in dev the used variant holds every table. */
256
+ variant(ctx, variant, dev) {
257
+ const all = [...tables.values()];
258
+ if (variant === USED) return dev ? all : subset(all, (ns, name) => refs.has(`${ns}:${name}`));
259
+ if (variant === "all") return all;
260
+ const custom = variants[variant];
261
+ if (custom) return subset(all, admits(custom));
262
+ const own = tables.get(variant);
263
+ if (!own) fail(ctx, `virtual:weasel-icons/${variant} names no custom variant and no icon namespace in this build`);
264
+ return [own];
265
+ }
266
+ };
267
+ }
268
+ var ICONS_GEN = /icons\.gen(?:\.[cm]?[jt]sx?)?$/;
269
+ var NAME = /^[^'"`\s\\]+$/;
270
+ function literalArg(args) {
271
+ const [arg] = args;
272
+ if (args.length !== 1 || !arg) return void 0;
273
+ if (arg.type === "Literal" && typeof arg.value === "string") return arg.value;
274
+ const quasis = arg.quasis;
275
+ if (arg.type === "TemplateLiteral" && quasis?.length === 1) return quasis[0].value.cooked ?? void 0;
276
+ return void 0;
277
+ }
278
+ function rewriteIconCalls(code, id, namespaceOf, warn) {
279
+ if (!code.includes("icons.gen")) return null;
280
+ const parsed = parseModule(code, id);
281
+ if ("error" in parsed) {
282
+ warn?.(`${id}: icon() calls left unrewritten, the module did not parse: ${parsed.error}`);
283
+ return null;
284
+ }
285
+ const locals = /* @__PURE__ */ new Map();
286
+ const unfollowed = (form) => warn?.(`${id}: a ${form} of icon from an icons.gen module is not followed, so its calls are not rewritten and their glyphs can miss a trimmed build`);
287
+ const fromGen = (source) => !!source && ICONS_GEN.test(source.value) && namespaceOf(source.value) !== void 0;
288
+ const nameOf = (n) => n.type === "Identifier" ? n.name : String(n.value);
289
+ for (const node of parsed.program.body) {
290
+ if (node.type === "ExportAllDeclaration" && node.exportKind !== "type" && fromGen(node.source)) unfollowed("re-export");
291
+ if (node.type === "ExportNamedDeclaration" && node.exportKind !== "type" && node.source && fromGen(node.source)) {
292
+ if (node.specifiers.some((e) => e.exportKind !== "type" && nameOf(e.local) === "icon")) unfollowed("re-export");
293
+ }
294
+ if (node.type !== "ImportDeclaration" || node.importKind === "type" || !ICONS_GEN.test(node.source.value)) continue;
295
+ const namespace = namespaceOf(node.source.value);
296
+ if (!namespace) continue;
297
+ for (const spec of node.specifiers) {
298
+ if (spec.type === "ImportNamespaceSpecifier") unfollowed("namespace import");
299
+ if (spec.type === "ImportDefaultSpecifier") unfollowed("default import");
300
+ if (spec.type !== "ImportSpecifier" || spec.importKind === "type") continue;
301
+ if (nameOf(spec.imported) === "icon") locals.set(spec.local.name, namespace);
302
+ }
303
+ }
304
+ for (const node of parsed.program.body) {
305
+ const local = node.type === "ExportNamedDeclaration" && !node.source && node.exportKind !== "type" ? node.specifiers.some((e) => locals.has(nameOf(e.local) ?? "")) : node.type === "ExportDefaultDeclaration" && node.declaration.type === "Identifier" && locals.has(node.declaration.name);
306
+ if (local) unfollowed("re-export");
307
+ }
308
+ if (locals.size === 0) return null;
309
+ const s = new MagicString(code);
310
+ let dynamic = 0;
311
+ new Visitor({
312
+ CallExpression(node) {
313
+ if (node.callee.type !== "Identifier" || !locals.has(node.callee.name)) return;
314
+ const name = literalArg(node.arguments);
315
+ if (name === void 0 || !NAME.test(name)) {
316
+ dynamic++;
317
+ return;
318
+ }
319
+ s.overwrite(node.start, node.end, `/* @icon */ '${qualify(locals.get(node.callee.name), name)}'`);
320
+ }
321
+ }).visit(parsed.program);
322
+ return { code: s.toString(), map: s.generateMap({ source: id, hires: true }), dynamic };
323
+ }
324
+
325
+ // src/index.ts
326
+ var SOURCE = /\.[cm]?[jt]sx?$/;
327
+ function liveModules(ctx) {
328
+ if (!("getModuleIds" in ctx) || typeof ctx.getModuleIds !== "function") return void 0;
329
+ return new Set(ctx.getModuleIds());
330
+ }
331
+ var weaselIcons = createUnplugin((options, meta) => {
332
+ assertBundler(options.mode, meta.framework);
333
+ const variants = options.variants ?? {};
334
+ for (const name of Object.keys(variants)) {
335
+ if (name === "all" || name === "") throw new Error(`weaselIcons: a custom variant cannot be named "${name}"`);
336
+ }
337
+ const app = options.mode === "app";
338
+ const catalog = iconCatalog(variants);
339
+ const packageDir = packageDirFinder();
340
+ const seenPackages = /* @__PURE__ */ new Set();
341
+ const library = libraryAnnotations();
342
+ let dev = false;
343
+ function renderChunk(code, chunk) {
344
+ if (!app) return library.renderChunk(code, chunk);
345
+ if (!code.includes("__WEASEL_ICONS__")) return null;
346
+ const s = new MagicString(code);
347
+ for (const m of code.matchAll(MARKER)) {
348
+ const json = JSON.stringify(JSON.stringify(catalog.variant(this, m[2], dev)));
349
+ s.overwrite(m.index, m.index + m[0].length, json);
350
+ }
351
+ return { code: s.toString(), map: s.generateMap({ hires: true }).toString() };
352
+ }
353
+ const lastRenderChunk = { order: "post", handler: renderChunk };
354
+ function generateBundle(_, bundle) {
355
+ const stripped = app ? void 0 : library.stripped(bundle);
356
+ if (stripped) fail(this, stripped);
357
+ }
358
+ return {
359
+ name: "weasel-icons",
360
+ enforce: "pre",
361
+ transformInclude: (id) => !id.startsWith("\0") && SOURCE.test(id.split("?")[0]),
362
+ transform(code, id) {
363
+ const file = id.split("?")[0];
364
+ const gens = [];
365
+ const out = rewriteIconCalls(
366
+ code,
367
+ file,
368
+ (spec) => {
369
+ const gen = genFile(spec, file);
370
+ if (gen) gens.push(gen);
371
+ return gen && namespaceIn(gen);
372
+ },
373
+ (message) => this.warn(message)
374
+ );
375
+ if (out && out.dynamic > 0) {
376
+ this.warn(`${file}: ${out.dynamic} icon() call(s) with a computed name resolve only from a loaded variant`);
377
+ }
378
+ const named2 = collectIconRefs(out?.code ?? code, file);
379
+ if (!app) {
380
+ library.record(id, named2);
381
+ } else {
382
+ const pkg = packageDir(file);
383
+ if (!dev) {
384
+ catalog.record(id, { file, gens, pkg, refs: named2 });
385
+ } else {
386
+ const fresh = pkg && !seenPackages.has(pkg) ? [pkg] : [];
387
+ fresh.forEach((d) => seenPackages.add(d));
388
+ for (const t of tablesFrom(gens, fresh)) catalog.add(this, t);
389
+ }
390
+ }
391
+ return out ? { code: out.code, map: out.map } : null;
392
+ },
393
+ resolveId: (id) => app && (id === PREFIX || id.startsWith(PREFIX + "/")) ? "\0" + id : null,
394
+ loadInclude: (id) => variantOf(id) !== void 0,
395
+ load(id) {
396
+ const variant = variantOf(id);
397
+ if (variant === void 0) return null;
398
+ return dev ? `export default ${JSON.stringify(catalog.variant(this, variant, dev))};` : moduleFor(variant);
399
+ },
400
+ buildEnd() {
401
+ if (dev) return;
402
+ const live = liveModules(this);
403
+ if (live) {
404
+ catalog.keep(live);
405
+ library.keep(live);
406
+ }
407
+ if (app) catalog.settle(this);
408
+ },
409
+ vite: {
410
+ configResolved(config) {
411
+ dev = config.command === "serve" || config.mode === "test";
412
+ if (app && dev) for (const t of reachableTables(config.root)) catalog.add(this, t);
413
+ },
414
+ renderChunk: lastRenderChunk,
415
+ generateBundle
416
+ },
417
+ rollup: { renderChunk: lastRenderChunk, generateBundle },
418
+ rolldown: { renderChunk: lastRenderChunk, generateBundle }
419
+ };
420
+ });
421
+
422
+ export { collectIconRefs, weaselIcons };
423
+ //# sourceMappingURL=index.js.map
424
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/parse.ts","../src/collect.ts","../src/annotate.ts","../src/bundlers.ts","../../icons/src/names.ts","../src/tables.ts","../src/virtual.ts","../src/catalog.ts","../src/rewrite.ts","../src/index.ts"],"names":["named","genFile","MagicString","Visitor"],"mappings":"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","file":"index.js","sourcesContent":["import { parseSync, type ParseResult } from 'oxc-parser';\n\ntype Lang = 'js' | 'jsx' | 'ts' | 'tsx';\n\n/** The grammar a module id's extension names; anything unrecognized parses as JS. */\nexport function langOf(id: string): Lang {\n const m = /\\.[cm]?([jt])s(x?)$/.exec(id);\n if (!m) return 'js';\n return `${m[1]}s${m[2]}` as Lang;\n}\n\n/** `code` parsed as an ES module, or the first error when it does not parse cleanly. */\nexport function parseModule(code: string, id: string): ParseResult | { error: string } {\n const result = parseSync(id, code, { lang: langOf(id), sourceType: 'module' });\n return result.errors.length > 0 ? { error: result.errors[0]!.message } : result;\n}\n","import { Visitor, type ParseResult } from 'oxc-parser';\nimport { parseModule } from './parse';\n\nconst ANNOTATED = /\\/\\*\\s*@icon\\s*\\*\\/\\s*(['\"])([^'\"]+)\\1/g;\nconst ANNOTATION = /^\\s*@icon\\s*$/;\n\n/** Every string literal in a parsed module, a template with no substitution included, by start offset. */\nexport function stringLiterals(parsed: ParseResult): Map<number, string> {\n const literals = new Map<number, string>();\n new Visitor({\n Literal(node) {\n if (typeof node.value === 'string') literals.set(node.start, node.value);\n },\n TemplateLiteral(node) {\n const cooked = node.expressions.length === 0 ? node.quasis[0]?.value.cooked : undefined;\n if (typeof cooked === 'string') literals.set(node.start, cooked);\n },\n }).visit(parsed.program);\n return literals;\n}\n\n/** The start offset of each string literal an `@icon` block comment leads, with its value. */\nexport function annotatedLiterals(parsed: ParseResult, code: string, literals = stringLiterals(parsed)): Map<number, string> {\n const out = new Map<number, string>();\n for (const c of parsed.comments) {\n if (c.type !== 'Block' || !ANNOTATION.test(c.value)) continue;\n let at = c.end;\n while (at < code.length && /\\s/.test(code[at]!)) at++;\n const ref = literals.get(at);\n if (ref !== undefined) out.set(at, ref);\n }\n return out;\n}\n\n/**\n * Every qualified ref the module names as a string literal led by an `@icon` block comment.\n * A module that does not parse falls back to a plain scan, which can over-count but never drops one.\n */\nexport function collectIconRefs(code: string, id = 'module.js'): string[] {\n if (!code.includes('@icon')) return [];\n const parsed = parseModule(code, id);\n if ('error' in parsed) return [...code.matchAll(ANNOTATED)].map((m) => m[2]!);\n return [...annotatedLiterals(parsed, code).values()];\n}\n","import MagicString from 'magic-string';\nimport { annotatedLiterals, stringLiterals } from './collect';\nimport { parseModule } from './parse';\n\n/** The start and value of each string literal in a chunk that is one of `refs` and has no `@icon` annotation. */\nfunction unannotated(code: string, id: string, refs: ReadonlySet<string>): [number, string][] {\n if (![...refs].some((r) => code.includes(r))) return [];\n const parsed = parseModule(code, id);\n if ('error' in parsed) throw new Error(`${id}: cannot check its @icon annotations, the chunk did not parse: ${parsed.error}`);\n const literals = stringLiterals(parsed);\n const done = annotatedLiterals(parsed, code, literals);\n return [...literals].filter(([start, value]) => refs.has(value) && !done.has(start));\n}\n\n/**\n * Annotate every string literal in a bundled chunk whose value is one of `refs`, unless it already\n * is. rolldown drops plain block comments as it generates a chunk, so a library built with it gets\n * its annotations back here.\n */\nexport function annotateRefs(code: string, id: string, refs: ReadonlySet<string>) {\n const bare = unannotated(code, id, refs);\n if (bare.length === 0) return null;\n const s = new MagicString(code);\n for (const [start] of bare) s.prependLeft(start, '/* @icon */ ');\n return { code: s.toString(), map: s.generateMap({ hires: true }).toString() };\n}\n\n/**\n * Library mode's bookkeeping: every ref the build's modules were left naming, annotated again in\n * whichever chunk a literal lands in, since a bundler can inline a constant into another chunk.\n */\nexport function libraryAnnotations() {\n const moduleRefs = new Map<string, string[]>();\n const all = () => new Set([...moduleRefs.values()].flat());\n return {\n record(id: string, refs: string[]) {\n if (refs.length > 0) moduleRefs.set(id, refs);\n else moduleRefs.delete(id);\n },\n /** Drop the modules a rebuild no longer holds. */\n keep(ids: ReadonlySet<string>) {\n for (const id of moduleRefs.keys()) if (!ids.has(id)) moduleRefs.delete(id);\n },\n renderChunk(code: string, chunk: { fileName: string }) {\n const named = all();\n return named.size > 0 ? annotateRefs(code, chunk.fileName, named) : null;\n },\n /** Why the bundle is wrong, when a chunk holds a recorded ref with its annotation stripped. */\n stripped(bundle: Record<string, { type: string; code?: string }>): string | undefined {\n const named = all();\n if (named.size === 0) return undefined;\n const lost = new Set<string>();\n for (const [file, c] of Object.entries(bundle)) {\n if (c.type === 'chunk' && c.code) for (const [, ref] of unannotated(c.code, file, named)) lost.add(ref);\n }\n if (lost.size === 0) return undefined;\n return `the library build stripped the @icon annotation from ${[...lost].join(', ')}; set both build.minify and the bundler output's minify to false`;\n },\n };\n}\n","type Mode = 'library' | 'app';\n\n/** The bundlers whose hooks each mode needs. Every other unplugin adapter is refused. */\nconst BUNDLERS: Record<Mode, readonly string[]> = {\n app: ['vite', 'rollup', 'rolldown'],\n library: ['vite', 'rollup', 'rolldown', 'esbuild'],\n};\n\n/** Throws unless `framework` runs every hook `mode` relies on. */\nexport function assertBundler(mode: Mode, framework: string): void {\n const allowed = BUNDLERS[mode];\n if (!allowed) throw new Error(`weaselIcons: mode must be 'library' or 'app', not ${JSON.stringify(mode)}`);\n if (allowed.includes(framework)) return;\n const why = mode === 'app' ? '; its virtual modules would ship as unfilled placeholders' : '';\n throw new Error(`weaselIcons: ${mode} mode runs under ${allowed.join(', ')}, not ${framework}${why}`);\n}\n","import type { QualifiedIconName } from './index';\n\ndeclare const brand: unique symbol;\n\n/** A qualified icon name (`namespace:name`) that came from `icon()` or `toIconRef`. */\nexport type IconRef = string & { readonly [brand]: 'IconRef' };\n\nconst QUALIFIED = /^([^:\\s]+):([^:\\s]+)$/;\n\n/** `name` in `namespace`, unless it already names one. */\nexport function qualify(namespace: string, name: string): string {\n return name.includes(':') ? name : `${namespace}:${name}`;\n}\n\n/** The two halves of a qualified ref, or `undefined` for anything else. */\nexport function splitIconRef(ref: string): { namespace: string; name: string } | undefined {\n const m = QUALIFIED.exec(ref);\n return m ? { namespace: m[1]!, name: m[2]! } : undefined;\n}\n\n/** A string read at run time (a schema loaded as JSON) as a ref, when it is qualified. */\nexport function toIconRef(value: string | undefined): IconRef | undefined {\n return value !== undefined && QUALIFIED.test(value) ? (value as IconRef) : undefined;\n}\n\n/** A package's `icon()`: bare names resolve in `namespace` only. Generated into each package's `icons.gen.ts`. */\nexport function scopedIcon<Own extends string>(namespace: string) {\n return (name: Own | QualifiedIconName): IconRef => qualify(namespace, name) as IconRef;\n}\n","import { existsSync, lstatSync, readdirSync, readFileSync, realpathSync } from 'node:fs';\nimport { dirname, join, parse, resolve } from 'node:path';\nimport type { IconTable } from '@weasel-js/icons';\n\nconst read = (file: string): IconTable => JSON.parse(readFileSync(file, 'utf8')) as IconTable;\n\n/** The table beside a generated icons.gen module. */\nexport function tableBeside(genFile: string): IconTable | undefined {\n const file = join(dirname(genFile), 'icons.table.json');\n return existsSync(file) ? read(file) : undefined;\n}\n\n/** The namespace a generated icons.gen module binds, read from its scopedIcon call. */\nexport function namespaceIn(genFile: string): string | undefined {\n return /scopedIcon<[^>]*>\\(\\s*['\"]([^'\"]+)['\"]\\s*\\)/.exec(readFileSync(genFile, 'utf8'))?.[1];\n}\n\n/** The table a package directory declares through its `weaselIcons.table` field. */\nexport function declaredTable(pkgDir: string): IconTable | undefined {\n const pkgFile = join(pkgDir, 'package.json');\n if (!existsSync(pkgFile)) return undefined;\n const table = (JSON.parse(readFileSync(pkgFile, 'utf8')) as { weaselIcons?: { table?: string } }).weaselIcons?.table;\n return table && existsSync(join(pkgDir, table)) ? read(join(pkgDir, table)) : undefined;\n}\n\n// A manifest with no name, such as a `dist/package.json` holding only `type`, does not root a package.\nconst named = (file: string) => existsSync(file) && typeof (JSON.parse(readFileSync(file, 'utf8')) as { name?: unknown }).name === 'string';\n\n/** Finds the package directory a file belongs to, caching by directory. */\nexport function packageDirFinder() {\n const cache = new Map<string, string | undefined>();\n const find = (dir: string): string | undefined => {\n if (cache.has(dir)) return cache.get(dir);\n const parent = dirname(dir);\n const out = named(join(dir, 'package.json')) ? dir : parent === dir ? undefined : find(parent);\n cache.set(dir, out);\n return out;\n };\n return (file: string) => find(dirname(file));\n}\n\nconst GEN = /^icons\\.gen\\.[cm]?[jt]sx?$/;\nconst SKIP = new Set(['node_modules', 'dist']);\nconst OWN_FIXTURES = join(import.meta.dirname, 'fixtures');\n\n/** Every table sitting beside a generated icons.gen anywhere under `dir`, outside `node_modules`, `dist` and this plugin's test fixtures. */\nexport function sourceTablesUnder(dir: string): IconTable[] {\n const out: IconTable[] = [];\n const walk = (d: string) => {\n const entries = readdirSync(d, { withFileTypes: true });\n if (entries.some((e) => e.isFile() && GEN.test(e.name)) && existsSync(join(d, 'icons.table.json'))) {\n out.push(read(join(d, 'icons.table.json')));\n }\n for (const e of entries) {\n const path = join(d, e.name);\n if (e.isDirectory() && !SKIP.has(e.name) && !e.name.startsWith('.') && path !== OWN_FIXTURES) walk(path);\n }\n };\n if (existsSync(dir)) walk(dir);\n return out;\n}\n\n/**\n * The tables a package ships, or, when it is a linked workspace package or its declared table\n * is not built, the source tables under its `src`.\n */\nfunction packageTables(pkg: string): IconTable[] {\n const declared = declaredTable(pkg);\n if (declared) return [declared];\n const linked = lstatSync(pkg).isSymbolicLink();\n const declares = existsSync(join(pkg, 'package.json')) && readFileSync(join(pkg, 'package.json'), 'utf8').includes('\"weaselIcons\"');\n if (!linked && !declares) return [];\n const real = realpathSync(pkg);\n return sourceTablesUnder(existsSync(join(real, 'src')) ? join(real, 'src') : real);\n}\n\n/**\n * Every table the app at `root` can reach without a transform: its own source tables, and those\n * of each package in a `node_modules` at `root` or above it. Dev and vitest use this, since vite\n * pre-bundles dependencies with esbuild, skipping the plugin, and a virtual module can load\n * before the modules that would reveal a table are transformed.\n */\nexport function reachableTables(root: string): IconTable[] {\n const out = sourceTablesUnder(root);\n for (let dir = root; ; dir = dirname(dir)) {\n const nm = join(dir, 'node_modules');\n if (existsSync(nm)) {\n const dirs = readdirSync(nm).flatMap((d) =>\n d.startsWith('@') ? readdirSync(join(nm, d)).map((s) => join(nm, d, s)) : d.startsWith('.') ? [] : [join(nm, d)],\n );\n for (const pkg of dirs) if (existsSync(join(pkg, 'package.json'))) out.push(...packageTables(pkg));\n }\n if (dir === parse(dir).root) return out;\n }\n}\n\n/** The icons.gen source file an import specifier names, relative to its importer. */\nexport function genFile(specifier: string, importer: string): string | undefined {\n const base = resolve(dirname(importer), specifier);\n return ['.ts', '.js', ''].map((e) => base + e).find((f) => existsSync(f) && /\\.[cm]?[jt]sx?$/.test(f));\n}\n","import type { IconTable } from '@weasel-js/icons';\n\nexport const PREFIX = 'virtual:weasel-icons';\nexport const RESOLVED = '\\0' + PREFIX;\n/** The default module's variant: the glyphs the build names. */\nexport const USED = '';\n\n/** The variant a resolved virtual id names, or `undefined` for any other id. */\nexport function variantOf(id: string): string | undefined {\n if (id === RESOLVED) return USED;\n return id.startsWith(RESOLVED + '/') ? id.slice(RESOLVED.length + 1) : undefined;\n}\n\n/** A string literal survives minification; an identifier would be renamed. */\nexport const moduleFor = (variant: string) => `export default JSON.parse(\"__WEASEL_ICONS__:${variant}\");`;\nexport const MARKER = /([\"'`])__WEASEL_ICONS__:([^\"'`]*)\\1/g;\n\n/** Which glyphs a custom variant holds. Each listed field narrows; a glyph needs one of the listed tags. */\nexport interface VariantFilter {\n namespaces?: string[];\n groups?: string[];\n tags?: string[];\n}\n\ntype Keep = (ns: string, name: string, tags: readonly string[], group: string) => boolean;\n\n/** `tables` cut down to the glyphs `keep` admits, dropping any table left empty. */\nexport function subset(tables: readonly IconTable[], keep: Keep): IconTable[] {\n return tables\n .map((t) => ({\n ...t,\n icons: Object.fromEntries(Object.entries(t.icons).filter(([n, g]) => keep(t.namespace, n, g.tags, g.group))),\n }))\n .filter((t) => Object.keys(t.icons).length > 0);\n}\n\nexport function admits(f: VariantFilter): Keep {\n return (ns, _name, tags, group) =>\n (!f.namespaces || f.namespaces.includes(ns)) &&\n (!f.groups || f.groups.includes(group)) &&\n (!f.tags || f.tags.some((t) => tags.includes(t)));\n}\n","import type { IconTable } from '@weasel-js/icons';\n// Relative, and so bundled in: vite and tsup configs load this from source, before any dist exists.\nimport { splitIconRef } from '../../icons/src/names';\nimport { declaredTable, tableBeside } from './tables';\nimport { USED, admits, subset, type VariantFilter } from './virtual';\n\n/** What one transformed module read. */\nexport interface ModuleUse {\n readonly file: string;\n /** The icons.gen modules it imports. */\n readonly gens: readonly string[];\n readonly pkg: string | undefined;\n readonly refs: readonly string[];\n}\n\n/** Report through the bundler when its context can, and throw in case it only records. */\nexport function fail(ctx: object, message: string): never {\n if ('error' in ctx && typeof ctx.error === 'function') ctx.error(message);\n throw new Error(message);\n}\n\n/** The tables beside each icons.gen module and declared by each package directory. */\nexport function tablesFrom(gens: Iterable<string>, pkgs: Iterable<string>): IconTable[] {\n return [...[...gens].map(tableBeside), ...[...pkgs].map(declaredTable)].filter((t): t is IconTable => t !== undefined);\n}\n\n/**\n * App mode's tables and refs. A build records each module's use, and at its end rebuilds both from\n * the modules it still holds, so a watch rebuild forgets what an earlier build saw.\n */\nexport function iconCatalog(variants: Record<string, VariantFilter>) {\n const refs = new Map<string, string>();\n const tables = new Map<string, IconTable>();\n const uses = new Map<string, ModuleUse>();\n\n const add = (ctx: object, table: IconTable) => {\n const held = tables.get(table.namespace);\n if (held && held.owner !== table.owner) {\n fail(ctx, `the icon namespace \"${table.namespace}\" is claimed by both ${held.owner} and ${table.owner}`);\n }\n if (table.namespace in variants) {\n fail(ctx, `the custom icon variant \"${table.namespace}\" has the name of ${table.owner}'s icon namespace`);\n }\n tables.set(table.namespace, held ? { ...table, icons: { ...held.icons, ...table.icons } } : table);\n };\n\n return {\n add,\n record: (id: string, use: ModuleUse) => void uses.set(id, use),\n /** Drop the modules a rebuild no longer holds. */\n keep(live: ReadonlySet<string>) {\n for (const id of uses.keys()) if (!live.has(id)) uses.delete(id);\n },\n /** Read every table afresh from the recorded uses, and fail on a ref no table holds. */\n settle(ctx: object) {\n tables.clear();\n refs.clear();\n const all = [...uses.values()];\n const pkgs = new Set(all.flatMap((u) => (u.pkg ? [u.pkg] : [])));\n for (const t of tablesFrom(new Set(all.flatMap((u) => u.gens)), pkgs)) add(ctx, t);\n for (const u of all) for (const ref of u.refs) if (!refs.has(ref)) refs.set(ref, u.file);\n for (const [ref, from] of refs) {\n const parts = splitIconRef(ref);\n const table = parts && tables.get(parts.namespace);\n if (!parts || !table) fail(ctx, `no package in this build provides the icon namespace \"${parts?.namespace ?? ref}\" (named in ${from})`);\n if (!table.icons[parts.name]) fail(ctx, `icon \"${ref}\" is not in ${table.owner}'s table (named in ${from})`);\n }\n },\n /** The tables a variant holds; in dev the used variant holds every table. */\n variant(ctx: object, variant: string, dev: boolean): IconTable[] {\n const all = [...tables.values()];\n if (variant === USED) return dev ? all : subset(all, (ns, name) => refs.has(`${ns}:${name}`));\n if (variant === 'all') return all;\n const custom = variants[variant];\n if (custom) return subset(all, admits(custom));\n const own = tables.get(variant);\n if (!own) fail(ctx, `virtual:weasel-icons/${variant} names no custom variant and no icon namespace in this build`);\n return [own];\n },\n };\n}\n","import MagicString, { type SourceMap } from 'magic-string';\nimport { Visitor } from 'oxc-parser';\nimport { qualify } from '../../icons/src/names';\nimport { parseModule } from './parse';\n\nconst ICONS_GEN = /icons\\.gen(?:\\.[cm]?[jt]sx?)?$/;\nconst NAME = /^[^'\"`\\s\\\\]+$/;\n\nexport interface RewriteResult {\n readonly code: string;\n readonly map: SourceMap;\n /** Calls whose argument is not a string literal, left as calls. */\n readonly dynamic: number;\n}\n\ninterface Node {\n readonly type: string;\n readonly start: number;\n readonly end: number;\n readonly [key: string]: unknown;\n}\n\n/** The string a call's lone argument spells, when it is a literal. */\nfunction literalArg(args: readonly Node[]): string | undefined {\n const [arg] = args;\n if (args.length !== 1 || !arg) return undefined;\n if (arg.type === 'Literal' && typeof arg.value === 'string') return arg.value;\n const quasis = arg.quasis as { value: { cooked: string | null } }[] | undefined;\n if (arg.type === 'TemplateLiteral' && quasis?.length === 1) return quasis[0]!.value.cooked ?? undefined;\n return undefined;\n}\n\n/**\n * Rewrite each `icon('x')` imported from a generated icons.gen into an annotated, qualified literal.\n * A module that does not parse is left alone, and `warn` hears why.\n */\nexport function rewriteIconCalls(\n code: string,\n id: string,\n namespaceOf: (specifier: string) => string | undefined,\n warn?: (message: string) => void,\n): RewriteResult | null {\n if (!code.includes('icons.gen')) return null;\n const parsed = parseModule(code, id);\n if ('error' in parsed) {\n warn?.(`${id}: icon() calls left unrewritten, the module did not parse: ${parsed.error}`);\n return null;\n }\n const locals = new Map<string, string>();\n const unfollowed = (form: string) =>\n warn?.(`${id}: a ${form} of icon from an icons.gen module is not followed, so its calls are not rewritten and their glyphs can miss a trimmed build`);\n const fromGen = (source: { value: string } | null | undefined) =>\n !!source && ICONS_GEN.test(source.value) && namespaceOf(source.value) !== undefined;\n const nameOf = (n: { type: string; name?: string; value?: unknown }) => (n.type === 'Identifier' ? n.name : String(n.value));\n for (const node of parsed.program.body) {\n if (node.type === 'ExportAllDeclaration' && node.exportKind !== 'type' && fromGen(node.source)) unfollowed('re-export');\n if (node.type === 'ExportNamedDeclaration' && node.exportKind !== 'type' && node.source && fromGen(node.source)) {\n if (node.specifiers.some((e) => e.exportKind !== 'type' && nameOf(e.local) === 'icon')) unfollowed('re-export');\n }\n if (node.type !== 'ImportDeclaration' || node.importKind === 'type' || !ICONS_GEN.test(node.source.value)) continue;\n const namespace = namespaceOf(node.source.value);\n if (!namespace) continue;\n for (const spec of node.specifiers) {\n if (spec.type === 'ImportNamespaceSpecifier') unfollowed('namespace import');\n if (spec.type === 'ImportDefaultSpecifier') unfollowed('default import');\n if (spec.type !== 'ImportSpecifier' || spec.importKind === 'type') continue;\n if (nameOf(spec.imported) === 'icon') locals.set(spec.local.name, namespace);\n }\n }\n for (const node of parsed.program.body) {\n const local =\n node.type === 'ExportNamedDeclaration' && !node.source && node.exportKind !== 'type'\n ? node.specifiers.some((e) => locals.has(nameOf(e.local) ?? ''))\n : node.type === 'ExportDefaultDeclaration' && node.declaration.type === 'Identifier' && locals.has(node.declaration.name);\n if (local) unfollowed('re-export');\n }\n if (locals.size === 0) return null;\n const s = new MagicString(code);\n let dynamic = 0;\n new Visitor({\n CallExpression(node) {\n if (node.callee.type !== 'Identifier' || !locals.has(node.callee.name)) return;\n const name = literalArg(node.arguments as unknown as Node[]);\n if (name === undefined || !NAME.test(name)) {\n dynamic++;\n return;\n }\n s.overwrite(node.start, node.end, `/* @icon */ '${qualify(locals.get(node.callee.name)!, name)}'`);\n },\n }).visit(parsed.program);\n return { code: s.toString(), map: s.generateMap({ source: id, hires: true }), dynamic };\n}\n","import MagicString from 'magic-string';\nimport { createUnplugin, type UnpluginInstance } from 'unplugin';\nimport { libraryAnnotations } from './annotate';\nimport { assertBundler } from './bundlers';\nimport { fail, iconCatalog, tablesFrom } from './catalog';\nimport { collectIconRefs } from './collect';\nimport { rewriteIconCalls } from './rewrite';\nimport { genFile, namespaceIn, packageDirFinder, reachableTables } from './tables';\nimport { MARKER, PREFIX, moduleFor, variantOf, type VariantFilter } from './virtual';\n\nexport type { VariantFilter } from './virtual';\nexport { collectIconRefs } from './collect';\n\n/** How {@link weaselIcons} treats the build it runs in. */\nexport interface WeaselIconsOptions {\n /**\n * `library` only rewrites `icon()` calls, under vite, rollup, rolldown or esbuild. `app` also emits\n * `virtual:weasel-icons` and its variants, and needs vite, rollup or rolldown: the others have no\n * hook to fill them in once every module is seen.\n */\n mode: 'library' | 'app';\n /** Extra variants, each loadable as `virtual:weasel-icons/<name>`. */\n variants?: Record<string, VariantFilter>;\n}\n\nconst SOURCE = /\\.[cm]?[jt]sx?$/;\n\n/** The ids of every module in the build, when the bundler's context can list them. */\nfunction liveModules(ctx: object): Set<string> | undefined {\n if (!('getModuleIds' in ctx) || typeof ctx.getModuleIds !== 'function') return undefined;\n return new Set(ctx.getModuleIds() as Iterable<string>);\n}\n\n/**\n * Rewrites each `icon('x')` imported from a generated `icons.gen` into an annotated, qualified\n * literal. In `app` mode it also emits `virtual:weasel-icons`, holding only the glyphs the build\n * names, plus `/all`, `/<namespace>` and each custom variant, every one its own chunk.\n */\nexport const weaselIcons: UnpluginInstance<WeaselIconsOptions, false> = createUnplugin((options: WeaselIconsOptions, meta) => {\n assertBundler(options.mode, meta.framework);\n const variants = options.variants ?? {};\n for (const name of Object.keys(variants)) {\n if (name === 'all' || name === '') throw new Error(`weaselIcons: a custom variant cannot be named \"${name}\"`);\n }\n const app = options.mode === 'app';\n const catalog = iconCatalog(variants);\n const packageDir = packageDirFinder();\n const seenPackages = new Set<string>();\n const library = libraryAnnotations();\n let dev = false;\n\n // Runs after every module is transformed, so `refs` and `tables` are complete.\n function renderChunk(this: object, code: string, chunk: { fileName: string }) {\n if (!app) return library.renderChunk(code, chunk);\n if (!code.includes('__WEASEL_ICONS__')) return null;\n const s = new MagicString(code);\n for (const m of code.matchAll(MARKER)) {\n const json = JSON.stringify(JSON.stringify(catalog.variant(this, m[2]!, dev)));\n s.overwrite(m.index!, m.index! + m[0].length, json);\n }\n // A string map: magic-string's object form types `sourcesContent` wider than rollup accepts.\n return { code: s.toString(), map: s.generateMap({ hires: true }).toString() };\n }\n // After the bundler's own renderChunk work, which drops plain comments. rolldown's output\n // minify, even its default dead-code pass, runs later still and drops them again.\n const lastRenderChunk = { order: 'post' as const, handler: renderChunk };\n function generateBundle(this: object, _: unknown, bundle: Record<string, { type: string; code?: string }>) {\n const stripped = app ? undefined : library.stripped(bundle);\n if (stripped) fail(this, stripped);\n }\n\n return {\n name: 'weasel-icons',\n enforce: 'pre',\n transformInclude: (id) => !id.startsWith('\\0') && SOURCE.test(id.split('?')[0]!),\n transform(code, id) {\n const file = id.split('?')[0]!;\n const gens: string[] = [];\n const out = rewriteIconCalls(\n code,\n file,\n (spec) => {\n const gen = genFile(spec, file);\n if (gen) gens.push(gen);\n return gen && namespaceIn(gen);\n },\n (message) => this.warn(message),\n );\n if (out && out.dynamic > 0) {\n this.warn(`${file}: ${out.dynamic} icon() call(s) with a computed name resolve only from a loaded variant`);\n }\n const named = collectIconRefs(out?.code ?? code, file);\n if (!app) {\n library.record(id, named);\n } else {\n const pkg = packageDir(file);\n if (!dev) {\n catalog.record(id, { file, gens, pkg, refs: named });\n } else {\n const fresh = pkg && !seenPackages.has(pkg) ? [pkg] : [];\n fresh.forEach((d) => seenPackages.add(d));\n for (const t of tablesFrom(gens, fresh)) catalog.add(this, t);\n }\n }\n return out ? { code: out.code, map: out.map } : null;\n },\n resolveId: (id) => (app && (id === PREFIX || id.startsWith(PREFIX + '/')) ? '\\0' + id : null),\n loadInclude: (id) => variantOf(id) !== undefined,\n load(id) {\n const variant = variantOf(id);\n if (variant === undefined) return null;\n return dev ? `export default ${JSON.stringify(catalog.variant(this, variant, dev))};` : moduleFor(variant);\n },\n buildEnd() {\n if (dev) return;\n const live = liveModules(this);\n if (live) {\n catalog.keep(live);\n library.keep(live);\n }\n if (app) catalog.settle(this);\n },\n vite: {\n configResolved(config) {\n dev = config.command === 'serve' || config.mode === 'test';\n if (app && dev) for (const t of reachableTables(config.root)) catalog.add(this, t);\n },\n renderChunk: lastRenderChunk,\n generateBundle,\n },\n rollup: { renderChunk: lastRenderChunk, generateBundle },\n rolldown: { renderChunk: lastRenderChunk, generateBundle },\n };\n});\n"]}
package/package.json CHANGED
@@ -1,6 +1,27 @@
1
1
  {
2
2
  "name": "@weasel-js/icons-plugin",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "1.10.1",
4
+ "description": "The build plugin that ships only the glyphs a build names, for vite, rollup, rolldown and esbuild.",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "sideEffects": false,
8
+ "main": "./dist/index.js",
9
+ "module": "./dist/index.js",
10
+ "types": "./dist/index.d.ts",
11
+ "exports": {
12
+ ".": { "import": "./dist/index.js", "types": "./dist/index.d.ts" },
13
+ "./virtual": { "types": "./virtual.d.ts" },
14
+ "./package.json": "./package.json"
15
+ },
16
+ "author": "orochi235",
17
+ "homepage": "https://orochi235.github.io/weasel/",
18
+ "repository": { "type": "git", "url": "git+https://github.com/orochi235/weasel.git", "directory": "packages/icons-plugin" },
19
+ "bugs": { "url": "https://github.com/orochi235/weasel/issues" },
20
+ "engines": { "node": ">=22" },
21
+ "files": ["dist", "virtual.d.ts", "README.md", "LICENSE"],
22
+ "scripts": { "build": "tsup" },
23
+ "dependencies": { "@weasel-js/icons": "1.10.1", "magic-string": "1.4.3", "oxc-parser": "0.154.0", "unplugin": "3.4.0" },
24
+ "peerDependencies": { "vite": "^8.0.0" },
25
+ "peerDependenciesMeta": { "vite": { "optional": true } },
26
+ "publishConfig": { "access": "public", "provenance": true }
27
+ }
package/virtual.d.ts ADDED
@@ -0,0 +1,8 @@
1
+ declare module 'virtual:weasel-icons' {
2
+ const tables: readonly import('@weasel-js/icons').IconTable[];
3
+ export default tables;
4
+ }
5
+ declare module 'virtual:weasel-icons/*' {
6
+ const tables: readonly import('@weasel-js/icons').IconTable[];
7
+ export default tables;
8
+ }