@geml/geml 1.7.7 → 1.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -21
- package/README.md +285 -285
- package/codemap/adapters/crg.mjs +120 -120
- package/codemap/adapters/joern.mjs +131 -131
- package/codemap/adapters/scip.mjs +658 -658
- package/codemap/browser-stub.mjs +34 -34
- package/codemap/build.mjs +629 -629
- package/codemap/cross-stack.mjs +303 -303
- package/codemap/detect.mjs +399 -399
- package/codemap/emit.mjs +510 -510
- package/codemap/entries.mjs +129 -129
- package/codemap/exclude.mjs +56 -56
- package/codemap/find.mjs +49 -49
- package/codemap/foldings.mjs +110 -110
- package/codemap/joern-export.sc +83 -83
- package/codemap/mcp-server.mjs +434 -431
- package/codemap/normalize.mjs +275 -275
- package/codemap/recipe-trust.mjs +103 -103
- package/codemap/refresh.mjs +313 -313
- package/codemap/render-all.mjs +90 -90
- package/codemap/serve.mjs +585 -585
- package/codemap/sfc-virtualize.mjs +367 -367
- package/codemap/verify.mjs +158 -158
- package/dist/cli.js +121 -121
- package/dist/diagnostics.d.ts +1 -1
- package/dist/diagnostics.js +2 -1
- package/dist/geml.js +45 -24
- package/dist/inline.d.ts +7 -1
- package/dist/inline.js +203 -137
- package/dist/mcp.js +32 -26
- package/dist/render-html.js +35 -35
- package/dist/render.js +192 -184
- package/package.json +1 -1
- package/skill/SKILL.md +167 -167
- package/skill/references/authoring.geml +365 -365
package/dist/geml.js
CHANGED
|
@@ -91,17 +91,26 @@ function jsonErrorLine(e, text, openLineNo) {
|
|
|
91
91
|
export { SEVERITY } from "./diagnostics.js";
|
|
92
92
|
// Type registry: which body mode each typed block uses. Unknown types are a
|
|
93
93
|
// warning and fall back to `raw` (forward compatibility, §3/§8).
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
94
|
+
//
|
|
95
|
+
// A Map, not an object, because the key is the type name off a fence head — i.e.
|
|
96
|
+
// document-controlled. Indexing a plain object with it answered for the whole
|
|
97
|
+
// prototype chain: `=== constructor` (also toString, valueOf, hasOwnProperty,
|
|
98
|
+
// isPrototypeOf, propertyIsEnumerable, toLocaleString) returned an inherited
|
|
99
|
+
// FUNCTION, which is not undefined, so the unknown-block-type warning never
|
|
100
|
+
// fired and a function reached the model's `mode` field — a value the published
|
|
101
|
+
// `BodyMode` type says cannot occur, and one JSON.stringify silently drops.
|
|
102
|
+
// Every other document-keyed registry here is already a Set or a Map.
|
|
103
|
+
const REGISTRY = new Map([
|
|
104
|
+
["code", "raw"],
|
|
105
|
+
["diagram", "raw"],
|
|
106
|
+
["math", "raw"],
|
|
107
|
+
["table", "raw"], // structured table parsing lands in M3
|
|
108
|
+
["data", "raw"], // GEP-0005: value tree — a format engine parses the raw body in a second stage
|
|
109
|
+
["embed", "raw"], // block transclusion: `src=` points at the content, body unused
|
|
110
|
+
["note", "flow"],
|
|
111
|
+
["text", "flow"], // addressable prose container: an id/attrs for a run of flow, no callout chrome
|
|
112
|
+
["meta", "data"],
|
|
113
|
+
]);
|
|
105
114
|
// §7: built-in diagram renderer registry. Unknown formats are a warning (the
|
|
106
115
|
// processor keeps the body raw rather than interpreting it).
|
|
107
116
|
const DIAGRAM_RENDERERS = new Set(["mermaid", "graphviz", "dot", "d2", "plantuml", "geml-chart", "geml-code-graph"]);
|
|
@@ -184,7 +193,7 @@ function slug(text) {
|
|
|
184
193
|
return text
|
|
185
194
|
.toLowerCase()
|
|
186
195
|
.replace(/`[^`]*`/g, "")
|
|
187
|
-
.replace(/[^\p{L}\p{N}\s
|
|
196
|
+
.replace(/[^\p{L}\p{N}\s\-_]/gu, "")
|
|
188
197
|
.trim()
|
|
189
198
|
.replace(/\s+/g, "-");
|
|
190
199
|
}
|
|
@@ -439,7 +448,7 @@ function scanBlocks(lines, base, ctx, depth = 0) {
|
|
|
439
448
|
const how = attrs.id !== undefined ? `${"=".repeat(openLen)} or \`=== #${attrs.id}\`` : "=".repeat(openLen);
|
|
440
449
|
diags.push({ severity: "error", code: "unterminated-block", message: `unterminated \`${type}\` block (no matching ${how})`, line: openLineNo });
|
|
441
450
|
}
|
|
442
|
-
let mode = REGISTRY
|
|
451
|
+
let mode = REGISTRY.get(type);
|
|
443
452
|
if (mode === undefined) {
|
|
444
453
|
diags.push({ severity: "warning", code: "unknown-block-type", message: `unknown block type \`${type}\`; body kept as raw`, line: openLineNo });
|
|
445
454
|
mode = "raw";
|
|
@@ -1111,8 +1120,9 @@ function gatherIds(source) {
|
|
|
1111
1120
|
}
|
|
1112
1121
|
// Pre-scan for `=== meta` blocks (at any fence depth) and merge their
|
|
1113
1122
|
// `key=val` lines, so `{{key}}` interpolation can resolve forward references.
|
|
1114
|
-
function collectMeta(lines) {
|
|
1123
|
+
function collectMeta(lines, diags) {
|
|
1115
1124
|
const meta = new Map();
|
|
1125
|
+
const firstLine = new Map(); // key → 1-based line of the defining fence
|
|
1116
1126
|
for (let i = 0; i < lines.length; i++) {
|
|
1117
1127
|
const open = FENCE_OPEN.exec(lines[i]);
|
|
1118
1128
|
if (!open || open[2] !== "meta")
|
|
@@ -1122,8 +1132,17 @@ function collectMeta(lines) {
|
|
|
1122
1132
|
let j = i + 1;
|
|
1123
1133
|
for (; j < lines.length && !isCloseFence(lines[j], len); j++)
|
|
1124
1134
|
body.push(lines[j]);
|
|
1125
|
-
for (const [k, v] of Object.entries(parseData(body)))
|
|
1126
|
-
meta.
|
|
1135
|
+
for (const [k, v] of Object.entries(parseData(body))) {
|
|
1136
|
+
if (meta.has(k)) {
|
|
1137
|
+
diags?.push({ severity: "warning", code: "duplicate-meta-key",
|
|
1138
|
+
message: `meta key \`${k}\` already defined at line ${firstLine.get(k)}; later definition at line ${i + 1} is ignored`,
|
|
1139
|
+
line: i + 1 });
|
|
1140
|
+
}
|
|
1141
|
+
else {
|
|
1142
|
+
meta.set(k, String(v));
|
|
1143
|
+
firstLine.set(k, i + 1);
|
|
1144
|
+
}
|
|
1145
|
+
}
|
|
1127
1146
|
i = j;
|
|
1128
1147
|
}
|
|
1129
1148
|
return meta;
|
|
@@ -1283,13 +1302,14 @@ function resolveCodeSources(ctx, opts) {
|
|
|
1283
1302
|
if (slice === null)
|
|
1284
1303
|
continue;
|
|
1285
1304
|
const hasBody = (block.raw ?? []).some((l) => l.trim() !== "");
|
|
1286
|
-
if (
|
|
1287
|
-
block
|
|
1305
|
+
if (hasBody) {
|
|
1306
|
+
// A code block must not carry both src= and an inline body (§3.3).
|
|
1307
|
+
ctx.diags.push({ severity: "error", code: "code-src-and-body",
|
|
1308
|
+
message: `code: carries both \`src=\` and an inline body; exactly one is permitted`,
|
|
1309
|
+
line });
|
|
1288
1310
|
}
|
|
1289
|
-
else
|
|
1290
|
-
|
|
1291
|
-
// Silence would let the two drift — the very thing the route prevents.
|
|
1292
|
-
ctx.diags.push({ severity: "warning", code: "stale-code-snapshot", message: `code block body differs from its source \`${target}\` — the body is a snapshot and is now out of date`, line });
|
|
1311
|
+
else {
|
|
1312
|
+
block.raw = slice;
|
|
1293
1313
|
}
|
|
1294
1314
|
}
|
|
1295
1315
|
}
|
|
@@ -1547,7 +1567,8 @@ function resolveCharts(ctx, opts) {
|
|
|
1547
1567
|
}
|
|
1548
1568
|
export function parse(source, opts = {}) {
|
|
1549
1569
|
const lines = normalizeSource(source).split("\n");
|
|
1550
|
-
const
|
|
1570
|
+
const diags = [];
|
|
1571
|
+
const ctx = { diags, ids: new Map(), refs: [], meta: collectMeta(lines, diags), resolveDoc: opts.resolveDoc };
|
|
1551
1572
|
const children = scanBlocks(lines, 0, ctx);
|
|
1552
1573
|
// Table sources first: a chart reads the build-time model of the table it
|
|
1553
1574
|
// charts, so that model has to be filled before charts are resolved.
|
|
@@ -1659,7 +1680,7 @@ units) {
|
|
|
1659
1680
|
// Only a flow body is scanned for nested blocks (raw/data bodies are
|
|
1660
1681
|
// opaque), so an id inside a `code` body is *not* addressable — exactly
|
|
1661
1682
|
// the parser's contract.
|
|
1662
|
-
if ((REGISTRY
|
|
1683
|
+
if ((REGISTRY.get(type) ?? "raw") === "flow" && depth < MAX_NESTING) {
|
|
1663
1684
|
collectSpans(lines.slice(i + 1, closed ? end - 1 : end), base + i + 1, out, ctx, depth + 1, units);
|
|
1664
1685
|
}
|
|
1665
1686
|
i = end;
|
package/dist/inline.d.ts
CHANGED
|
@@ -70,4 +70,10 @@ export interface RefSink {
|
|
|
70
70
|
export declare const META_REF_SRC = "\\{\\{\\s*([A-Za-z_][A-Za-z0-9_-]*)\\s*\\}\\}";
|
|
71
71
|
export declare function schemeOf(url: string): string | null;
|
|
72
72
|
export declare function isSafeUrl(url: string, allowDataImage?: boolean): boolean;
|
|
73
|
-
|
|
73
|
+
interface Pairs {
|
|
74
|
+
br: Int32Array;
|
|
75
|
+
pa: Int32Array;
|
|
76
|
+
off: number;
|
|
77
|
+
}
|
|
78
|
+
export declare function parseInline(s: string, line: number, sink: RefSink, depth?: number, pairs?: Pairs): Inline[];
|
|
79
|
+
export {};
|