@fazelstudio/floe 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.
Files changed (154) hide show
  1. package/LICENSE +21 -0
  2. package/dist/src/cli/check.d.ts +14 -0
  3. package/dist/src/cli/check.d.ts.map +1 -0
  4. package/dist/src/cli/check.js +88 -0
  5. package/dist/src/cli/check.js.map +1 -0
  6. package/dist/src/cli/format.d.ts +9 -0
  7. package/dist/src/cli/format.d.ts.map +1 -0
  8. package/dist/src/cli/format.js +114 -0
  9. package/dist/src/cli/format.js.map +1 -0
  10. package/dist/src/cli/main.d.ts +19 -0
  11. package/dist/src/cli/main.d.ts.map +1 -0
  12. package/dist/src/cli/main.js +207 -0
  13. package/dist/src/cli/main.js.map +1 -0
  14. package/dist/src/cli/render.d.ts +7 -0
  15. package/dist/src/cli/render.d.ts.map +1 -0
  16. package/dist/src/cli/render.js +90 -0
  17. package/dist/src/cli/render.js.map +1 -0
  18. package/dist/src/diagnostics.d.ts +32 -0
  19. package/dist/src/diagnostics.d.ts.map +1 -0
  20. package/dist/src/diagnostics.js +4 -0
  21. package/dist/src/diagnostics.js.map +1 -0
  22. package/dist/src/index.d.ts +40 -0
  23. package/dist/src/index.d.ts.map +1 -0
  24. package/dist/src/index.js +64 -0
  25. package/dist/src/index.js.map +1 -0
  26. package/dist/src/language/completion.d.ts +6 -0
  27. package/dist/src/language/completion.d.ts.map +1 -0
  28. package/dist/src/language/completion.js +363 -0
  29. package/dist/src/language/completion.js.map +1 -0
  30. package/dist/src/language/definitions.d.ts +9 -0
  31. package/dist/src/language/definitions.d.ts.map +1 -0
  32. package/dist/src/language/definitions.js +70 -0
  33. package/dist/src/language/definitions.js.map +1 -0
  34. package/dist/src/language/diagnosticsService.d.ts +14 -0
  35. package/dist/src/language/diagnosticsService.d.ts.map +1 -0
  36. package/dist/src/language/diagnosticsService.js +37 -0
  37. package/dist/src/language/diagnosticsService.js.map +1 -0
  38. package/dist/src/language/folding.d.ts +8 -0
  39. package/dist/src/language/folding.d.ts.map +1 -0
  40. package/dist/src/language/folding.js +58 -0
  41. package/dist/src/language/folding.js.map +1 -0
  42. package/dist/src/language/formatting.d.ts +5 -0
  43. package/dist/src/language/formatting.d.ts.map +1 -0
  44. package/dist/src/language/formatting.js +274 -0
  45. package/dist/src/language/formatting.js.map +1 -0
  46. package/dist/src/language/highlighting.d.ts +9 -0
  47. package/dist/src/language/highlighting.d.ts.map +1 -0
  48. package/dist/src/language/highlighting.js +74 -0
  49. package/dist/src/language/highlighting.js.map +1 -0
  50. package/dist/src/language/hover.d.ts +6 -0
  51. package/dist/src/language/hover.d.ts.map +1 -0
  52. package/dist/src/language/hover.js +197 -0
  53. package/dist/src/language/hover.js.map +1 -0
  54. package/dist/src/language/indentation.d.ts +15 -0
  55. package/dist/src/language/indentation.d.ts.map +1 -0
  56. package/dist/src/language/indentation.js +97 -0
  57. package/dist/src/language/indentation.js.map +1 -0
  58. package/dist/src/language/index.d.ts +54 -0
  59. package/dist/src/language/index.d.ts.map +1 -0
  60. package/dist/src/language/index.js +85 -0
  61. package/dist/src/language/index.js.map +1 -0
  62. package/dist/src/language/references.d.ts +12 -0
  63. package/dist/src/language/references.d.ts.map +1 -0
  64. package/dist/src/language/references.js +35 -0
  65. package/dist/src/language/references.js.map +1 -0
  66. package/dist/src/language/rename.d.ts +18 -0
  67. package/dist/src/language/rename.d.ts.map +1 -0
  68. package/dist/src/language/rename.js +53 -0
  69. package/dist/src/language/rename.js.map +1 -0
  70. package/dist/src/language/semanticModel.d.ts +21 -0
  71. package/dist/src/language/semanticModel.d.ts.map +1 -0
  72. package/dist/src/language/semanticModel.js +43 -0
  73. package/dist/src/language/semanticModel.js.map +1 -0
  74. package/dist/src/language/symbols.d.ts +9 -0
  75. package/dist/src/language/symbols.d.ts.map +1 -0
  76. package/dist/src/language/symbols.js +160 -0
  77. package/dist/src/language/symbols.js.map +1 -0
  78. package/dist/src/language/types.d.ts +49 -0
  79. package/dist/src/language/types.d.ts.map +1 -0
  80. package/dist/src/language/types.js +2 -0
  81. package/dist/src/language/types.js.map +1 -0
  82. package/dist/src/language/utils.d.ts +24 -0
  83. package/dist/src/language/utils.d.ts.map +1 -0
  84. package/dist/src/language/utils.js +154 -0
  85. package/dist/src/language/utils.js.map +1 -0
  86. package/dist/src/layout/dagre.d.ts +13 -0
  87. package/dist/src/layout/dagre.d.ts.map +1 -0
  88. package/dist/src/layout/dagre.js +229 -0
  89. package/dist/src/layout/dagre.js.map +1 -0
  90. package/dist/src/layout/index.d.ts +15 -0
  91. package/dist/src/layout/index.d.ts.map +1 -0
  92. package/dist/src/layout/index.js +22 -0
  93. package/dist/src/layout/index.js.map +1 -0
  94. package/dist/src/layout/simple.d.ts +20 -0
  95. package/dist/src/layout/simple.d.ts.map +1 -0
  96. package/dist/src/layout/simple.js +674 -0
  97. package/dist/src/layout/simple.js.map +1 -0
  98. package/dist/src/layout/types.d.ts +65 -0
  99. package/dist/src/layout/types.d.ts.map +1 -0
  100. package/dist/src/layout/types.js +2 -0
  101. package/dist/src/layout/types.js.map +1 -0
  102. package/dist/src/lexer.d.ts +25 -0
  103. package/dist/src/lexer.d.ts.map +1 -0
  104. package/dist/src/lexer.js +280 -0
  105. package/dist/src/lexer.js.map +1 -0
  106. package/dist/src/lsp/documents.d.ts +24 -0
  107. package/dist/src/lsp/documents.d.ts.map +1 -0
  108. package/dist/src/lsp/documents.js +97 -0
  109. package/dist/src/lsp/documents.js.map +1 -0
  110. package/dist/src/lsp/server.d.ts +70 -0
  111. package/dist/src/lsp/server.d.ts.map +1 -0
  112. package/dist/src/lsp/server.js +623 -0
  113. package/dist/src/lsp/server.js.map +1 -0
  114. package/dist/src/lsp/utils.d.ts +47 -0
  115. package/dist/src/lsp/utils.d.ts.map +1 -0
  116. package/dist/src/lsp/utils.js +142 -0
  117. package/dist/src/lsp/utils.js.map +1 -0
  118. package/dist/src/parser.d.ts +106 -0
  119. package/dist/src/parser.d.ts.map +1 -0
  120. package/dist/src/parser.js +1018 -0
  121. package/dist/src/parser.js.map +1 -0
  122. package/dist/src/pipeline.d.ts +51 -0
  123. package/dist/src/pipeline.d.ts.map +1 -0
  124. package/dist/src/pipeline.js +65 -0
  125. package/dist/src/pipeline.js.map +1 -0
  126. package/dist/src/range.d.ts +24 -0
  127. package/dist/src/range.d.ts.map +1 -0
  128. package/dist/src/range.js +20 -0
  129. package/dist/src/range.js.map +1 -0
  130. package/dist/src/render/index.d.ts +3 -0
  131. package/dist/src/render/index.d.ts.map +1 -0
  132. package/dist/src/render/index.js +3 -0
  133. package/dist/src/render/index.js.map +1 -0
  134. package/dist/src/render/shapes.d.ts +20 -0
  135. package/dist/src/render/shapes.d.ts.map +1 -0
  136. package/dist/src/render/shapes.js +110 -0
  137. package/dist/src/render/shapes.js.map +1 -0
  138. package/dist/src/render/svg.d.ts +19 -0
  139. package/dist/src/render/svg.d.ts.map +1 -0
  140. package/dist/src/render/svg.js +227 -0
  141. package/dist/src/render/svg.js.map +1 -0
  142. package/dist/src/security/url.d.ts +7 -0
  143. package/dist/src/security/url.d.ts.map +1 -0
  144. package/dist/src/security/url.js +27 -0
  145. package/dist/src/security/url.js.map +1 -0
  146. package/dist/src/types.d.ts +111 -0
  147. package/dist/src/types.d.ts.map +1 -0
  148. package/dist/src/types.js +16 -0
  149. package/dist/src/types.js.map +1 -0
  150. package/dist/src/validator.d.ts +47 -0
  151. package/dist/src/validator.d.ts.map +1 -0
  152. package/dist/src/validator.js +235 -0
  153. package/dist/src/validator.js.map +1 -0
  154. package/package.json +90 -0
@@ -0,0 +1,227 @@
1
+ import { renderNodeShape } from "./shapes.js";
2
+ const DEFAULT_FONT = "ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial, sans-serif";
3
+ /**
4
+ * Deterministic SVG renderer.
5
+ * Consumes LayoutResult (semantic + layout), not raw Floe text.
6
+ */
7
+ export function renderSvg(layout, opts) {
8
+ const padding = opts?.padding ?? 0;
9
+ const background = opts?.background ?? "#ffffff";
10
+ const fontFamily = opts?.fontFamily ?? DEFAULT_FONT;
11
+ // Deterministic dimensions: layout width/height plus padding
12
+ const width = Math.ceil(layout.width + padding * 2);
13
+ const height = Math.ceil(layout.height + padding * 2);
14
+ const viewBox = `0 0 ${width} ${height}`;
15
+ // Sort for determinism
16
+ const nodesSorted = [...layout.nodes].sort((a, b) => a.id.localeCompare(b.id));
17
+ const edgesSorted = [...layout.edges].sort((a, b) => {
18
+ if (a.source !== b.source)
19
+ return a.source.localeCompare(b.source);
20
+ if (a.target !== b.target)
21
+ return a.target.localeCompare(b.target);
22
+ return (a.label ?? "").localeCompare(b.label ?? "");
23
+ });
24
+ const parts = [];
25
+ // Header
26
+ parts.push(`<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}" viewBox="${viewBox}" role="img" font-family="${escapeAttr(fontFamily)}">`);
27
+ // Background
28
+ if (background && background !== "transparent") {
29
+ parts.push(`<rect width="${width}" height="${height}" fill="${escapeAttr(background)}" />`);
30
+ }
31
+ // Styles
32
+ const css = opts?.css ?? defaultCss();
33
+ parts.push(`<style>${css}</style>`);
34
+ // Defs: arrowhead marker (deterministic id)
35
+ parts.push(`<defs>`);
36
+ parts.push(`<marker id="arrowhead" viewBox="0 0 10 7" refX="9" refY="3.5" markerWidth="10" markerHeight="7" orient="auto" markerUnits="strokeWidth">`);
37
+ parts.push(`<path d="M 0 0 L 10 3.5 L 0 7 z" fill="#334155" />`);
38
+ parts.push(`</marker>`);
39
+ parts.push(`</defs>`);
40
+ // Group for offset padding
41
+ const offset = padding;
42
+ if (offset !== 0)
43
+ parts.push(`<g transform="translate(${offset} ${offset})">`);
44
+ // Groups containers — draw behind nodes/edges but above background
45
+ const groups = layout.groups ?? [];
46
+ if (groups.length > 0) {
47
+ parts.push(`<g class="groups">`);
48
+ // flatten and sort deterministically already done by layout, but re-sort for rendering stability
49
+ const flatGroups = flattenGroups(groups);
50
+ // Draw outer groups first (sorted by area descending so outer wraps inner? For determinism, sort by id depth)
51
+ // Already deterministic, just render each via helper
52
+ for (const g of flatGroups) {
53
+ // For nested rendering, we render all groups individually; outer will be drawn before inner due to flat order (parent before child)
54
+ parts.push(renderGroupSvg(g, fontFamily));
55
+ }
56
+ parts.push(`</g>`);
57
+ }
58
+ // Edges group (draw first, under nodes)
59
+ parts.push(`<g class="edges" stroke-linecap="round" stroke-linejoin="round">`);
60
+ for (const e of edgesSorted) {
61
+ const d = pointsToPath(e.points);
62
+ const edgeId = `edge-${escapeId(e.source)}-${escapeId(e.target)}${e.label ? "-" + hashLabel(e.label) : ""}`;
63
+ // Edge semantics: directed has arrow, undirected is dashed without arrow
64
+ const isUndirected = e.data?.kind === "undirected";
65
+ const dash = isUndirected ? ` stroke-dasharray="6 3"` : "";
66
+ const marker = isUndirected ? "" : ` marker-end="url(#arrowhead)"`;
67
+ parts.push(`<path id="${edgeId}" d="${d}" fill="none" stroke="#334155" stroke-width="1.6"${dash}${marker} />`);
68
+ }
69
+ parts.push(`</g>`);
70
+ // Edge labels group (above edges, below nodes)
71
+ if (edgesSorted.some((e) => e.label)) {
72
+ parts.push(`<g class="edge-labels">`);
73
+ for (const e of edgesSorted) {
74
+ if (!e.label)
75
+ continue;
76
+ const pos = e.labelPos ?? midpoint(e.points);
77
+ const x = fmt(pos.x);
78
+ const y = fmt(pos.y);
79
+ const label = escapeXml(e.label);
80
+ // Estimate text width for background rect
81
+ const estW = estimateTextWidth(e.label) + 8;
82
+ const estH = 16;
83
+ const rx = 4;
84
+ // Background rect for readability
85
+ parts.push(`<g class="edge-label" transform="translate(${x} ${y})">`);
86
+ parts.push(`<rect x="${fmt(-estW / 2)}" y="${fmt(-estH / 2 + 1)}" width="${fmt(estW)}" height="${fmt(estH)}" rx="${rx}" ry="${rx}" fill="white" stroke="#e2e8f0" stroke-width="0.8" />`);
87
+ parts.push(`<text text-anchor="middle" dominant-baseline="middle" font-size="11" fill="#334155" font-family="${escapeAttr(fontFamily)}">${label}</text>`);
88
+ parts.push(`</g>`);
89
+ }
90
+ parts.push(`</g>`);
91
+ }
92
+ // Nodes group
93
+ parts.push(`<g class="nodes">`);
94
+ for (const n of nodesSorted) {
95
+ const shapeSvg = renderNodeShape(n);
96
+ const label = escapeXml(n.label);
97
+ const tx = fmt(n.x);
98
+ const ty = fmt(n.y);
99
+ // Node group with deterministic id and class per type
100
+ const kindClass = n.type ? `node-${escapeId(n.type)}` : `node-default`;
101
+ parts.push(`<g id="node-${escapeId(n.id)}" class="node ${kindClass}" data-node-id="${escapeAttr(n.id)}"${n.type ? ` data-node-type="${escapeAttr(n.type)}"` : ""}>`);
102
+ parts.push(shapeSvg);
103
+ // Label centered
104
+ // For database shape, label y is slightly lower due to cylinder top? Keep centered for now
105
+ parts.push(`<text x="${tx}" y="${ty}" text-anchor="middle" dominant-baseline="middle" font-size="12" font-weight="500" fill="#0f172a" font-family="${escapeAttr(fontFamily)}">${label}</text>`);
106
+ parts.push(`</g>`);
107
+ }
108
+ parts.push(`</g>`);
109
+ if (offset !== 0)
110
+ parts.push(`</g>`);
111
+ // Optional debug: bounding boxes
112
+ if (opts?.debug) {
113
+ parts.push(`<g class="debug">`);
114
+ for (const n of nodesSorted) {
115
+ const x = fmt(n.x - n.width / 2);
116
+ const y = fmt(n.y - n.height / 2);
117
+ parts.push(`<rect x="${x}" y="${y}" width="${fmt(n.width)}" height="${fmt(n.height)}" fill="none" stroke="red" stroke-dasharray="3 3" stroke-width="0.5" />`);
118
+ }
119
+ parts.push(`</g>`);
120
+ }
121
+ parts.push(`</svg>`);
122
+ return parts.join("\n");
123
+ }
124
+ function defaultCss() {
125
+ return `
126
+ .node text { pointer-events: none; user-select: none; }
127
+ .edge-label text { pointer-events: none; user-select: none; }
128
+ `;
129
+ }
130
+ function pointsToPath(points) {
131
+ if (points.length === 0)
132
+ return "";
133
+ if (points.length === 1)
134
+ return `M ${fmt(points[0].x)} ${fmt(points[0].y)}`;
135
+ const start = points[0];
136
+ let d = `M ${fmt(start.x)} ${fmt(start.y)}`;
137
+ for (let i = 1; i < points.length; i++) {
138
+ const p = points[i];
139
+ d += ` L ${fmt(p.x)} ${fmt(p.y)}`;
140
+ }
141
+ return d;
142
+ }
143
+ function midpoint(points) {
144
+ if (points.length === 0)
145
+ return { x: 0, y: 0 };
146
+ if (points.length === 1)
147
+ return points[0];
148
+ if (points.length === 2) {
149
+ const a = points[0], b = points[1];
150
+ return { x: (a.x + b.x) / 2, y: (a.y + b.y) / 2 };
151
+ }
152
+ const mid = Math.floor(points.length / 2);
153
+ const a = points[mid - 1], b = points[mid];
154
+ return { x: (a.x + b.x) / 2, y: (a.y + b.y) / 2 };
155
+ }
156
+ function estimateTextWidth(text) {
157
+ // Deterministic char width approximation: 6.5 per char at 11px
158
+ return text.length * 6.5;
159
+ }
160
+ function fmt(n) {
161
+ const r = Math.round(n * 100) / 100;
162
+ if (Number.isInteger(r))
163
+ return String(r);
164
+ return r.toFixed(2).replace(/\.?0+$/, "");
165
+ }
166
+ function escapeXml(s) {
167
+ return s
168
+ .replace(/&/g, "&amp;")
169
+ .replace(/</g, "&lt;")
170
+ .replace(/>/g, "&gt;")
171
+ .replace(/"/g, "&quot;")
172
+ .replace(/'/g, "&apos;");
173
+ }
174
+ function escapeAttr(s) {
175
+ return escapeXml(s);
176
+ }
177
+ function escapeId(s) {
178
+ // For SVG id attribute, replace invalid chars deterministically
179
+ return s.replace(/[^A-Za-z0-9_-]/g, "_");
180
+ }
181
+ function hashLabel(s) {
182
+ let h = 0;
183
+ for (let i = 0; i < s.length; i++) {
184
+ h = (h * 31 + s.charCodeAt(i)) | 0;
185
+ }
186
+ return Math.abs(h).toString(36).slice(0, 6);
187
+ }
188
+ function renderGroupSvg(g, fontFamily) {
189
+ const x = fmt(g.x - g.width / 2);
190
+ const y = fmt(g.y - g.height / 2);
191
+ const w = fmt(g.width);
192
+ const h = fmt(g.height);
193
+ const label = escapeXml(g.label);
194
+ const gid = escapeId(g.id);
195
+ const typeAttr = g.type ? ` data-group-type="${escapeAttr(g.type)}"` : "";
196
+ // Group container rect with subtle fill and header bar for label
197
+ const headerH = 22;
198
+ // Main group rect
199
+ const parts = [];
200
+ parts.push(`<g id="group-${gid}" class="group group-${gid}" data-group-id="${escapeAttr(g.id)}"${typeAttr}>`);
201
+ // Background
202
+ parts.push(`<rect x="${x}" y="${y}" width="${w}" height="${h}" rx="8" ry="8" fill="#f8fafc" stroke="#cbd5e1" stroke-width="1.2" stroke-dasharray="8 4" />`);
203
+ // Header bar
204
+ parts.push(`<rect x="${x}" y="${y}" width="${w}" height="${fmt(headerH)}" rx="8" ry="8" fill="#e2e8f0" stroke="none" />`);
205
+ // To keep header rounded only top, overlay bottom rect of header? Simplify as above.
206
+ // Clip bottom of header: draw rect covering lower part of header's rounded bottom to make sharp bottom
207
+ parts.push(`<rect x="${x}" y="${fmt(g.y - g.height / 2 + headerH / 2)}" width="${w}" height="${fmt(headerH / 2)}" fill="#e2e8f0" stroke="none" />`);
208
+ // Header label
209
+ parts.push(`<text x="${fmt(g.x)}" y="${fmt(g.y - g.height / 2 + headerH / 2 + 1)}" text-anchor="middle" dominant-baseline="middle" font-size="11" font-weight="600" fill="#334155" font-family="${escapeAttr(fontFamily)}">${label}</text>`);
210
+ parts.push(`</g>`);
211
+ return parts.join("\n");
212
+ }
213
+ function flattenGroups(groups) {
214
+ const out = [];
215
+ function dfs(arr) {
216
+ // Deterministic order: sort by id at each level (layout already sorted, but enforce)
217
+ const sorted = [...arr].sort((a, b) => a.id.localeCompare(b.id));
218
+ for (const g of sorted) {
219
+ out.push(g);
220
+ if (g.children && g.children.length > 0)
221
+ dfs(g.children);
222
+ }
223
+ }
224
+ dfs(groups);
225
+ return out;
226
+ }
227
+ //# sourceMappingURL=svg.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"svg.js","sourceRoot":"","sources":["../../../src/render/svg.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * URL sanitization for Floe links — prevents execution vectors.
3
+ * Only allow safe schemes; block javascript:, data:, vbscript:
4
+ */
5
+ export declare function sanitizeUrl(url: string): string | null;
6
+ export declare function isSafeUrl(url: string): boolean;
7
+ //# sourceMappingURL=url.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"url.d.ts","sourceRoot":"","sources":["../../../src/security/url.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAYtD;AAED,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAE9C"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * URL sanitization for Floe links — prevents execution vectors.
3
+ * Only allow safe schemes; block javascript:, data:, vbscript:
4
+ */
5
+ export function sanitizeUrl(url) {
6
+ const s = url.trim();
7
+ if (!s)
8
+ return null;
9
+ if (/^(javascript|data|vbscript):/i.test(s))
10
+ return null;
11
+ // allow http/https, mailto, relative paths, or simple identifiers without scheme
12
+ if (/^https?:\/\//i.test(s))
13
+ return s;
14
+ if (/^mailto:/i.test(s))
15
+ return s;
16
+ if (s.startsWith("/") && !s.startsWith("//"))
17
+ return s;
18
+ // relative or simple: allow if no colon (no scheme) or known safe
19
+ if (!s.includes(":"))
20
+ return s;
21
+ // unknown scheme -> block
22
+ return null;
23
+ }
24
+ export function isSafeUrl(url) {
25
+ return sanitizeUrl(url) !== null;
26
+ }
27
+ //# sourceMappingURL=url.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"url.js","sourceRoot":"","sources":["../../../src/security/url.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,GAAW;IACrC,MAAM,CAAC,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IACrB,IAAI,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IACpB,IAAI,+BAA+B,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IACzD,iFAAiF;IACjF,IAAI,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO,CAAC,CAAC;IACtC,IAAI,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO,CAAC,CAAC;IAClC,IAAI,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,CAAC,CAAC;IACvD,kEAAkE;IAClE,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,CAAC,CAAC;IAC/B,0BAA0B;IAC1B,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,GAAW;IACnC,OAAO,WAAW,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC;AACnC,CAAC"}
@@ -0,0 +1,111 @@
1
+ import type { Range } from "./range.js";
2
+ /**
3
+ * Supported diagram directions
4
+ */
5
+ export type Direction = "TB" | "BT" | "LR" | "RL";
6
+ export declare const DIRECTIONS: readonly Direction[];
7
+ export declare const DEFAULT_DIRECTION: Direction;
8
+ /**
9
+ * Identifier rules:
10
+ * - Must match: [A-Za-z_][A-Za-z0-9_-]*
11
+ * - Must start with letter or underscore
12
+ * - May contain letters, digits, underscore, hyphen
13
+ * - No spaces, no Unicode beyond ASCII, no leading digit, no punctuation other than _ and -
14
+ * - Case-sensitive
15
+ * - Display labels are separate concept; IDs are internal keys
16
+ */
17
+ export declare const IDENTIFIER_RE: RegExp;
18
+ export declare function isValidIdentifier(id: string): boolean;
19
+ /**
20
+ * Semantic edge kind — directed or undirected association
21
+ */
22
+ export type EdgeKind = "directed" | "undirected";
23
+ /**
24
+ * Renderer-independent semantic model
25
+ * No visual coordinates, SVG, or layout information.
26
+ */
27
+ export interface FloeNode {
28
+ id: string;
29
+ /** Display label — conceptually separate from `id`; quoted string after id/type, defaults to id if not set */
30
+ label?: string;
31
+ /** Explicit node type, e.g. "person", "service", "database" — semantic style reference */
32
+ type?: string;
33
+ /** Source range covering the identifier (and type brackets if present, and label if present) */
34
+ range: Range;
35
+ }
36
+ /**
37
+ * Annotation — semantic note attached to a node/group or diagram-level if target undefined.
38
+ */
39
+ export interface FloeAnnotation {
40
+ /** Target node or group id; undefined => diagram-level */
41
+ target?: string;
42
+ text: string;
43
+ range: Range;
44
+ }
45
+ /**
46
+ * Link — semantic external link attached to a node/group.
47
+ */
48
+ export interface FloeLink {
49
+ target: string;
50
+ url: string;
51
+ range: Range;
52
+ }
53
+ export interface FloeEdge {
54
+ source: string;
55
+ target: string;
56
+ label?: string;
57
+ /** Edge semantics: directed ( -> ) or undirected ( -- ) */
58
+ kind: EdgeKind;
59
+ /** Range covering entire edge statement */
60
+ range: Range;
61
+ /** Ranges for sub-components for diagnostics / tooling */
62
+ sourceRange: Range;
63
+ targetRange: Range;
64
+ labelRange?: Range;
65
+ }
66
+ /**
67
+ * Group — semantic container; may be nested. Renderer-independent.
68
+ */
69
+ export interface FloeGroup {
70
+ id: string;
71
+ /** Display label for group (quoted string), defaults to id */
72
+ label?: string;
73
+ /** Semantic type e.g. "subsystem" */
74
+ type?: string;
75
+ range: Range;
76
+ /** Direct member node ids defined inside this group (not counting nested subgroup members) */
77
+ nodeIds: string[];
78
+ /** Nested groups */
79
+ groups: FloeGroup[];
80
+ /** Semantic metadata scoped to this group */
81
+ metadata: Record<string, string>;
82
+ /** Annotations scoped to this group */
83
+ annotations: FloeAnnotation[];
84
+ /** External link for group */
85
+ link?: string;
86
+ /** Parent group id if nested */
87
+ parentId?: string;
88
+ }
89
+ export interface FloeDiagram {
90
+ direction: Direction;
91
+ /** Direction declaration range if explicitly provided */
92
+ directionRange?: Range;
93
+ nodes: FloeNode[];
94
+ edges: FloeEdge[];
95
+ /** Top-level groups (nested via groups[].groups) */
96
+ groups: FloeGroup[];
97
+ /** Semantic metadata at diagram level */
98
+ metadata: Record<string, string>;
99
+ /** Diagram-level and targeted annotations */
100
+ annotations: FloeAnnotation[];
101
+ /** Semantic external links (target -> url) */
102
+ links: FloeLink[];
103
+ }
104
+ /**
105
+ * Full parse result including diagnostics
106
+ */
107
+ export interface ParseResult {
108
+ diagram: FloeDiagram;
109
+ diagnostics: import("./diagnostics.js").Diagnostic[];
110
+ }
111
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAExC;;GAEG;AACH,MAAM,MAAM,SAAS,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAElD,eAAO,MAAM,UAAU,EAAE,SAAS,SAAS,EAAsC,CAAC;AAClF,eAAO,MAAM,iBAAiB,EAAE,SAAgB,CAAC;AAEjD;;;;;;;;GAQG;AACH,eAAO,MAAM,aAAa,QAA8B,CAAC;AAEzD,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAErD;AAED;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG,UAAU,GAAG,YAAY,CAAC;AAEjD;;;GAGG;AACH,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,8GAA8G;IAC9G,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0FAA0F;IAC1F,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gGAAgG;IAChG,KAAK,EAAE,KAAK,CAAC;CACd;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,0DAA0D;IAC1D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,KAAK,CAAC;CACd;AAED;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,KAAK,CAAC;CACd;AAED,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2DAA2D;IAC3D,IAAI,EAAE,QAAQ,CAAC;IACf,2CAA2C;IAC3C,KAAK,EAAE,KAAK,CAAC;IACb,0DAA0D;IAC1D,WAAW,EAAE,KAAK,CAAC;IACnB,WAAW,EAAE,KAAK,CAAC;IACnB,UAAU,CAAC,EAAE,KAAK,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,8DAA8D;IAC9D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,qCAAqC;IACrC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,KAAK,CAAC;IACb,8FAA8F;IAC9F,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,oBAAoB;IACpB,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,6CAA6C;IAC7C,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,uCAAuC;IACvC,WAAW,EAAE,cAAc,EAAE,CAAC;IAC9B,8BAA8B;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gCAAgC;IAChC,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,SAAS,CAAC;IACrB,yDAAyD;IACzD,cAAc,CAAC,EAAE,KAAK,CAAC;IACvB,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,oDAAoD;IACpD,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,yCAAyC;IACzC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,6CAA6C;IAC7C,WAAW,EAAE,cAAc,EAAE,CAAC;IAC9B,8CAA8C;IAC9C,KAAK,EAAE,QAAQ,EAAE,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,WAAW,CAAC;IACrB,WAAW,EAAE,OAAO,kBAAkB,EAAE,UAAU,EAAE,CAAC;CACtD"}
@@ -0,0 +1,16 @@
1
+ export const DIRECTIONS = ["TB", "BT", "LR", "RL"];
2
+ export const DEFAULT_DIRECTION = "TB";
3
+ /**
4
+ * Identifier rules:
5
+ * - Must match: [A-Za-z_][A-Za-z0-9_-]*
6
+ * - Must start with letter or underscore
7
+ * - May contain letters, digits, underscore, hyphen
8
+ * - No spaces, no Unicode beyond ASCII, no leading digit, no punctuation other than _ and -
9
+ * - Case-sensitive
10
+ * - Display labels are separate concept; IDs are internal keys
11
+ */
12
+ export const IDENTIFIER_RE = /^[A-Za-z_][A-Za-z0-9_-]*$/;
13
+ export function isValidIdentifier(id) {
14
+ return IDENTIFIER_RE.test(id);
15
+ }
16
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAOA,MAAM,CAAC,MAAM,UAAU,GAAyB,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAU,CAAC;AAClF,MAAM,CAAC,MAAM,iBAAiB,GAAc,IAAI,CAAC;AAEjD;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,2BAA2B,CAAC;AAEzD,MAAM,UAAU,iBAAiB,CAAC,EAAU;IAC1C,OAAO,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AAChC,CAAC"}
@@ -0,0 +1,47 @@
1
+ import type { Diagnostic } from "./diagnostics.js";
2
+ import type { FloeDiagram, FloeNode, FloeEdge, FloeGroup } from "./types.js";
3
+ import type { Range } from "./range.js";
4
+ /**
5
+ * Input for semantic validation — separates syntax parsing from semantic checks.
6
+ */
7
+ export interface ValidationInput {
8
+ /** Diagram produced by parser (may contain duplicates before validation) */
9
+ diagram: FloeDiagram;
10
+ /** Diagnostics already produced by parser (syntax errors) */
11
+ diagnostics: Diagnostic[];
12
+ /** Explicit node declarations as parsed (including duplicates, before implicit expansion) */
13
+ explicitNodes: FloeNode[];
14
+ /** Parsed edges */
15
+ edges: FloeEdge[];
16
+ /** All direction declarations as they appeared in source */
17
+ directionDeclarations: Array<{
18
+ value: string;
19
+ range: Range;
20
+ rawLexeme: string;
21
+ }>;
22
+ /** Groups tree */
23
+ groups?: FloeGroup[];
24
+ /** Annotations */
25
+ annotations?: import("./types.js").FloeAnnotation[];
26
+ /** Links */
27
+ links?: import("./types.js").FloeLink[];
28
+ }
29
+ export interface ValidationResult {
30
+ diagram: FloeDiagram;
31
+ diagnostics: Diagnostic[];
32
+ }
33
+ /**
34
+ * Semantic validator
35
+ *
36
+ * Detects:
37
+ * - invalid direction (E001)
38
+ * - invalid identifiers (E002)
39
+ * - duplicate node declarations (E003)
40
+ * - duplicate direction declarations (E004)
41
+ * - malformed / invalid constructs (E005, E008, etc.)
42
+ *
43
+ * Keeps validation separate from parsing so the core model can be reused
44
+ * without parser errors leaking into semantics.
45
+ */
46
+ export declare function validate(input: ValidationInput): ValidationResult;
47
+ //# sourceMappingURL=validator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../../src/validator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE7E,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAExC;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,4EAA4E;IAC5E,OAAO,EAAE,WAAW,CAAC;IACrB,6DAA6D;IAC7D,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,6FAA6F;IAC7F,aAAa,EAAE,QAAQ,EAAE,CAAC;IAC1B,mBAAmB;IACnB,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,4DAA4D;IAC5D,qBAAqB,EAAE,KAAK,CAAC;QAC3B,KAAK,EAAE,MAAM,CAAC;QACd,KAAK,EAAE,KAAK,CAAC;QACb,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC,CAAC;IACH,kBAAkB;IAClB,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC;IACrB,kBAAkB;IAClB,WAAW,CAAC,EAAE,OAAO,YAAY,EAAE,cAAc,EAAE,CAAC;IACpD,YAAY;IACZ,KAAK,CAAC,EAAE,OAAO,YAAY,EAAE,QAAQ,EAAE,CAAC;CACzC;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,WAAW,CAAC;IACrB,WAAW,EAAE,UAAU,EAAE,CAAC;CAC3B;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,eAAe,GAAG,gBAAgB,CAyQjE"}