@robosophy/ui-react 1.0.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,1026 @@
1
+ // AUTO-GENERATED FILE. DO NOT EDIT MANUALLY.
2
+ import {
3
+ GRADE_VARIANTS,
4
+ clampGrade
5
+ } from "./chunk-D4ZW5VUU.js";
6
+
7
+ // src/vite.ts
8
+ import { createHash } from "crypto";
9
+ import { mkdir, readFile, readdir, writeFile } from "fs/promises";
10
+ import { extname, join } from "path";
11
+ import { fileURLToPath } from "url";
12
+ var families = ["outlined", "rounded", "sharp"];
13
+ var defaultFamily = "outlined";
14
+ var iconNamePattern = /^[a-z0-9_]+$/;
15
+ var sourceExtensions = /* @__PURE__ */ new Set([".js", ".jsx", ".mjs", ".ts", ".tsx"]);
16
+ var skippedDirs = /* @__PURE__ */ new Set([".git", "dist", "node_modules", "storybook-static"]);
17
+ var cssPropertyValues = /* @__PURE__ */ new Set([
18
+ "auto",
19
+ "block",
20
+ "center",
21
+ "contain",
22
+ "cover",
23
+ "flex",
24
+ "grid",
25
+ "hidden",
26
+ "inherit",
27
+ "initial",
28
+ "left",
29
+ "middle",
30
+ "none",
31
+ "normal",
32
+ "pointer",
33
+ "relative",
34
+ "right",
35
+ "solid",
36
+ "static",
37
+ "stretch",
38
+ "text",
39
+ "top",
40
+ "unset"
41
+ ]);
42
+ var internalIconNames = [
43
+ "arrow_drop_down",
44
+ "arrow_drop_up",
45
+ "arrow_left",
46
+ "chevron_right",
47
+ "close",
48
+ "login",
49
+ "nest_eco_leaf"
50
+ ];
51
+ var GITHUB_RAW = "https://raw.githubusercontent.com/google/material-design-icons/master/symbols/web";
52
+ var CACHE_BASE = join("node_modules", ".cache", "robosophy-svgs");
53
+ var BASE_OPSZ = 24;
54
+ var DEFAULT_WEIGHT = 400;
55
+ function variantKey(grade, fill, weight) {
56
+ return `${clampGrade(grade)}:${fill ? 1 : 0}:${weight}`;
57
+ }
58
+ function parseVariantKey(key) {
59
+ const [grade, fill, weight] = key.split(":").map(Number);
60
+ return { grade, fill: fill === 1, weight };
61
+ }
62
+ function robosophyMaterialSymbols(options = {}) {
63
+ const raw = (options.outputDir ?? "").trim().replace(/^\/+/, "");
64
+ const outputDir = raw.split("/").filter((part) => part && part !== "..").join("/") || "assets";
65
+ let config;
66
+ let cacheDir;
67
+ let cachedAssets = null;
68
+ let cachedUsagesKey = "";
69
+ let needsRegeneration = true;
70
+ function usageMapKey(usages) {
71
+ const parts = [];
72
+ for (const family of families) {
73
+ const iconVariants = usages.get(family);
74
+ if (!iconVariants || iconVariants.size === 0) continue;
75
+ const entries = [...iconVariants.entries()].map(([name, variants]) => `${name}[${[...variants].sort().join(";")}]`).sort();
76
+ parts.push(`${family}:${entries.join(",")}`);
77
+ }
78
+ return parts.join("|") || "(empty)";
79
+ }
80
+ async function getAssets() {
81
+ if (!needsRegeneration && cachedAssets) return cachedAssets;
82
+ const usages = await collectMaterialSymbolUsages(config, options);
83
+ const newKey = usageMapKey(usages);
84
+ if (newKey === cachedUsagesKey && cachedAssets) {
85
+ needsRegeneration = false;
86
+ return cachedAssets;
87
+ }
88
+ if (config.command !== "build" && cachedUsagesKey !== "") {
89
+ config.logger.info(
90
+ "[robosophy-material-symbols] icon usage changed, regenerating SVG sprite"
91
+ );
92
+ }
93
+ cachedUsagesKey = newKey;
94
+ cachedAssets = await generateSpriteAssets(usages, cacheDir, config);
95
+ needsRegeneration = false;
96
+ return cachedAssets;
97
+ }
98
+ return {
99
+ name: "robosophy-material-symbols",
100
+ async configResolved(resolvedConfig) {
101
+ config = resolvedConfig;
102
+ cacheDir = join(config.root, CACHE_BASE);
103
+ await mkdir(cacheDir, { recursive: true });
104
+ },
105
+ async buildStart() {
106
+ if (config.command === "serve" || config.command === "build") {
107
+ await getAssets();
108
+ }
109
+ },
110
+ async transformIndexHtml() {
111
+ const assets = await getAssets();
112
+ const tag = {
113
+ tag: "svg",
114
+ attrs: {
115
+ xmlns: "http://www.w3.org/2000/svg",
116
+ style: "display:none;",
117
+ "aria-hidden": "true"
118
+ },
119
+ children: assets.spriteContent,
120
+ injectTo: "body-prepend"
121
+ };
122
+ return [tag, ...buildMaterialSymbolsCss(assets.css)];
123
+ },
124
+ configureServer(server) {
125
+ server.watcher.on("all", (_event, file) => {
126
+ if (sourceExtensions.has(extname(file))) {
127
+ needsRegeneration = true;
128
+ }
129
+ });
130
+ server.middlewares.use(async (request, response, next) => {
131
+ if (!request.url?.startsWith("/@robosophy-material-symbols/")) {
132
+ next();
133
+ return;
134
+ }
135
+ try {
136
+ const assets = await getAssets();
137
+ const fileName = decodeURIComponent(
138
+ request.url.replace("/@robosophy-material-symbols/", "").split("?")[0] ?? ""
139
+ );
140
+ if (fileName === "rs-material-symbols.svg") {
141
+ response.setHeader("Content-Type", "image/svg+xml; charset=utf-8");
142
+ response.setHeader("Cache-Control", "no-cache");
143
+ response.end(assets.fullSprite);
144
+ return;
145
+ }
146
+ next();
147
+ } catch (error) {
148
+ next(error);
149
+ }
150
+ });
151
+ },
152
+ async generateBundle() {
153
+ }
154
+ };
155
+ }
156
+ function buildSvgVariant(grade, fill, weight = DEFAULT_WEIGHT) {
157
+ const clampedGrade = clampGrade(grade);
158
+ const gradeSuffix = clampedGrade === 0 ? "" : clampedGrade > 0 ? `grad${clampedGrade}` : `gradN${Math.abs(clampedGrade)}`;
159
+ const symbolGradeSuffix = clampedGrade === 0 ? "" : `-${gradeSuffix}`;
160
+ const fillSuffix = fill ? "fill1" : "";
161
+ const symbolFillSuffix = fill ? "-fill" : "";
162
+ const weightSuffix = weight !== DEFAULT_WEIGHT ? `wght${weight}` : "";
163
+ const weightSymbolSuffix = weight !== DEFAULT_WEIGHT ? `-wght${weight}` : "";
164
+ const parts = [gradeSuffix, fillSuffix, weightSuffix].filter(Boolean);
165
+ return {
166
+ suffix: parts.length > 0 ? `${parts.join("")}_${BASE_OPSZ}px` : `${BASE_OPSZ}px`,
167
+ symbolSuffix: `${symbolGradeSuffix}${symbolFillSuffix}${weightSymbolSuffix}`
168
+ };
169
+ }
170
+ function buildSvgUrl(name, family, suffix) {
171
+ const style = family === "outlined" ? "materialsymbolsoutlined" : family === "rounded" ? "materialsymbolsrounded" : "materialsymbolssharp";
172
+ return `${GITHUB_RAW}/${name.toLowerCase()}/${style}/${name.toLowerCase()}_${suffix}.svg`;
173
+ }
174
+ function buildSymbolId(name, family, symbolSuffix) {
175
+ return `rs-icon-${family}-${name}${symbolSuffix}`;
176
+ }
177
+ async function fetchSvg(url) {
178
+ try {
179
+ const response = await fetch(url);
180
+ if (!response.ok) return null;
181
+ return await response.text();
182
+ } catch {
183
+ return null;
184
+ }
185
+ }
186
+ async function loadSvgFromCache(cacheDir, cacheKey) {
187
+ const cachePath = join(cacheDir, `${cacheKey}.svg`);
188
+ try {
189
+ return await readFile(cachePath, "utf8");
190
+ } catch {
191
+ return null;
192
+ }
193
+ }
194
+ async function saveSvgToCache(cacheDir, cacheKey, content) {
195
+ const cachePath = join(cacheDir, `${cacheKey}.svg`);
196
+ try {
197
+ await writeFile(cachePath, content, "utf8");
198
+ } catch {
199
+ }
200
+ }
201
+ function parseSvgPaths(svgContent) {
202
+ const viewBoxMatch = svgContent.match(/viewBox="([^"]+)"/i);
203
+ if (!viewBoxMatch) return null;
204
+ const paths = [];
205
+ const pathRegex = /<path\s+([^>]*)>/g;
206
+ let pathMatch;
207
+ while (pathMatch = pathRegex.exec(svgContent)) {
208
+ const attrs = pathMatch[1] ?? "";
209
+ const dMatch = attrs.match(/d="([^"]*)"/);
210
+ if (dMatch) {
211
+ paths.push(dMatch[1] ?? "");
212
+ }
213
+ }
214
+ if (paths.length === 0) return null;
215
+ return paths.map((d) => `<path fill="currentColor" d="${d}"/>`).join("");
216
+ }
217
+ async function generateSpriteAssets(usages, cacheDir, config) {
218
+ const symbols = [];
219
+ const iconClasses = [];
220
+ const skipped = /* @__PURE__ */ new Map();
221
+ let totalFetched = 0;
222
+ let totalBytes = 0;
223
+ for (const family of families) {
224
+ const iconVariants = usages.get(family);
225
+ if (!iconVariants || iconVariants.size === 0) continue;
226
+ for (const [name, variants] of [...iconVariants.entries()].sort()) {
227
+ for (const key of [...variants].sort()) {
228
+ const { grade, fill, weight } = parseVariantKey(key);
229
+ const variant = buildSvgVariant(grade, fill, weight);
230
+ const symbolId = buildSymbolId(name, family, variant.symbolSuffix);
231
+ const url = buildSvgUrl(name, family, variant.suffix);
232
+ const cacheKey = createHash("sha256").update(url).digest("hex").slice(0, 12);
233
+ let svgContent = cacheDir ? await loadSvgFromCache(cacheDir, cacheKey) : null;
234
+ if (!svgContent) {
235
+ svgContent = await fetchSvg(url);
236
+ if (!svgContent) {
237
+ skipped.set(`${family}/${name}`, "fetch fall\xF3");
238
+ continue;
239
+ }
240
+ if (cacheDir) {
241
+ await saveSvgToCache(cacheDir, cacheKey, svgContent);
242
+ }
243
+ }
244
+ const pathContent = parseSvgPaths(svgContent);
245
+ if (!pathContent) {
246
+ skipped.set(`${family}/${name}`, "sin viewBox / formato viejo");
247
+ continue;
248
+ }
249
+ symbols.push(
250
+ `<symbol id="${symbolId}" viewBox="0 -960 960 960" fill="currentColor">${pathContent}</symbol>`
251
+ );
252
+ totalFetched++;
253
+ totalBytes += svgContent.length;
254
+ }
255
+ }
256
+ }
257
+ const iconNames = /* @__PURE__ */ new Set();
258
+ for (const family of families) {
259
+ const iconVariants = usages.get(family);
260
+ if (iconVariants) {
261
+ for (const name of iconVariants.keys()) {
262
+ iconNames.add(name);
263
+ }
264
+ }
265
+ }
266
+ for (const name of [...iconNames].sort()) {
267
+ iconClasses.push(`.rs-icon-${name} { --rs-icon-content: "${name}"; }`);
268
+ }
269
+ const spriteContent = `<defs>${symbols.join("")}</defs>`;
270
+ const fullSprite = `<svg xmlns="http://www.w3.org/2000/svg" style="display:none" aria-hidden="true">${spriteContent}</svg>`;
271
+ const css = iconClasses.join("\n");
272
+ const totalIcons = [...usages.values()].reduce((sum, m) => sum + m.size, 0);
273
+ if (skipped.size > 0) {
274
+ const lines = [...skipped.entries()].map(([key, reason]) => `${key} (${reason})`);
275
+ config.logger.warn(
276
+ `[robosophy-material-symbols] ${skipped.size} \xEDconos omitidos, van a renderizar vac\xEDos:
277
+ ${lines.join("\n ")}`
278
+ );
279
+ }
280
+ if (totalIcons > 0) {
281
+ const summary = formatDetectedMaterialSymbols(usages);
282
+ config.logger.info(
283
+ `[robosophy-material-symbols] ${totalIcons} icons detected, ${totalFetched} SVG variants (${(totalBytes / 1024).toFixed(1)} KB)
284
+ ${summary}`
285
+ );
286
+ } else {
287
+ config.logger.warn(
288
+ "[robosophy-material-symbols] No Material Symbols icons detected in source. Add them via the include option."
289
+ );
290
+ }
291
+ return { fullSprite, spriteContent, css };
292
+ }
293
+ async function collectMaterialSymbolUsages(config, options = {}) {
294
+ const usages = createUsageMap();
295
+ const manifest = await loadIconManifest();
296
+ if (manifest) {
297
+ for (const family of families) {
298
+ for (const name of manifest[family] ?? []) {
299
+ addUsage(usages, { family, name });
300
+ }
301
+ }
302
+ } else {
303
+ for (const name of internalIconNames) {
304
+ for (const family of families) {
305
+ addUsage(usages, { family, name });
306
+ }
307
+ }
308
+ }
309
+ for (const icon of options.include ?? []) {
310
+ const resolved = typeof icon === "string" ? { family: defaultFamily, name: icon } : icon;
311
+ addUsage(usages, resolved);
312
+ }
313
+ if (options.scan !== false) {
314
+ const roots = options.roots ?? [join(config.root, "src")];
315
+ const sources = await readAllSources(roots);
316
+ for (const source of sources.values()) {
317
+ collectFromSource(source, usages);
318
+ }
319
+ const proxyComponents = findIconProxyComponents(sources);
320
+ if (proxyComponents.size > 0) {
321
+ for (const source of sources.values()) {
322
+ collectProxyIconUsages(source, proxyComponents, usages);
323
+ }
324
+ }
325
+ }
326
+ return usages;
327
+ }
328
+ function buildMaterialSymbolsCss(iconClasses) {
329
+ if (!iconClasses) return [];
330
+ return [
331
+ {
332
+ tag: "style",
333
+ children: iconClasses,
334
+ injectTo: "head"
335
+ }
336
+ ];
337
+ }
338
+ function skipStringBackward(source, pos, quote) {
339
+ pos--;
340
+ while (pos >= 0) {
341
+ if (source[pos] === "\\") {
342
+ pos -= 2;
343
+ continue;
344
+ }
345
+ if (source[pos] === quote) {
346
+ let backslashCount = 0;
347
+ let k = pos - 1;
348
+ while (k >= 0 && source[k] === "\\") {
349
+ backslashCount++;
350
+ k--;
351
+ }
352
+ if (backslashCount % 2 === 1) {
353
+ pos = pos - backslashCount - 1;
354
+ continue;
355
+ }
356
+ return pos - 1;
357
+ }
358
+ pos--;
359
+ }
360
+ return -1;
361
+ }
362
+ function skipStringForward(source, pos, quote) {
363
+ pos++;
364
+ while (pos < source.length) {
365
+ if (source[pos] === "\\") {
366
+ pos += 2;
367
+ continue;
368
+ }
369
+ if (source[pos] === quote) {
370
+ return pos + 1;
371
+ }
372
+ pos++;
373
+ }
374
+ return source.length;
375
+ }
376
+ function findEnclosingObject(source, fromIndex) {
377
+ let depth = 0;
378
+ let i = fromIndex;
379
+ while (i >= 0) {
380
+ const char = source[i];
381
+ if (char === '"' || char === "'" || char === "`") {
382
+ i = skipStringBackward(source, i, char);
383
+ continue;
384
+ }
385
+ if (char === "/" && i > 0 && source[i - 1] === "/") {
386
+ i -= 2;
387
+ while (i >= 0 && source[i] !== "\n") i--;
388
+ continue;
389
+ }
390
+ if (char === "/" && i > 0 && source[i - 1] === "*") {
391
+ i -= 2;
392
+ while (i >= 0) {
393
+ if (source[i] === "/" && i + 1 < source.length && source[i + 1] === "*") {
394
+ i--;
395
+ break;
396
+ }
397
+ i--;
398
+ }
399
+ continue;
400
+ }
401
+ if (char === "}") {
402
+ depth++;
403
+ } else if (char === "{") {
404
+ if (depth === 0) {
405
+ const start = i;
406
+ let j = i + 1;
407
+ let innerDepth = 1;
408
+ while (j < source.length) {
409
+ const c = source[j];
410
+ if (c === '"' || c === "'" || c === "`") {
411
+ j = skipStringForward(source, j, c);
412
+ continue;
413
+ }
414
+ if (c === "/") {
415
+ if (j + 1 < source.length && source[j + 1] === "/") {
416
+ j += 2;
417
+ while (j < source.length && source[j] !== "\n") j++;
418
+ continue;
419
+ }
420
+ if (j + 1 < source.length && source[j + 1] === "*") {
421
+ j += 2;
422
+ while (j + 1 < source.length) {
423
+ if (source[j] === "*" && source[j + 1] === "/") {
424
+ j += 2;
425
+ break;
426
+ }
427
+ j++;
428
+ }
429
+ continue;
430
+ }
431
+ }
432
+ if (c === "{") innerDepth++;
433
+ else if (c === "}") {
434
+ innerDepth--;
435
+ if (innerDepth === 0) {
436
+ return {
437
+ start,
438
+ end: j,
439
+ body: source.slice(start + 1, j)
440
+ };
441
+ }
442
+ }
443
+ j++;
444
+ }
445
+ return null;
446
+ }
447
+ depth--;
448
+ }
449
+ i--;
450
+ }
451
+ return null;
452
+ }
453
+ function isDynamicNonLiteral(attrs, name) {
454
+ const bound = attrs[`:${name}`];
455
+ if (bound === void 0) return false;
456
+ if (bound === "true" || bound === "false" || /^-?\d+$/.test(bound.trim())) return false;
457
+ return true;
458
+ }
459
+ function collectFromSource(source, usages) {
460
+ const rsIconTagPattern = /<RsIcon\b([\s\S]*?)\/?>/g;
461
+ let tagMatch;
462
+ while (tagMatch = rsIconTagPattern.exec(source)) {
463
+ const attrsSource = tagMatch[1] ?? "";
464
+ const attrs = parseStaticAttributes(attrsSource);
465
+ const jsxAttrs = parseJsxAttributes(attrsSource);
466
+ const rawName = attrs.name ?? attrs[":name"] ?? jsxAttrs.name;
467
+ const hasFamily = "family" in attrs || ":family" in attrs || "family" in jsxAttrs;
468
+ const rawFamily = attrs.family ?? attrs[":family"] ?? jsxAttrs.family ?? "";
469
+ const weight = jsxAttrs.weight ?? parseNumberAttr(attrs, "weight", DEFAULT_WEIGHT);
470
+ const resolvedWeight = weight > 0 ? weight : DEFAULT_WEIGHT;
471
+ const fill = parseBooleanAttr(attrs, attrsSource, "fill") || jsxAttrs.fill === true;
472
+ const grade = jsxAttrs.grade ?? parseNumberAttr(attrs, "grade", 0);
473
+ if (rawName) {
474
+ const isNameDynamic = ":name" in attrs || jsxAttrs.nameDynamic === true;
475
+ const familyList = resolveFamilies(rawFamily, hasFamily);
476
+ const names = resolveNames(rawName, isNameDynamic);
477
+ const isFillDynamic = isDynamicNonLiteral(attrs, "fill") || jsxAttrs.fillDynamic === true;
478
+ const isGradeDynamic = isDynamicNonLiteral(attrs, "grade") || jsxAttrs.gradeDynamic === true;
479
+ const isWeightDynamic = isDynamicNonLiteral(attrs, "weight") || jsxAttrs.weightDynamic === true;
480
+ const fills = isFillDynamic ? [false, true] : [fill];
481
+ const grades = isGradeDynamic ? [...GRADE_VARIANTS] : [grade];
482
+ const weights = isWeightDynamic ? [...VALID_WEIGHTS] : [resolvedWeight];
483
+ for (const family of familyList) {
484
+ for (const name of names) {
485
+ for (const g of grades) {
486
+ for (const f of fills) {
487
+ for (const w of weights) {
488
+ addUsage(usages, { family, name, grade: g, fill: f, weight: w });
489
+ }
490
+ }
491
+ }
492
+ }
493
+ }
494
+ }
495
+ }
496
+ const primeHelperPattern = /\brsPrimeIcon\(\s*["'`]([a-z0-9_]+)["'`](?:\s*,\s*\{([^)]*)\})?/g;
497
+ let helperMatch;
498
+ while (helperMatch = primeHelperPattern.exec(source)) {
499
+ const family = toFamily(helperMatch[2]?.match(/\bfamily\s*:\s*["'](\w+)["']/)?.[1]);
500
+ addUsage(usages, {
501
+ family: family ?? defaultFamily,
502
+ name: helperMatch[1] ?? ""
503
+ });
504
+ }
505
+ const objectIconPattern = /\bicon\s*:\s*["'`]([a-z0-9_]+)["'`]/g;
506
+ let objectMatch;
507
+ while (objectMatch = objectIconPattern.exec(source)) {
508
+ const name = objectMatch[1] ?? "";
509
+ const obj = findEnclosingObject(source, objectMatch.index);
510
+ if (obj) {
511
+ const cleanBody = obj.body.replace(/\/\/.*/g, "").replace(/\/\*[\s\S]*?\*\//g, "");
512
+ const weightMatch = cleanBody.match(/\bweight\s*:\s*(\d+)/);
513
+ const familyMatch = cleanBody.match(/\bfamily\s*:\s*["'](\w+)["']/);
514
+ const fillMatch = cleanBody.match(/\bfill\s*:\s*(true|false)/);
515
+ const gradeMatch = cleanBody.match(/\bgrade\s*:\s*(-?\d+)/);
516
+ addUsage(usages, {
517
+ family: familyMatch ? familyMatch[1] : defaultFamily,
518
+ name,
519
+ weight: weightMatch ? parseInt(weightMatch[1], 10) : void 0,
520
+ fill: fillMatch ? fillMatch[1] === "true" : void 0,
521
+ grade: gradeMatch ? parseInt(gradeMatch[1], 10) : void 0
522
+ });
523
+ } else {
524
+ addUsage(usages, { family: defaultFamily, name });
525
+ }
526
+ }
527
+ const magicCommentPattern = /(?:\/\/|\/\*)\s*@robosophy-icon:\s*([a-z0-9_]+)/g;
528
+ let magicMatch;
529
+ while (magicMatch = magicCommentPattern.exec(source)) {
530
+ const name = magicMatch[1] ?? "";
531
+ const lineEnd = source.indexOf("\n", magicMatch.index);
532
+ const line = lineEnd === -1 ? source.slice(magicMatch.index) : source.slice(magicMatch.index, lineEnd);
533
+ const familyMatch = line.match(/\bfamily\s*=\s*["']?(\w+)["']?/);
534
+ const weightMatch = line.match(/\bweight\s*=\s*(\d+)/);
535
+ const fillMatch = line.match(/\bfill\s*=\s*(true|false)/);
536
+ const gradeMatch = line.match(/\bgrade\s*=\s*(-?\d+)/);
537
+ addUsage(usages, {
538
+ family: familyMatch ? familyMatch[1] : defaultFamily,
539
+ name,
540
+ weight: weightMatch ? parseInt(weightMatch[1], 10) : void 0,
541
+ fill: fillMatch ? fillMatch[1] === "true" : void 0,
542
+ grade: gradeMatch ? parseInt(gradeMatch[1], 10) : void 0
543
+ });
544
+ }
545
+ const iconArrayPattern = /(?:const|let|var)\s+(\w*[Ii]con\w*)\s*=\s*\[/g;
546
+ let arrayMatch;
547
+ while (arrayMatch = iconArrayPattern.exec(source)) {
548
+ const bracketStart = arrayMatch.index + arrayMatch[0].length - 1;
549
+ let depth = 1;
550
+ let j = bracketStart + 1;
551
+ while (j < source.length) {
552
+ const c = source[j];
553
+ if (c === '"' || c === "'" || c === "`") {
554
+ j = skipStringForward(source, j, c);
555
+ continue;
556
+ }
557
+ if (c === "/") {
558
+ if (j + 1 < source.length && source[j + 1] === "/") {
559
+ j += 2;
560
+ while (j < source.length && source[j] !== "\n") j++;
561
+ continue;
562
+ }
563
+ if (j + 1 < source.length && source[j + 1] === "*") {
564
+ j += 2;
565
+ while (j + 1 < source.length) {
566
+ if (source[j] === "*" && source[j + 1] === "/") {
567
+ j += 2;
568
+ break;
569
+ }
570
+ j++;
571
+ }
572
+ continue;
573
+ }
574
+ }
575
+ if (c === "[") depth++;
576
+ else if (c === "]") {
577
+ depth--;
578
+ if (depth === 0) break;
579
+ }
580
+ j++;
581
+ }
582
+ if (depth === 0) {
583
+ const arrayContent = source.slice(bracketStart + 1, j);
584
+ let braceDepth = 0;
585
+ let bracketDepth = 0;
586
+ let k = 0;
587
+ while (k < arrayContent.length) {
588
+ const c = arrayContent[k];
589
+ if (c === '"' || c === "'" || c === "`") {
590
+ if (braceDepth === 0) {
591
+ const quote = c;
592
+ let strEnd = k + 1;
593
+ while (strEnd < arrayContent.length) {
594
+ if (arrayContent[strEnd] === "\\") {
595
+ strEnd += 2;
596
+ continue;
597
+ }
598
+ if (arrayContent[strEnd] === quote) break;
599
+ strEnd++;
600
+ }
601
+ const iconName = arrayContent.slice(k + 1, strEnd);
602
+ if (iconNamePattern.test(iconName) && !cssPropertyValues.has(iconName) && !/^\d/.test(iconName)) {
603
+ addUsage(usages, { family: defaultFamily, name: iconName });
604
+ }
605
+ k = strEnd + 1;
606
+ continue;
607
+ } else {
608
+ k = skipStringForward(arrayContent, k, c);
609
+ continue;
610
+ }
611
+ }
612
+ if (c === "{") braceDepth++;
613
+ else if (c === "}") braceDepth--;
614
+ else if (c === "[") bracketDepth++;
615
+ else if (c === "]") bracketDepth--;
616
+ k++;
617
+ }
618
+ }
619
+ }
620
+ const iconObjectPattern = /(?:const|let|var)\s+(\w*(?:[Ii]cons|[Ii]con(?:Map|List|Names?|Array|Set|Data|Items|Entries))\w*)[^=]*=\s*\{/g;
621
+ let objMatch;
622
+ while (objMatch = iconObjectPattern.exec(source)) {
623
+ const braceStart = objMatch.index + objMatch[0].length - 1;
624
+ let depth = 1;
625
+ let j = braceStart + 1;
626
+ while (j < source.length) {
627
+ const c = source[j];
628
+ if (c === '"' || c === "'" || c === "`") {
629
+ j = skipStringForward(source, j, c);
630
+ continue;
631
+ }
632
+ if (c === "/") {
633
+ if (j + 1 < source.length && source[j + 1] === "/") {
634
+ j += 2;
635
+ while (j < source.length && source[j] !== "\n") j++;
636
+ continue;
637
+ }
638
+ if (j + 1 < source.length && source[j + 1] === "*") {
639
+ j += 2;
640
+ while (j + 1 < source.length) {
641
+ if (source[j] === "*" && source[j + 1] === "/") {
642
+ j += 2;
643
+ break;
644
+ }
645
+ j++;
646
+ }
647
+ continue;
648
+ }
649
+ }
650
+ if (c === "{") depth++;
651
+ else if (c === "}") {
652
+ depth--;
653
+ if (depth === 0) break;
654
+ }
655
+ j++;
656
+ }
657
+ if (depth === 0) {
658
+ const bodyContent = source.slice(braceStart + 1, j);
659
+ let braceDepth = 0;
660
+ let k = 0;
661
+ while (k < bodyContent.length) {
662
+ const c = bodyContent[k];
663
+ if (c === '"' || c === "'" || c === "`") {
664
+ if (braceDepth === 0) {
665
+ const quote = c;
666
+ let strEnd = k + 1;
667
+ while (strEnd < bodyContent.length) {
668
+ if (bodyContent[strEnd] === "\\") {
669
+ strEnd += 2;
670
+ continue;
671
+ }
672
+ if (bodyContent[strEnd] === quote) break;
673
+ strEnd++;
674
+ }
675
+ const iconName = bodyContent.slice(k + 1, strEnd);
676
+ if (iconNamePattern.test(iconName) && !cssPropertyValues.has(iconName) && !/^\d/.test(iconName)) {
677
+ addUsage(usages, { family: defaultFamily, name: iconName });
678
+ }
679
+ k = strEnd + 1;
680
+ continue;
681
+ } else {
682
+ k = skipStringForward(bodyContent, k, c);
683
+ continue;
684
+ }
685
+ }
686
+ if (c === "{") braceDepth++;
687
+ else if (c === "}") braceDepth--;
688
+ k++;
689
+ }
690
+ }
691
+ }
692
+ const componentIconPattern = /<([A-Z][a-zA-Z0-9_]*)\b([\s\S]*?)\/?>/g;
693
+ let compMatch;
694
+ while (compMatch = componentIconPattern.exec(source)) {
695
+ const tagName = compMatch[1];
696
+ if (tagName === "RsIcon") continue;
697
+ const attrs = parseStaticAttributes(compMatch[2] ?? "");
698
+ const jsxAttrs = parseJsxAttributes(compMatch[2] ?? "");
699
+ const iconValue = attrs.icon ?? attrs.iconName ?? attrs["icon-name"];
700
+ if (iconValue && iconNamePattern.test(iconValue)) {
701
+ addUsage(usages, { family: defaultFamily, name: iconValue });
702
+ }
703
+ }
704
+ }
705
+ async function readAllSources(roots) {
706
+ const sources = /* @__PURE__ */ new Map();
707
+ for (const root of roots) {
708
+ for (const filePath of await listSourceFiles(root)) {
709
+ if (!sources.has(filePath)) {
710
+ sources.set(filePath, await readFile(filePath, "utf8"));
711
+ }
712
+ }
713
+ }
714
+ return sources;
715
+ }
716
+ function findIconProxyComponents(sources) {
717
+ const proxyComponents = /* @__PURE__ */ new Map();
718
+ for (const source of sources.values()) {
719
+ const explicitProxyPattern = /\/\/\s*@robosophy-icon-proxy:\s*([A-Z][a-zA-Z0-9_]*)\s+([a-zA-Z_][a-zA-Z0-9_]*)/g;
720
+ let explicitMatch;
721
+ while (explicitMatch = explicitProxyPattern.exec(source)) {
722
+ proxyComponents.set(explicitMatch[1], explicitMatch[2]);
723
+ }
724
+ const rsIconPattern = /<RsIcon[^>]*?name\s*=\s*\{([a-zA-Z_][a-zA-Z0-9_]*)\}/g;
725
+ let match;
726
+ while (match = rsIconPattern.exec(source)) {
727
+ const internalVarName = match[1];
728
+ const rsIconPos = match.index;
729
+ const sourceBefore = source.slice(0, rsIconPos);
730
+ const componentDefs = [];
731
+ const funcPattern = /function\s+([A-Z][a-zA-Z0-9_]*)\s*\(([^)]*)\)/g;
732
+ let funcMatch;
733
+ while (funcMatch = funcPattern.exec(sourceBefore)) {
734
+ componentDefs.push({ name: funcMatch[1], pos: funcMatch.index, isDefault: false, params: funcMatch[2] ?? "" });
735
+ }
736
+ const constPattern = /const\s+([A-Z][a-zA-Z0-9_]*)\s*=\s*(?:function\s*\(([^)]*)\)|forwardRef\s*\(([^)]*)\)|\(([^)]*)\))/g;
737
+ let constMatch;
738
+ while (constMatch = constPattern.exec(sourceBefore)) {
739
+ const params = constMatch[2] ?? constMatch[3] ?? constMatch[4] ?? "";
740
+ componentDefs.push({ name: constMatch[1], pos: constMatch.index, isDefault: false, params });
741
+ }
742
+ const defaultExportPattern = /export\s+default\s+(?:function\s+)?([A-Z][a-zA-Z0-9_]*)/;
743
+ const defaultMatch = source.match(defaultExportPattern);
744
+ if (defaultMatch) {
745
+ const defaultName = defaultMatch[1];
746
+ const def = componentDefs.find((d) => d.name === defaultName);
747
+ if (def) {
748
+ def.isDefault = true;
749
+ }
750
+ }
751
+ if (componentDefs.length > 0) {
752
+ componentDefs.sort((a, b) => b.pos - a.pos);
753
+ const defaultExport = componentDefs.find((d) => d.isDefault);
754
+ const closestComponent = defaultExport ?? componentDefs[0];
755
+ const resolvedProp = resolvePropFromDestructuring(closestComponent.params, internalVarName);
756
+ if (resolvedProp) {
757
+ proxyComponents.set(closestComponent.name, resolvedProp);
758
+ }
759
+ }
760
+ }
761
+ }
762
+ return proxyComponents;
763
+ }
764
+ function resolvePropFromDestructuring(params, internalVarName) {
765
+ const trimmed = params.trim();
766
+ if (!trimmed) return null;
767
+ if (!trimmed.startsWith("{")) return null;
768
+ const braceEnd = findMatchingBrace(trimmed, 0);
769
+ if (braceEnd === -1) return null;
770
+ const body = trimmed.slice(1, braceEnd);
771
+ const aliasPattern = new RegExp(
772
+ `\\b([a-zA-Z_][a-zA-Z0-9_]*)\\s*:\\s*${escapeRegex(internalVarName)}\\b`
773
+ );
774
+ const aliasMatch = body.match(aliasPattern);
775
+ if (aliasMatch) return aliasMatch[1] ?? null;
776
+ const shorthandPattern = new RegExp(`\\b${escapeRegex(internalVarName)}\\b`);
777
+ if (shorthandPattern.test(body)) return internalVarName;
778
+ return null;
779
+ }
780
+ function findMatchingBrace(s, start) {
781
+ let depth = 0;
782
+ for (let i = start; i < s.length; i++) {
783
+ if (s[i] === "{") depth++;
784
+ else if (s[i] === "}") {
785
+ depth--;
786
+ if (depth === 0) return i;
787
+ }
788
+ }
789
+ return -1;
790
+ }
791
+ function escapeRegex(s) {
792
+ return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
793
+ }
794
+ function collectProxyIconUsages(source, proxyComponents, usages) {
795
+ for (const [compName, propName] of proxyComponents) {
796
+ const pattern = new RegExp(
797
+ `<${compName}\\b([\\s\\S]*?)>`,
798
+ "g"
799
+ );
800
+ let tagMatch;
801
+ while (tagMatch = pattern.exec(source)) {
802
+ const attrs = parseStaticAttributes(tagMatch[1] ?? "");
803
+ const value = attrs[propName];
804
+ if (value && iconNamePattern.test(value)) {
805
+ addUsage(usages, { family: defaultFamily, name: value });
806
+ }
807
+ }
808
+ }
809
+ }
810
+ function parseBooleanAttr(attrs, raw, name) {
811
+ const bound = attrs[`:${name}`];
812
+ if (bound === "false") return false;
813
+ if (bound === "true" || bound === "") return true;
814
+ const staticVal = attrs[name];
815
+ if (staticVal === "false") return false;
816
+ if (staticVal === "true" || staticVal === "") return true;
817
+ return new RegExp(`(?:^|\\s)${name}(?:\\s|$|(?==))`).test(raw);
818
+ }
819
+ function parseNumberAttr(attrs, name, fallback) {
820
+ const raw = attrs[name] ?? attrs[`:${name}`] ?? "";
821
+ const parsed = parseInt(raw, 10);
822
+ return !isNaN(parsed) ? parsed : fallback;
823
+ }
824
+ function parseStaticAttributes(source) {
825
+ const attrs = {};
826
+ const attrPattern = /([:@\w-]+)\s*=\s*(?:"([^"]*)"|'([^']*)')/g;
827
+ let match;
828
+ while (match = attrPattern.exec(source)) {
829
+ attrs[match[1] ?? ""] = match[2] ?? match[3] ?? "";
830
+ }
831
+ return attrs;
832
+ }
833
+ function parseJsxAttributes(source) {
834
+ const result = {};
835
+ const nameStaticMatch = source.match(/\bname\s*=\s*["']([a-z0-9_]+)["']/i);
836
+ if (nameStaticMatch) {
837
+ result.name = nameStaticMatch[1];
838
+ }
839
+ const nameDynamicMatch = source.match(/\bname\s*=\s*\{([^}]+)\}/);
840
+ if (nameDynamicMatch) {
841
+ const value = nameDynamicMatch[1]?.trim() ?? "";
842
+ const stringLiteralMatch = value.match(/^["'`]([a-z0-9_]+)["'`]$/);
843
+ if (stringLiteralMatch) {
844
+ result.name = stringLiteralMatch[1];
845
+ } else {
846
+ const ternaryStrings = value.match(/["'`]([a-z0-9_]+)["'`]/g);
847
+ if (ternaryStrings && ternaryStrings.length > 0) {
848
+ const names = ternaryStrings.map((s) => s.replace(/^["'`]|["'`]$/g, "")).filter((n) => iconNamePattern.test(n));
849
+ if (names.length > 0) {
850
+ result.name = names.join("|");
851
+ } else {
852
+ result.nameDynamic = true;
853
+ }
854
+ } else {
855
+ result.nameDynamic = true;
856
+ }
857
+ }
858
+ }
859
+ const familyStaticMatch = source.match(/\bfamily\s*=\s*["'](\w+)["']/);
860
+ if (familyStaticMatch) {
861
+ result.family = familyStaticMatch[1];
862
+ } else {
863
+ const familyDynamicMatch = source.match(/\bfamily\s*=\s*\{([^}]+)\}/);
864
+ if (familyDynamicMatch) {
865
+ const value = familyDynamicMatch[1]?.trim() ?? "";
866
+ const stringLiteralMatch = value.match(/^["'](\w+)["']$/);
867
+ if (stringLiteralMatch) {
868
+ result.family = stringLiteralMatch[1];
869
+ } else {
870
+ const ternaryStrings = value.match(/["'`](\w+)["'`]/g);
871
+ if (ternaryStrings && ternaryStrings.length > 0) {
872
+ const familyValues = ternaryStrings.map((s) => s.replace(/^["'`]|["'`]$/g, "")).filter((f) => families.includes(f));
873
+ if (familyValues.length > 0) {
874
+ result.family = familyValues.join("|");
875
+ } else {
876
+ result.family = "__dynamic__";
877
+ }
878
+ } else {
879
+ result.family = "__dynamic__";
880
+ }
881
+ }
882
+ }
883
+ }
884
+ const fillMatch = source.match(/\bfill\s*=\s*\{?(true|false)\}?/);
885
+ if (fillMatch) {
886
+ result.fill = fillMatch[1] === "true";
887
+ } else if (/\bfill\s*=\s*\{[^}]*\}/.test(source)) {
888
+ result.fillDynamic = true;
889
+ } else if (/\bfill\b/.test(source) && !/\bfill\s*=/.test(source)) {
890
+ result.fill = true;
891
+ }
892
+ const weightMatch = source.match(/\bweight\s*=\s*\{(-?\d+)\}/);
893
+ if (weightMatch) {
894
+ result.weight = parseInt(weightMatch[1] ?? "", 10);
895
+ } else if (/\bweight\s*=\s*\{[^}]*\}/.test(source)) {
896
+ result.weightDynamic = true;
897
+ }
898
+ const gradeMatch = source.match(/\bgrade\s*=\s*\{(-?\d+)\}/);
899
+ if (gradeMatch) {
900
+ result.grade = parseInt(gradeMatch[1] ?? "", 10);
901
+ } else if (/\bgrade\s*=\s*\{[^}]*\}/.test(source)) {
902
+ result.gradeDynamic = true;
903
+ }
904
+ return result;
905
+ }
906
+ function unwrapStaticValue(value) {
907
+ return value.replace(/^['"`](.+)['"`]$/, "$1");
908
+ }
909
+ var VALID_WEIGHTS = [100, 200, 300, 400, 500, 600, 700];
910
+ function addUsage(usages, icon) {
911
+ const family = icon.family ?? defaultFamily;
912
+ const name = icon.name.trim();
913
+ const weight = icon.weight ?? DEFAULT_WEIGHT;
914
+ const fill = icon.fill ?? false;
915
+ const grade = icon.grade ?? 0;
916
+ if (!families.includes(family) || !iconNamePattern.test(name)) {
917
+ return;
918
+ }
919
+ if (!VALID_WEIGHTS.includes(weight)) return;
920
+ const iconMap = usages.get(family);
921
+ if (!iconMap) return;
922
+ const key = variantKey(grade, fill, weight);
923
+ const existing = iconMap.get(name);
924
+ if (existing) {
925
+ existing.add(key);
926
+ } else {
927
+ iconMap.set(name, /* @__PURE__ */ new Set([key]));
928
+ }
929
+ }
930
+ async function loadIconManifest() {
931
+ try {
932
+ const dir = join(fileURLToPath(import.meta.url), "..");
933
+ const manifestPath = join(dir, "icon-manifest.json");
934
+ const source = await readFile(manifestPath, "utf8");
935
+ return JSON.parse(source);
936
+ } catch {
937
+ return null;
938
+ }
939
+ }
940
+ function toFamily(value) {
941
+ const normalized = value ? unwrapStaticValue(value) : "";
942
+ return families.includes(normalized) ? normalized : void 0;
943
+ }
944
+ function resolveNames(rawName, isDynamic = false) {
945
+ if (rawName.includes("|")) {
946
+ const parts = rawName.split("|").map((p) => p.trim());
947
+ const validNames = parts.filter((p) => iconNamePattern.test(p));
948
+ if (validNames.length > 0) return validNames;
949
+ }
950
+ const stringLiterals = /["'`]([a-z0-9_]+)["'`]/g;
951
+ let strMatch;
952
+ const names = [];
953
+ while (strMatch = stringLiterals.exec(rawName)) {
954
+ const candidate = strMatch[1] ?? "";
955
+ if (iconNamePattern.test(candidate)) {
956
+ names.push(candidate);
957
+ }
958
+ }
959
+ if (names.length === 0) {
960
+ if (isDynamic) return names;
961
+ const name = unwrapStaticValue(rawName);
962
+ if (iconNamePattern.test(name)) {
963
+ names.push(name);
964
+ }
965
+ }
966
+ return names;
967
+ }
968
+ function resolveFamilies(rawFamily, hasFamily = true) {
969
+ if (rawFamily === "__dynamic__") return [...families];
970
+ if (rawFamily.includes("|")) {
971
+ const parts = rawFamily.split("|").map((p) => p.trim());
972
+ const validFamilies = parts.filter(
973
+ (p) => families.includes(p)
974
+ );
975
+ if (validFamilies.length > 0) return validFamilies;
976
+ }
977
+ const family = toFamily(rawFamily);
978
+ if (family) return [family];
979
+ const stringLiterals = /["'`](\w+)["'`]/g;
980
+ let strMatch;
981
+ const found = /* @__PURE__ */ new Set();
982
+ while (strMatch = stringLiterals.exec(rawFamily)) {
983
+ const candidate = strMatch[1] ?? "";
984
+ const f = toFamily(candidate);
985
+ if (f) {
986
+ found.add(f);
987
+ }
988
+ }
989
+ if (found.size > 0) return [...found];
990
+ if (!hasFamily) return [defaultFamily];
991
+ return [...families];
992
+ }
993
+ function createUsageMap() {
994
+ return new Map(families.map((family) => [family, /* @__PURE__ */ new Map()]));
995
+ }
996
+ async function listSourceFiles(root) {
997
+ try {
998
+ const entries = await readdir(root, { withFileTypes: true });
999
+ const files = await Promise.all(
1000
+ entries.map(async (entry) => {
1001
+ const path = join(root, entry.name);
1002
+ if (entry.isDirectory()) {
1003
+ return skippedDirs.has(entry.name) ? [] : listSourceFiles(path);
1004
+ }
1005
+ return sourceExtensions.has(extname(entry.name)) ? [path] : [];
1006
+ })
1007
+ );
1008
+ return files.flat();
1009
+ } catch {
1010
+ return [];
1011
+ }
1012
+ }
1013
+ function formatDetectedMaterialSymbols(usages) {
1014
+ return families.map((family) => {
1015
+ const iconVariants = usages.get(family);
1016
+ if (!iconVariants || iconVariants.size === 0) return `${family}: (none)`;
1017
+ const entries = [...iconVariants.entries()].map(([name, variants]) => `${name}[${[...variants].sort().join(";")}]`).sort().join(", ");
1018
+ return `${family}: ${entries}`;
1019
+ }).join("\n");
1020
+ }
1021
+ export {
1022
+ buildMaterialSymbolsCss,
1023
+ collectMaterialSymbolUsages,
1024
+ formatDetectedMaterialSymbols,
1025
+ robosophyMaterialSymbols
1026
+ };