@cristianormazabal/triton-core 0.1.14 → 0.1.16

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.
Files changed (55) hide show
  1. package/dist/contracts/anchors.d.ts +6 -0
  2. package/dist/contracts/anchors.d.ts.map +1 -1
  3. package/dist/contracts/icons.d.ts +228 -0
  4. package/dist/contracts/icons.d.ts.map +1 -0
  5. package/dist/contracts/icons.js +28 -0
  6. package/dist/contracts/icons.js.map +1 -0
  7. package/dist/contracts/index.d.ts +2 -1
  8. package/dist/contracts/index.d.ts.map +1 -1
  9. package/dist/contracts/index.js.map +1 -1
  10. package/dist/contracts/result.d.ts +1 -1
  11. package/dist/contracts/result.d.ts.map +1 -1
  12. package/dist/contracts/result.js.map +1 -1
  13. package/dist/contracts/scene.d.ts +47 -1
  14. package/dist/contracts/scene.d.ts.map +1 -1
  15. package/dist/diagrams/mermaid/flowchart/index.d.ts.map +1 -1
  16. package/dist/diagrams/mermaid/flowchart/index.js +19 -1
  17. package/dist/diagrams/mermaid/flowchart/index.js.map +1 -1
  18. package/dist/diagrams/mermaid/flowchart/ir.d.ts +4 -1
  19. package/dist/diagrams/mermaid/flowchart/ir.d.ts.map +1 -1
  20. package/dist/diagrams/mermaid/flowchart/layout.d.ts.map +1 -1
  21. package/dist/diagrams/mermaid/flowchart/layout.js +177 -19
  22. package/dist/diagrams/mermaid/flowchart/layout.js.map +1 -1
  23. package/dist/diagrams/triton/ds/queue/shared.js +2 -0
  24. package/dist/diagrams/triton/ds/queue/shared.js.map +1 -1
  25. package/dist/diagrams/triton/ds/struct/array.d.ts.map +1 -1
  26. package/dist/diagrams/triton/ds/struct/array.js +2 -0
  27. package/dist/diagrams/triton/ds/struct/array.js.map +1 -1
  28. package/dist/frontend/index.d.ts +4 -3
  29. package/dist/frontend/index.d.ts.map +1 -1
  30. package/dist/frontend/index.js +7 -6
  31. package/dist/frontend/index.js.map +1 -1
  32. package/dist/icons/discover.d.ts +51 -0
  33. package/dist/icons/discover.d.ts.map +1 -0
  34. package/dist/icons/discover.js +124 -0
  35. package/dist/icons/discover.js.map +1 -0
  36. package/dist/icons/resolver.d.ts +84 -0
  37. package/dist/icons/resolver.d.ts.map +1 -0
  38. package/dist/icons/resolver.js +226 -0
  39. package/dist/icons/resolver.js.map +1 -0
  40. package/dist/icons/validate.d.ts +36 -0
  41. package/dist/icons/validate.d.ts.map +1 -0
  42. package/dist/icons/validate.js +257 -0
  43. package/dist/icons/validate.js.map +1 -0
  44. package/dist/index.js +1150 -492
  45. package/dist/index.js.map +4 -4
  46. package/dist/overlay/layout.js +2 -0
  47. package/dist/overlay/layout.js.map +1 -1
  48. package/dist/render/svg.d.ts.map +1 -1
  49. package/dist/render/svg.js +104 -0
  50. package/dist/render/svg.js.map +1 -1
  51. package/dist/scene/build.d.ts +16 -1
  52. package/dist/scene/build.d.ts.map +1 -1
  53. package/dist/scene/build.js +7 -0
  54. package/dist/scene/build.js.map +1 -1
  55. package/package.json +1 -1
@@ -0,0 +1,226 @@
1
+ /**
2
+ * Icon resolution — pure, no I/O.
3
+ *
4
+ * Three exported functions:
5
+ *
6
+ * parseIconRef(token) — parse "prefix:name" → Result<IconRef>
7
+ * resolveIcon(ref, packs) — resolve IconRef against IconPackMap → Result<ResolvedIcon>
8
+ * detectColorMode(body) — classify body as 'monochrome' | 'brand'
9
+ *
10
+ * All functions are pure: they take data in and return data out.
11
+ * No filesystem access, no network, no process.
12
+ *
13
+ * ViewBox merge order (highest priority first):
14
+ * 1. Alias-level dimension overrides (if the reference was an alias)
15
+ * 2. Icon-level dimension overrides
16
+ * 3. Pack-level dimension defaults
17
+ * 4. System defaults: width=16, height=16, left=0, top=0
18
+ *
19
+ * Transform composition (alias-level on top of icon-level):
20
+ * rotate : (aliasRotate + iconRotate) mod 4
21
+ * hFlip : aliasHFlip XOR iconHFlip
22
+ * vFlip : aliasVFlip XOR iconVFlip
23
+ *
24
+ * Color-mode detection heuristic (precise, documented):
25
+ * Scan body for fill="..." and stroke="..." attribute values.
26
+ * If any value is not in {none, currentColor, inherit} → brand.
27
+ * If body contains <linearGradient or <radialGradient → brand.
28
+ * Otherwise → monochrome.
29
+ *
30
+ * Alias depth limit: MAX_ALIAS_DEPTH (4) to prevent infinite loops.
31
+ */
32
+ import { ok, err } from '../contracts/result.js';
33
+ // ─── Token grammar ────────────────────────────────────────────────────────────
34
+ /**
35
+ * Valid prefix: starts with a lowercase letter, followed by lowercase alnum or hyphens.
36
+ * Examples: "azure", "mdi", "my-pack"
37
+ */
38
+ const PREFIX_RE = /^[a-z][a-z0-9-]*$/;
39
+ /**
40
+ * Valid name: starts with lowercase alnum, followed by lowercase alnum or hyphens.
41
+ * Examples: "app-service", "server", "12px" (unusual but valid per grammar)
42
+ */
43
+ const NAME_RE = /^[a-z0-9][a-z0-9-]*$/;
44
+ // ─── System defaults ──────────────────────────────────────────────────────────
45
+ const DEFAULT_WIDTH = 16;
46
+ const DEFAULT_HEIGHT = 16;
47
+ const DEFAULT_LEFT = 0;
48
+ const DEFAULT_TOP = 0;
49
+ /** Maximum alias chain depth. Prevents infinite loops from circular aliases. */
50
+ const MAX_ALIAS_DEPTH = 4;
51
+ // ─── parseIconRef ─────────────────────────────────────────────────────────────
52
+ /**
53
+ * Parse an icon token string of the form "prefix:name" into an IconRef.
54
+ *
55
+ * Valid: "azure:app-service", "mdi:server", "lucide:0-circle"
56
+ * Invalid: "no-colon", ":name" (empty prefix), "prefix:" (empty name),
57
+ * "Azure:App" (uppercase), "prefix:name:extra" (too many colons)
58
+ *
59
+ * Returns err(ICON_NOT_FOUND, ...) on parse failure (not ICON_VALIDATION_ERROR
60
+ * since this is a reference parse, not a pack-structure validation).
61
+ */
62
+ export function parseIconRef(token) {
63
+ if (typeof token !== 'string' || token.length === 0) {
64
+ return err('ICON_NOT_FOUND', `Icon token must be a non-empty string, got ${JSON.stringify(token)}`);
65
+ }
66
+ const colonIdx = token.indexOf(':');
67
+ if (colonIdx === -1) {
68
+ return err('ICON_NOT_FOUND', `Invalid icon token ${JSON.stringify(token)}: must be "prefix:name"`);
69
+ }
70
+ // Only one colon allowed
71
+ if (token.indexOf(':', colonIdx + 1) !== -1) {
72
+ return err('ICON_NOT_FOUND', `Invalid icon token ${JSON.stringify(token)}: too many colons — expected "prefix:name"`);
73
+ }
74
+ const prefix = token.slice(0, colonIdx);
75
+ const name = token.slice(colonIdx + 1);
76
+ if (!PREFIX_RE.test(prefix)) {
77
+ return err('ICON_NOT_FOUND', `Invalid icon token ${JSON.stringify(token)}: prefix ${JSON.stringify(prefix)} must match ^[a-z][a-z0-9-]*$`);
78
+ }
79
+ if (!NAME_RE.test(name)) {
80
+ return err('ICON_NOT_FOUND', `Invalid icon token ${JSON.stringify(token)}: name ${JSON.stringify(name)} must match ^[a-z0-9][a-z0-9-]*$`);
81
+ }
82
+ return ok({ prefix, name });
83
+ }
84
+ // ─── detectColorMode ──────────────────────────────────────────────────────────
85
+ /**
86
+ * Classify an icon body as 'monochrome' or 'brand'.
87
+ *
88
+ * Heuristic (precise):
89
+ * 1. Scan body for fill="..." and stroke="..." attribute values.
90
+ * If any value is not one of {none, currentColor, inherit} → brand.
91
+ * 2. If body contains "<linearGradient" or "<radialGradient" → brand.
92
+ * 3. Otherwise → monochrome.
93
+ *
94
+ * Rationale:
95
+ * Monochrome icons (MDI, Lucide, Heroicons) use only fill="currentColor" or
96
+ * fill="none", allowing the renderer to tint them via CSS color inheritance.
97
+ * Brand icons (Azure architecture icons, logos) embed hardcoded hex fills
98
+ * and/or gradient definitions that must render verbatim.
99
+ *
100
+ * The gradient check is necessary because some icons use fill="url(#grad1)"
101
+ * which would pass the fill-value check but still requires brand rendering.
102
+ *
103
+ * Note: this is a string scan heuristic, not a full SVG parser. It handles
104
+ * well-formed IconifyJSON bodies as produced by @iconify/tools. Pathological
105
+ * bodies with fill/stroke in non-attribute contexts (e.g. CSS text) could
106
+ * produce false positives, but this is acceptable for the BYOP use case.
107
+ */
108
+ export function detectColorMode(body) {
109
+ // Gradient definitions always → brand
110
+ if (body.includes('<linearGradient') || body.includes('<radialGradient')) {
111
+ return 'brand';
112
+ }
113
+ // Scan fill="..." and stroke="..." attribute values
114
+ // Match: fill="value" or stroke="value" (handles single/double quotes)
115
+ const ATTR_RE = /(?:fill|stroke)=["']([^"']+)["']/g;
116
+ const NEUTRAL = new Set(['none', 'currentcolor', 'inherit']);
117
+ let match;
118
+ while ((match = ATTR_RE.exec(body)) !== null) {
119
+ const value = match[1];
120
+ if (value === undefined)
121
+ continue;
122
+ // Normalize to lowercase for case-insensitive comparison
123
+ const lower = value.toLowerCase();
124
+ if (!NEUTRAL.has(lower)) {
125
+ return 'brand';
126
+ }
127
+ }
128
+ return 'monochrome';
129
+ }
130
+ function mergeViewBox(aliasLevel, iconLevel, packLevel) {
131
+ return {
132
+ width: aliasLevel.width ?? iconLevel.width ?? packLevel.width ?? DEFAULT_WIDTH,
133
+ height: aliasLevel.height ?? iconLevel.height ?? packLevel.height ?? DEFAULT_HEIGHT,
134
+ left: aliasLevel.left ?? iconLevel.left ?? packLevel.left ?? DEFAULT_LEFT,
135
+ top: aliasLevel.top ?? iconLevel.top ?? packLevel.top ?? DEFAULT_TOP,
136
+ };
137
+ }
138
+ // ─── Internal: transform composition ─────────────────────────────────────────
139
+ function composeTransforms(icon, alias) {
140
+ const iconRotate = icon.rotate ?? 0;
141
+ const iconHFlip = icon.hFlip ?? false;
142
+ const iconVFlip = icon.vFlip ?? false;
143
+ if (alias === null) {
144
+ return {
145
+ rotate: iconRotate,
146
+ hFlip: iconHFlip,
147
+ vFlip: iconVFlip,
148
+ };
149
+ }
150
+ const aliasRotate = alias.rotate ?? 0;
151
+ const aliasHFlip = alias.hFlip ?? false;
152
+ const aliasVFlip = alias.vFlip ?? false;
153
+ return {
154
+ rotate: ((iconRotate + aliasRotate) % 4),
155
+ hFlip: iconHFlip !== aliasHFlip, // XOR
156
+ vFlip: iconVFlip !== aliasVFlip, // XOR
157
+ };
158
+ }
159
+ // ─── resolveIcon ─────────────────────────────────────────────────────────────
160
+ /**
161
+ * Resolve an IconRef against an IconPackMap to produce a ResolvedIcon.
162
+ *
163
+ * Resolution steps:
164
+ * 1. Look up the pack by ref.prefix. → ICON_NOT_FOUND if absent.
165
+ * 2. Look for ref.name in pack.icons. If found, use it directly.
166
+ * 3. Else look in pack.aliases. Follow the alias chain up to MAX_ALIAS_DEPTH.
167
+ * → ICON_NOT_FOUND if name not in icons or aliases, or chain too deep.
168
+ * 4. Merge viewBox dimensions: alias-level → icon-level → pack-level → defaults.
169
+ * 5. Compose transforms: alias-level on top of icon-level.
170
+ * 6. Detect colorMode from the resolved body.
171
+ *
172
+ * Pure — never throws, never touches the filesystem.
173
+ */
174
+ export function resolveIcon(ref, packs) {
175
+ const pack = packs.get(ref.prefix);
176
+ if (pack === undefined) {
177
+ return err('ICON_NOT_FOUND', `Icon pack "${ref.prefix}" not loaded (looking up "${ref.prefix}:${ref.name}")`);
178
+ }
179
+ // Try direct icon lookup first
180
+ const directIcon = pack.icons[ref.name];
181
+ if (directIcon !== undefined) {
182
+ const viewBox = mergeViewBox({}, directIcon, pack);
183
+ const transforms = composeTransforms(directIcon, null);
184
+ return ok({
185
+ body: directIcon.body,
186
+ viewBox,
187
+ transforms,
188
+ colorMode: detectColorMode(directIcon.body),
189
+ });
190
+ }
191
+ // Try alias lookup
192
+ const aliases = pack.aliases;
193
+ if (aliases === undefined || !(ref.name in aliases)) {
194
+ return err('ICON_NOT_FOUND', `Icon "${ref.name}" not found in pack "${ref.prefix}" (checked icons and aliases)`);
195
+ }
196
+ // Follow alias chain, accumulating the first alias's transform/dim overrides
197
+ let currentName = ref.name;
198
+ let currentAlias = aliases[ref.name] ?? null;
199
+ const topAlias = currentAlias; // preserve top-level alias for dim/transform composition
200
+ for (let depth = 0; depth < MAX_ALIAS_DEPTH; depth++) {
201
+ if (currentAlias === null)
202
+ break;
203
+ const parentName = currentAlias.parent;
204
+ const parentIcon = pack.icons[parentName];
205
+ if (parentIcon !== undefined) {
206
+ // Found the base icon — compose transforms and merge viewBox
207
+ const viewBox = mergeViewBox(topAlias ?? {}, parentIcon, pack);
208
+ const transforms = composeTransforms(parentIcon, topAlias);
209
+ return ok({
210
+ body: parentIcon.body,
211
+ viewBox,
212
+ transforms,
213
+ colorMode: detectColorMode(parentIcon.body),
214
+ });
215
+ }
216
+ // Parent is itself an alias — follow one more level
217
+ const parentAlias = aliases[parentName];
218
+ if (parentAlias === undefined) {
219
+ return err('ICON_NOT_FOUND', `Alias "${currentName}" in pack "${ref.prefix}" points to parent "${parentName}" which does not exist`);
220
+ }
221
+ currentName = parentName;
222
+ currentAlias = parentAlias;
223
+ }
224
+ return err('ICON_NOT_FOUND', `Alias chain for "${ref.name}" in pack "${ref.prefix}" exceeds maximum depth of ${MAX_ALIAS_DEPTH}`);
225
+ }
226
+ //# sourceMappingURL=resolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolver.js","sourceRoot":"","sources":["../../../../src/icons/resolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAaH,OAAO,EAAE,EAAE,EAAE,GAAG,EAAe,MAAM,wBAAwB,CAAC;AAE9D,iFAAiF;AAEjF;;;GAGG;AACH,MAAM,SAAS,GAAG,mBAAmB,CAAC;AAEtC;;;GAGG;AACH,MAAM,OAAO,GAAG,sBAAsB,CAAC;AAEvC,iFAAiF;AAEjF,MAAM,aAAa,GAAI,EAAE,CAAC;AAC1B,MAAM,cAAc,GAAG,EAAE,CAAC;AAC1B,MAAM,YAAY,GAAK,CAAC,CAAC;AACzB,MAAM,WAAW,GAAM,CAAC,CAAC;AAEzB,gFAAgF;AAChF,MAAM,eAAe,GAAG,CAAC,CAAC;AAE1B,iFAAiF;AAEjF;;;;;;;;;GASG;AACH,MAAM,UAAU,YAAY,CAAC,KAAa;IACxC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACpD,OAAO,GAAG,CAAC,gBAAgB,EAAE,8CAA8C,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACtG,CAAC;IAED,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACpC,IAAI,QAAQ,KAAK,CAAC,CAAC,EAAE,CAAC;QACpB,OAAO,GAAG,CAAC,gBAAgB,EAAE,sBAAsB,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,yBAAyB,CAAC,CAAC;IACrG,CAAC;IAED,yBAAyB;IACzB,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;QAC5C,OAAO,GAAG,CACR,gBAAgB,EAChB,sBAAsB,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,4CAA4C,CACxF,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;IACxC,MAAM,IAAI,GAAK,KAAK,CAAC,KAAK,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC;IAEzC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QAC5B,OAAO,GAAG,CACR,gBAAgB,EAChB,sBAAsB,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,YAAY,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,+BAA+B,CAC7G,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACxB,OAAO,GAAG,CACR,gBAAgB,EAChB,sBAAsB,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,UAAU,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,kCAAkC,CAC5G,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;AAC9B,CAAC;AAED,iFAAiF;AAEjF;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,UAAU,eAAe,CAAC,IAAY;IAC1C,sCAAsC;IACtC,IAAI,IAAI,CAAC,QAAQ,CAAC,iBAAiB,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,CAAC;QACzE,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,oDAAoD;IACpD,uEAAuE;IACvE,MAAM,OAAO,GAAG,mCAAmC,CAAC;IACpD,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,CAAC,MAAM,EAAE,cAAc,EAAE,SAAS,CAAC,CAAC,CAAC;IAE7D,IAAI,KAA6B,CAAC;IAClC,OAAO,CAAC,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QAC7C,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACvB,IAAI,KAAK,KAAK,SAAS;YAAE,SAAS;QAClC,yDAAyD;QACzD,MAAM,KAAK,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;QAClC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;YACxB,OAAO,OAAO,CAAC;QACjB,CAAC;IACH,CAAC;IAED,OAAO,YAAY,CAAC;AACtB,CAAC;AAWD,SAAS,YAAY,CACnB,UAAqB,EACrB,SAAoB,EACpB,SAAoB;IAEpB,OAAO;QACL,KAAK,EAAG,UAAU,CAAC,KAAK,IAAK,SAAS,CAAC,KAAK,IAAK,SAAS,CAAC,KAAK,IAAK,aAAa;QAClF,MAAM,EAAE,UAAU,CAAC,MAAM,IAAI,SAAS,CAAC,MAAM,IAAI,SAAS,CAAC,MAAM,IAAI,cAAc;QACnF,IAAI,EAAI,UAAU,CAAC,IAAI,IAAM,SAAS,CAAC,IAAI,IAAM,SAAS,CAAC,IAAI,IAAM,YAAY;QACjF,GAAG,EAAK,UAAU,CAAC,GAAG,IAAO,SAAS,CAAC,GAAG,IAAO,SAAS,CAAC,GAAG,IAAO,WAAW;KACjF,CAAC;AACJ,CAAC;AAED,gFAAgF;AAEhF,SAAS,iBAAiB,CACxB,IAAkD,EAClD,KAA2D;IAE3D,MAAM,UAAU,GAAI,IAAI,CAAC,MAAM,IAAK,CAAC,CAAC;IACtC,MAAM,SAAS,GAAK,IAAI,CAAC,KAAK,IAAM,KAAK,CAAC;IAC1C,MAAM,SAAS,GAAK,IAAI,CAAC,KAAK,IAAM,KAAK,CAAC;IAE1C,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACnB,OAAO;YACL,MAAM,EAAE,UAAwB;YAChC,KAAK,EAAG,SAAS;YACjB,KAAK,EAAG,SAAS;SAClB,CAAC;IACJ,CAAC;IAED,MAAM,WAAW,GAAG,KAAK,CAAC,MAAM,IAAI,CAAC,CAAC;IACtC,MAAM,UAAU,GAAI,KAAK,CAAC,KAAK,IAAK,KAAK,CAAC;IAC1C,MAAM,UAAU,GAAI,KAAK,CAAC,KAAK,IAAK,KAAK,CAAC;IAE1C,OAAO;QACL,MAAM,EAAE,CAAC,CAAC,UAAU,GAAG,WAAW,CAAC,GAAG,CAAC,CAAe;QACtD,KAAK,EAAG,SAAS,KAAM,UAAU,EAAI,MAAM;QAC3C,KAAK,EAAG,SAAS,KAAM,UAAU,EAAI,MAAM;KAC5C,CAAC;AACJ,CAAC;AAED,gFAAgF;AAEhF;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,WAAW,CAAC,GAAY,EAAE,KAAkB;IAC1D,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACnC,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,OAAO,GAAG,CAAC,gBAAgB,EAAE,cAAc,GAAG,CAAC,MAAM,6BAA6B,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,IAAI,IAAI,CAAC,CAAC;IAChH,CAAC;IAED,+BAA+B;IAC/B,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACxC,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;QAC7B,MAAM,OAAO,GAAM,YAAY,CAAC,EAAE,EAAE,UAAU,EAAE,IAAI,CAAC,CAAC;QACtD,MAAM,UAAU,GAAG,iBAAiB,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;QACvD,OAAO,EAAE,CAAC;YACR,IAAI,EAAQ,UAAU,CAAC,IAAI;YAC3B,OAAO;YACP,UAAU;YACV,SAAS,EAAG,eAAe,CAAC,UAAU,CAAC,IAAI,CAAC;SAC7C,CAAC,CAAC;IACL,CAAC;IAED,mBAAmB;IACnB,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;IAC7B,IAAI,OAAO,KAAK,SAAS,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,IAAI,OAAO,CAAC,EAAE,CAAC;QACpD,OAAO,GAAG,CACR,gBAAgB,EAChB,SAAS,GAAG,CAAC,IAAI,wBAAwB,GAAG,CAAC,MAAM,+BAA+B,CACnF,CAAC;IACJ,CAAC;IAED,6EAA6E;IAC7E,IAAI,WAAW,GAAI,GAAG,CAAC,IAAI,CAAC;IAC5B,IAAI,YAAY,GAAqB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC;IAC/D,MAAM,QAAQ,GAAG,YAAY,CAAC,CAAE,yDAAyD;IAEzF,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,eAAe,EAAE,KAAK,EAAE,EAAE,CAAC;QACrD,IAAI,YAAY,KAAK,IAAI;YAAE,MAAM;QAEjC,MAAM,UAAU,GAAG,YAAY,CAAC,MAAM,CAAC;QACvC,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QAE1C,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;YAC7B,6DAA6D;YAC7D,MAAM,OAAO,GAAM,YAAY,CAAC,QAAQ,IAAI,EAAE,EAAE,UAAU,EAAE,IAAI,CAAC,CAAC;YAClE,MAAM,UAAU,GAAG,iBAAiB,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;YAC3D,OAAO,EAAE,CAAC;gBACR,IAAI,EAAO,UAAU,CAAC,IAAI;gBAC1B,OAAO;gBACP,UAAU;gBACV,SAAS,EAAE,eAAe,CAAC,UAAU,CAAC,IAAI,CAAC;aAC5C,CAAC,CAAC;QACL,CAAC;QAED,oDAAoD;QACpD,MAAM,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;QACxC,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;YAC9B,OAAO,GAAG,CACR,gBAAgB,EAChB,UAAU,WAAW,cAAc,GAAG,CAAC,MAAM,uBAAuB,UAAU,wBAAwB,CACvG,CAAC;QACJ,CAAC;QAED,WAAW,GAAI,UAAU,CAAC;QAC1B,YAAY,GAAG,WAAW,CAAC;IAC7B,CAAC;IAED,OAAO,GAAG,CACR,gBAAgB,EAChB,oBAAoB,GAAG,CAAC,IAAI,cAAc,GAAG,CAAC,MAAM,8BAA8B,eAAe,EAAE,CACpG,CAAC;AACJ,CAAC"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * validateIconPack
3
+ *
4
+ * Pure validator for `.triton-icons.json` icon pack files. No file or network
5
+ * I/O — only validates an already-parsed JSON value against the IconifyJSON
6
+ * contract. Returns a Result so callers never need try/catch.
7
+ *
8
+ * Strictness policy:
9
+ * - Top-level Triton keys: strict (unknown keys are an error).
10
+ * - IconData and IconAlias entries: strict (unknown keys are an error).
11
+ * - All required fields must be present with the correct types.
12
+ * - Icon names and prefix format are validated against the token grammar.
13
+ *
14
+ * Token grammar (enforced here):
15
+ * prefix ::= [a-z][a-z0-9-]*
16
+ * name ::= [a-z0-9][a-z0-9-]*
17
+ */
18
+ import type { IconifyJSON } from '../contracts/icons.js';
19
+ import { type Result } from '../contracts/result.js';
20
+ /**
21
+ * Validate an unknown value against the IconifyJSON contract.
22
+ *
23
+ * Pure and synchronous — never throws, never reads files.
24
+ * Returns ok(IconifyJSON) on success, err(ICON_VALIDATION_ERROR, ...) on any violation.
25
+ *
26
+ * Validates:
27
+ * - Required fields: prefix, icons
28
+ * - prefix format: [a-z][a-z0-9-]*
29
+ * - icons: at least one entry; each key matches [a-z0-9][a-z0-9-]*
30
+ * - Each IconData: required body, optional dims (positive), rotate (0–3), flips (boolean)
31
+ * - aliases: each alias key matches [a-z0-9][a-z0-9-]*; required parent
32
+ * - Pack-level dims: positive numbers if present
33
+ * - Unknown keys at any level: hard error
34
+ */
35
+ export declare function validateIconPack(json: unknown): Result<IconifyJSON>;
36
+ //# sourceMappingURL=validate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../../../src/icons/validate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAuB,MAAM,uBAAuB,CAAC;AAC9E,OAAO,EAAW,KAAK,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAwK9D;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAAC,WAAW,CAAC,CAsGnE"}
@@ -0,0 +1,257 @@
1
+ /**
2
+ * validateIconPack
3
+ *
4
+ * Pure validator for `.triton-icons.json` icon pack files. No file or network
5
+ * I/O — only validates an already-parsed JSON value against the IconifyJSON
6
+ * contract. Returns a Result so callers never need try/catch.
7
+ *
8
+ * Strictness policy:
9
+ * - Top-level Triton keys: strict (unknown keys are an error).
10
+ * - IconData and IconAlias entries: strict (unknown keys are an error).
11
+ * - All required fields must be present with the correct types.
12
+ * - Icon names and prefix format are validated against the token grammar.
13
+ *
14
+ * Token grammar (enforced here):
15
+ * prefix ::= [a-z][a-z0-9-]*
16
+ * name ::= [a-z0-9][a-z0-9-]*
17
+ */
18
+ import { ok, err } from '../contracts/result.js';
19
+ // ─── Known key sets ───────────────────────────────────────────────────────────
20
+ const TOP_LEVEL_KEYS = new Set([
21
+ 'prefix', 'icons', 'aliases', 'width', 'height', 'left', 'top',
22
+ ]);
23
+ const ICON_DATA_KEYS = new Set([
24
+ 'body', 'width', 'height', 'left', 'top', 'rotate', 'hFlip', 'vFlip',
25
+ ]);
26
+ const ICON_ALIAS_KEYS = new Set([
27
+ 'parent', 'rotate', 'hFlip', 'vFlip', 'width', 'height', 'left', 'top',
28
+ ]);
29
+ // ─── Token grammar regexes ────────────────────────────────────────────────────
30
+ /** Pack prefix: starts with a lowercase letter, then lowercase alnum/hyphens. */
31
+ const PREFIX_RE = /^[a-z][a-z0-9-]*$/;
32
+ /** Icon/alias name: starts with lowercase alnum, then lowercase alnum/hyphens. */
33
+ const NAME_RE = /^[a-z0-9][a-z0-9-]*$/;
34
+ const VALID_ROTATE = new Set([0, 1, 2, 3]);
35
+ // ─── Helpers ──────────────────────────────────────────────────────────────────
36
+ function isPlainObject(v) {
37
+ return v !== null && typeof v === 'object' && !Array.isArray(v);
38
+ }
39
+ function fail(message) {
40
+ return err('ICON_VALIDATION_ERROR', message);
41
+ }
42
+ // ─── IconData validator ───────────────────────────────────────────────────────
43
+ function validateIconData(iconName, obj) {
44
+ const ctx = `icons["${iconName}"]`;
45
+ if (!isPlainObject(obj)) {
46
+ return fail(`${ctx} must be a plain object`);
47
+ }
48
+ for (const key of Object.keys(obj)) {
49
+ if (!ICON_DATA_KEYS.has(key)) {
50
+ return fail(`Unknown key in ${ctx}: "${key}"`);
51
+ }
52
+ }
53
+ // body — required, non-empty string
54
+ if (!('body' in obj)) {
55
+ return fail(`${ctx} is missing required field "body"`);
56
+ }
57
+ const body = obj['body'];
58
+ if (typeof body !== 'string' || body.length === 0) {
59
+ return fail(`${ctx}.body must be a non-empty string, got ${JSON.stringify(body)}`);
60
+ }
61
+ // width / height — optional positive numbers
62
+ for (const dim of ['width', 'height']) {
63
+ if (dim in obj) {
64
+ const val = obj[dim];
65
+ if (typeof val !== 'number' || val <= 0) {
66
+ return fail(`${ctx}.${dim} must be a positive number, got ${JSON.stringify(val)}`);
67
+ }
68
+ }
69
+ }
70
+ // left / top — optional numbers (may be zero or negative for unusual viewBoxes)
71
+ for (const origin of ['left', 'top']) {
72
+ if (origin in obj) {
73
+ const val = obj[origin];
74
+ if (typeof val !== 'number') {
75
+ return fail(`${ctx}.${origin} must be a number, got ${JSON.stringify(val)}`);
76
+ }
77
+ }
78
+ }
79
+ // rotate — optional, must be 0 | 1 | 2 | 3
80
+ if ('rotate' in obj) {
81
+ const val = obj['rotate'];
82
+ if (!VALID_ROTATE.has(val)) {
83
+ return fail(`${ctx}.rotate must be 0, 1, 2, or 3, got ${JSON.stringify(val)}`);
84
+ }
85
+ }
86
+ // hFlip / vFlip — optional booleans
87
+ for (const flip of ['hFlip', 'vFlip']) {
88
+ if (flip in obj) {
89
+ const val = obj[flip];
90
+ if (typeof val !== 'boolean') {
91
+ return fail(`${ctx}.${flip} must be a boolean, got ${JSON.stringify(val)}`);
92
+ }
93
+ }
94
+ }
95
+ return ok(obj);
96
+ }
97
+ // ─── IconAlias validator ──────────────────────────────────────────────────────
98
+ function validateIconAlias(aliasName, obj) {
99
+ const ctx = `aliases["${aliasName}"]`;
100
+ if (!isPlainObject(obj)) {
101
+ return fail(`${ctx} must be a plain object`);
102
+ }
103
+ for (const key of Object.keys(obj)) {
104
+ if (!ICON_ALIAS_KEYS.has(key)) {
105
+ return fail(`Unknown key in ${ctx}: "${key}"`);
106
+ }
107
+ }
108
+ // parent — required, non-empty string
109
+ if (!('parent' in obj)) {
110
+ return fail(`${ctx} is missing required field "parent"`);
111
+ }
112
+ const parent = obj['parent'];
113
+ if (typeof parent !== 'string' || parent.length === 0) {
114
+ return fail(`${ctx}.parent must be a non-empty string, got ${JSON.stringify(parent)}`);
115
+ }
116
+ // rotate — optional, 0 | 1 | 2 | 3
117
+ if ('rotate' in obj) {
118
+ const val = obj['rotate'];
119
+ if (!VALID_ROTATE.has(val)) {
120
+ return fail(`${ctx}.rotate must be 0, 1, 2, or 3, got ${JSON.stringify(val)}`);
121
+ }
122
+ }
123
+ // hFlip / vFlip — optional booleans
124
+ for (const flip of ['hFlip', 'vFlip']) {
125
+ if (flip in obj) {
126
+ const val = obj[flip];
127
+ if (typeof val !== 'boolean') {
128
+ return fail(`${ctx}.${flip} must be a boolean, got ${JSON.stringify(val)}`);
129
+ }
130
+ }
131
+ }
132
+ // width / height — optional positive numbers
133
+ for (const dim of ['width', 'height']) {
134
+ if (dim in obj) {
135
+ const val = obj[dim];
136
+ if (typeof val !== 'number' || val <= 0) {
137
+ return fail(`${ctx}.${dim} must be a positive number, got ${JSON.stringify(val)}`);
138
+ }
139
+ }
140
+ }
141
+ // left / top — optional numbers
142
+ for (const origin of ['left', 'top']) {
143
+ if (origin in obj) {
144
+ const val = obj[origin];
145
+ if (typeof val !== 'number') {
146
+ return fail(`${ctx}.${origin} must be a number, got ${JSON.stringify(val)}`);
147
+ }
148
+ }
149
+ }
150
+ return ok(obj);
151
+ }
152
+ // ─── Main validator ───────────────────────────────────────────────────────────
153
+ /**
154
+ * Validate an unknown value against the IconifyJSON contract.
155
+ *
156
+ * Pure and synchronous — never throws, never reads files.
157
+ * Returns ok(IconifyJSON) on success, err(ICON_VALIDATION_ERROR, ...) on any violation.
158
+ *
159
+ * Validates:
160
+ * - Required fields: prefix, icons
161
+ * - prefix format: [a-z][a-z0-9-]*
162
+ * - icons: at least one entry; each key matches [a-z0-9][a-z0-9-]*
163
+ * - Each IconData: required body, optional dims (positive), rotate (0–3), flips (boolean)
164
+ * - aliases: each alias key matches [a-z0-9][a-z0-9-]*; required parent
165
+ * - Pack-level dims: positive numbers if present
166
+ * - Unknown keys at any level: hard error
167
+ */
168
+ export function validateIconPack(json) {
169
+ if (!isPlainObject(json)) {
170
+ return fail(`IconifyJSON must be a non-null plain object, got ${json === null ? 'null' : Array.isArray(json) ? 'array' : typeof json}`);
171
+ }
172
+ // Unknown top-level key check
173
+ for (const key of Object.keys(json)) {
174
+ if (!TOP_LEVEL_KEYS.has(key)) {
175
+ return fail(`Unknown top-level key: "${key}"`);
176
+ }
177
+ }
178
+ // prefix — required string matching [a-z][a-z0-9-]*
179
+ if (!('prefix' in json)) {
180
+ return fail('Missing required field "prefix"');
181
+ }
182
+ const prefix = json['prefix'];
183
+ if (typeof prefix !== 'string') {
184
+ return fail(`"prefix" must be a string, got ${JSON.stringify(prefix)}`);
185
+ }
186
+ if (!PREFIX_RE.test(prefix)) {
187
+ return fail(`"prefix" must match ^[a-z][a-z0-9-]*$ (lowercase letter start, then lowercase alnum/hyphens), got ${JSON.stringify(prefix)}`);
188
+ }
189
+ // icons — required plain object with ≥1 entry
190
+ if (!('icons' in json)) {
191
+ return fail('Missing required field "icons"');
192
+ }
193
+ const iconsRaw = json['icons'];
194
+ if (!isPlainObject(iconsRaw)) {
195
+ return fail('"icons" must be a plain object');
196
+ }
197
+ const iconNames = Object.keys(iconsRaw);
198
+ if (iconNames.length === 0) {
199
+ return fail('"icons" must contain at least one icon entry');
200
+ }
201
+ const icons = {};
202
+ for (const name of iconNames) {
203
+ if (!NAME_RE.test(name)) {
204
+ return fail(`Icon name ${JSON.stringify(name)} must match ^[a-z0-9][a-z0-9-]*$ (lowercase alnum start, then lowercase alnum/hyphens)`);
205
+ }
206
+ const r = validateIconData(name, iconsRaw[name]);
207
+ if (!r.ok)
208
+ return r;
209
+ icons[name] = r.value;
210
+ }
211
+ // aliases — optional plain object
212
+ let aliases;
213
+ if ('aliases' in json) {
214
+ const aliasesRaw = json['aliases'];
215
+ if (!isPlainObject(aliasesRaw)) {
216
+ return fail('"aliases" must be a plain object');
217
+ }
218
+ aliases = {};
219
+ for (const aliasName of Object.keys(aliasesRaw)) {
220
+ if (!NAME_RE.test(aliasName)) {
221
+ return fail(`Alias name ${JSON.stringify(aliasName)} must match ^[a-z0-9][a-z0-9-]*$`);
222
+ }
223
+ const r = validateIconAlias(aliasName, aliasesRaw[aliasName]);
224
+ if (!r.ok)
225
+ return r;
226
+ aliases[aliasName] = r.value;
227
+ }
228
+ }
229
+ // Pack-level dimension defaults — optional positive numbers (width/height) or numbers (left/top)
230
+ for (const dim of ['width', 'height']) {
231
+ if (dim in json) {
232
+ const val = json[dim];
233
+ if (typeof val !== 'number' || val <= 0) {
234
+ return fail(`"${dim}" must be a positive number, got ${JSON.stringify(val)}`);
235
+ }
236
+ }
237
+ }
238
+ for (const origin of ['left', 'top']) {
239
+ if (origin in json) {
240
+ const val = json[origin];
241
+ if (typeof val !== 'number') {
242
+ return fail(`"${origin}" must be a number, got ${JSON.stringify(val)}`);
243
+ }
244
+ }
245
+ }
246
+ const result = {
247
+ prefix: prefix,
248
+ icons,
249
+ ...(aliases !== undefined ? { aliases } : {}),
250
+ ...('width' in json ? { width: json['width'] } : {}),
251
+ ...('height' in json ? { height: json['height'] } : {}),
252
+ ...('left' in json ? { left: json['left'] } : {}),
253
+ ...('top' in json ? { top: json['top'] } : {}),
254
+ };
255
+ return ok(result);
256
+ }
257
+ //# sourceMappingURL=validate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.js","sourceRoot":"","sources":["../../../../src/icons/validate.ts"],"names":[],"mappings":"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"}