@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.
- package/LICENSE +21 -0
- package/dist/src/cli/check.d.ts +14 -0
- package/dist/src/cli/check.d.ts.map +1 -0
- package/dist/src/cli/check.js +88 -0
- package/dist/src/cli/check.js.map +1 -0
- package/dist/src/cli/format.d.ts +9 -0
- package/dist/src/cli/format.d.ts.map +1 -0
- package/dist/src/cli/format.js +114 -0
- package/dist/src/cli/format.js.map +1 -0
- package/dist/src/cli/main.d.ts +19 -0
- package/dist/src/cli/main.d.ts.map +1 -0
- package/dist/src/cli/main.js +207 -0
- package/dist/src/cli/main.js.map +1 -0
- package/dist/src/cli/render.d.ts +7 -0
- package/dist/src/cli/render.d.ts.map +1 -0
- package/dist/src/cli/render.js +90 -0
- package/dist/src/cli/render.js.map +1 -0
- package/dist/src/diagnostics.d.ts +32 -0
- package/dist/src/diagnostics.d.ts.map +1 -0
- package/dist/src/diagnostics.js +4 -0
- package/dist/src/diagnostics.js.map +1 -0
- package/dist/src/index.d.ts +40 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +64 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/language/completion.d.ts +6 -0
- package/dist/src/language/completion.d.ts.map +1 -0
- package/dist/src/language/completion.js +363 -0
- package/dist/src/language/completion.js.map +1 -0
- package/dist/src/language/definitions.d.ts +9 -0
- package/dist/src/language/definitions.d.ts.map +1 -0
- package/dist/src/language/definitions.js +70 -0
- package/dist/src/language/definitions.js.map +1 -0
- package/dist/src/language/diagnosticsService.d.ts +14 -0
- package/dist/src/language/diagnosticsService.d.ts.map +1 -0
- package/dist/src/language/diagnosticsService.js +37 -0
- package/dist/src/language/diagnosticsService.js.map +1 -0
- package/dist/src/language/folding.d.ts +8 -0
- package/dist/src/language/folding.d.ts.map +1 -0
- package/dist/src/language/folding.js +58 -0
- package/dist/src/language/folding.js.map +1 -0
- package/dist/src/language/formatting.d.ts +5 -0
- package/dist/src/language/formatting.d.ts.map +1 -0
- package/dist/src/language/formatting.js +274 -0
- package/dist/src/language/formatting.js.map +1 -0
- package/dist/src/language/highlighting.d.ts +9 -0
- package/dist/src/language/highlighting.d.ts.map +1 -0
- package/dist/src/language/highlighting.js +74 -0
- package/dist/src/language/highlighting.js.map +1 -0
- package/dist/src/language/hover.d.ts +6 -0
- package/dist/src/language/hover.d.ts.map +1 -0
- package/dist/src/language/hover.js +197 -0
- package/dist/src/language/hover.js.map +1 -0
- package/dist/src/language/indentation.d.ts +15 -0
- package/dist/src/language/indentation.d.ts.map +1 -0
- package/dist/src/language/indentation.js +97 -0
- package/dist/src/language/indentation.js.map +1 -0
- package/dist/src/language/index.d.ts +54 -0
- package/dist/src/language/index.d.ts.map +1 -0
- package/dist/src/language/index.js +85 -0
- package/dist/src/language/index.js.map +1 -0
- package/dist/src/language/references.d.ts +12 -0
- package/dist/src/language/references.d.ts.map +1 -0
- package/dist/src/language/references.js +35 -0
- package/dist/src/language/references.js.map +1 -0
- package/dist/src/language/rename.d.ts +18 -0
- package/dist/src/language/rename.d.ts.map +1 -0
- package/dist/src/language/rename.js +53 -0
- package/dist/src/language/rename.js.map +1 -0
- package/dist/src/language/semanticModel.d.ts +21 -0
- package/dist/src/language/semanticModel.d.ts.map +1 -0
- package/dist/src/language/semanticModel.js +43 -0
- package/dist/src/language/semanticModel.js.map +1 -0
- package/dist/src/language/symbols.d.ts +9 -0
- package/dist/src/language/symbols.d.ts.map +1 -0
- package/dist/src/language/symbols.js +160 -0
- package/dist/src/language/symbols.js.map +1 -0
- package/dist/src/language/types.d.ts +49 -0
- package/dist/src/language/types.d.ts.map +1 -0
- package/dist/src/language/types.js +2 -0
- package/dist/src/language/types.js.map +1 -0
- package/dist/src/language/utils.d.ts +24 -0
- package/dist/src/language/utils.d.ts.map +1 -0
- package/dist/src/language/utils.js +154 -0
- package/dist/src/language/utils.js.map +1 -0
- package/dist/src/layout/dagre.d.ts +13 -0
- package/dist/src/layout/dagre.d.ts.map +1 -0
- package/dist/src/layout/dagre.js +229 -0
- package/dist/src/layout/dagre.js.map +1 -0
- package/dist/src/layout/index.d.ts +15 -0
- package/dist/src/layout/index.d.ts.map +1 -0
- package/dist/src/layout/index.js +22 -0
- package/dist/src/layout/index.js.map +1 -0
- package/dist/src/layout/simple.d.ts +20 -0
- package/dist/src/layout/simple.d.ts.map +1 -0
- package/dist/src/layout/simple.js +674 -0
- package/dist/src/layout/simple.js.map +1 -0
- package/dist/src/layout/types.d.ts +65 -0
- package/dist/src/layout/types.d.ts.map +1 -0
- package/dist/src/layout/types.js +2 -0
- package/dist/src/layout/types.js.map +1 -0
- package/dist/src/lexer.d.ts +25 -0
- package/dist/src/lexer.d.ts.map +1 -0
- package/dist/src/lexer.js +280 -0
- package/dist/src/lexer.js.map +1 -0
- package/dist/src/lsp/documents.d.ts +24 -0
- package/dist/src/lsp/documents.d.ts.map +1 -0
- package/dist/src/lsp/documents.js +97 -0
- package/dist/src/lsp/documents.js.map +1 -0
- package/dist/src/lsp/server.d.ts +70 -0
- package/dist/src/lsp/server.d.ts.map +1 -0
- package/dist/src/lsp/server.js +623 -0
- package/dist/src/lsp/server.js.map +1 -0
- package/dist/src/lsp/utils.d.ts +47 -0
- package/dist/src/lsp/utils.d.ts.map +1 -0
- package/dist/src/lsp/utils.js +142 -0
- package/dist/src/lsp/utils.js.map +1 -0
- package/dist/src/parser.d.ts +106 -0
- package/dist/src/parser.d.ts.map +1 -0
- package/dist/src/parser.js +1018 -0
- package/dist/src/parser.js.map +1 -0
- package/dist/src/pipeline.d.ts +51 -0
- package/dist/src/pipeline.d.ts.map +1 -0
- package/dist/src/pipeline.js +65 -0
- package/dist/src/pipeline.js.map +1 -0
- package/dist/src/range.d.ts +24 -0
- package/dist/src/range.d.ts.map +1 -0
- package/dist/src/range.js +20 -0
- package/dist/src/range.js.map +1 -0
- package/dist/src/render/index.d.ts +3 -0
- package/dist/src/render/index.d.ts.map +1 -0
- package/dist/src/render/index.js +3 -0
- package/dist/src/render/index.js.map +1 -0
- package/dist/src/render/shapes.d.ts +20 -0
- package/dist/src/render/shapes.d.ts.map +1 -0
- package/dist/src/render/shapes.js +110 -0
- package/dist/src/render/shapes.js.map +1 -0
- package/dist/src/render/svg.d.ts +19 -0
- package/dist/src/render/svg.d.ts.map +1 -0
- package/dist/src/render/svg.js +227 -0
- package/dist/src/render/svg.js.map +1 -0
- package/dist/src/security/url.d.ts +7 -0
- package/dist/src/security/url.d.ts.map +1 -0
- package/dist/src/security/url.js +27 -0
- package/dist/src/security/url.js.map +1 -0
- package/dist/src/types.d.ts +111 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js +16 -0
- package/dist/src/types.js.map +1 -0
- package/dist/src/validator.d.ts +47 -0
- package/dist/src/validator.d.ts.map +1 -0
- package/dist/src/validator.js +235 -0
- package/dist/src/validator.js.map +1 -0
- 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, "&")
|
|
169
|
+
.replace(/</g, "<")
|
|
170
|
+
.replace(/>/g, ">")
|
|
171
|
+
.replace(/"/g, """)
|
|
172
|
+
.replace(/'/g, "'");
|
|
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"}
|