@geml/geml 1.4.5 → 1.5.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/codemap/mcp-server.mjs +1 -1
- package/codemap/render-all.mjs +16 -3
- package/codemap/serve.mjs +8 -1
- package/dist/diagnostics.d.ts +1 -1
- package/dist/diagnostics.js +10 -0
- package/dist/geml.d.ts +4 -0
- package/dist/geml.js +529 -57
- package/dist/inline.d.ts +20 -0
- package/dist/inline.js +29 -2
- package/dist/mcp.js +13 -5
- package/dist/render.d.ts +19 -0
- package/dist/render.js +349 -24
- package/dist/serialize.js +9 -1
- package/dist/table.js +5 -3
- package/dist/to-md.js +13 -2
- package/package.json +5 -2
package/codemap/mcp-server.mjs
CHANGED
|
@@ -290,7 +290,7 @@ export const TOOLS = [
|
|
|
290
290
|
// EVERY line carries the full `doc.geml#id`, including same-document
|
|
291
291
|
// targets that profile §4 would abbreviate to `#id`. The reader here is
|
|
292
292
|
// an agent, and each line has to be usable as-is for the next
|
|
293
|
-
// `
|
|
293
|
+
// `geml_codemap_node`/`geml_codemap_callchain` call. A bare id would make it infer the
|
|
294
294
|
// document from the line's ancestors — cheaper output, one more thing to
|
|
295
295
|
// get wrong.
|
|
296
296
|
const walk = (doc, id, level, prefix, last) => {
|
package/codemap/render-all.mjs
CHANGED
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
// graph area (nested frame), so the whole map is browsable offline — this is
|
|
9
9
|
// the "copy the folder to someone" mode. For a live view that never goes
|
|
10
10
|
// stale, use `geml codemap serve` instead.
|
|
11
|
-
import { readdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
12
|
-
import { join, basename } from "node:path";
|
|
11
|
+
import { readdirSync, readFileSync, writeFileSync, realpathSync } from "node:fs";
|
|
12
|
+
import { join, basename, sep, resolve as resolvePath } from "node:path";
|
|
13
13
|
import { parse, renderHtml } from "../dist/geml.js";
|
|
14
14
|
|
|
15
15
|
if (process.argv[2] === "--help" || process.argv[2] === "-h") {
|
|
@@ -25,9 +25,22 @@ const dir = process.argv[2] || ".geml-code-graph";
|
|
|
25
25
|
// text + parsed docs live in memory for the duration of the run).
|
|
26
26
|
const texts = new Map(); // rel -> text | null
|
|
27
27
|
const parsed = new Map(); // text -> Document
|
|
28
|
+
// `rel` is document-controlled — a `src=` composed by the renderer — and the
|
|
29
|
+
// output of this command is a published artifact, so an unconfined read here
|
|
30
|
+
// writes any .geml on the filesystem into a file that then gets served. Gate on
|
|
31
|
+
// the realpath, the same shape `serve` and the CLI resolver use.
|
|
32
|
+
let realDir = null;
|
|
33
|
+
try { realDir = realpathSync(resolvePath(dir)); } catch { realDir = null; }
|
|
28
34
|
const loadDoc = (rel) => {
|
|
29
35
|
if (!texts.has(rel)) {
|
|
30
|
-
|
|
36
|
+
let text = null;
|
|
37
|
+
if (realDir !== null) {
|
|
38
|
+
try {
|
|
39
|
+
const real = realpathSync(join(dir, rel));
|
|
40
|
+
if (real === realDir || real.startsWith(realDir + sep)) text = readFileSync(real, "utf8");
|
|
41
|
+
} catch { text = null; }
|
|
42
|
+
}
|
|
43
|
+
texts.set(rel, text);
|
|
31
44
|
}
|
|
32
45
|
return texts.get(rel);
|
|
33
46
|
};
|
package/codemap/serve.mjs
CHANGED
|
@@ -182,7 +182,14 @@ export function createApp({ dir, root, port, cacheMb, srcRoot }) {
|
|
|
182
182
|
return entry;
|
|
183
183
|
};
|
|
184
184
|
const loadDoc = (rel) => {
|
|
185
|
-
|
|
185
|
+
// `rel` is document-controlled — it is whatever a `src=` composed — so it goes
|
|
186
|
+
// through the same symlink-safe gate the URL router uses. Without it a
|
|
187
|
+
// transclusion could name `../../../secret.geml` and this loader would read
|
|
188
|
+
// and serve any .geml on the filesystem. (confine is declared below; loadDoc
|
|
189
|
+
// is only ever called while handling a request, so the closure is resolved.)
|
|
190
|
+
const abs = confine(join(root, rel));
|
|
191
|
+
if (abs === null) return null;
|
|
192
|
+
const e = loadCached(abs);
|
|
186
193
|
return e ? e.text : null;
|
|
187
194
|
};
|
|
188
195
|
// loadDoc hands out the cached string instance, so the by-text lookup hits
|
package/dist/diagnostics.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type DiagnosticCode = "unterminated-block" | "unknown-block-type" | "block-nesting-too-deep" | "list-nesting-too-deep" | "inline-nesting-too-deep" | "duplicate-id" | "unresolved-reference" | "unresolved-footnote" | "unresolved-cross-document-reference" | "unresolvable-document" | "unchecked-cross-document-reference" | "unknown-metadata-reference" | "table-src-and-body" | "unknown-table-format" | "bad-compute-formula" | "unlexable-compute-formula" | "compute-error" | "bad-summary-entry" | "summary-unknown-column" | "unlexable-summary-expression" | "summary-error" | "bad-span" | "span-outside-table" | "unknown-diagram-format" | "ignored-diagram-body" | "code-graph-missing-src" | "code-graph-unresolvable-document" | "chart-missing-data" | "chart-data-not-a-table" | "chart-missing-type" | "chart-unknown-type" | "chart-unknown-rows-scope" | "chart-missing-channel" | "chart-empty-channel" | "chart-unknown-column" | "chart-unused-channel" | "chart-missing-summary-row" | "chart-summary-row-unavailable" | "chart-non-numeric-value";
|
|
1
|
+
export type DiagnosticCode = "unterminated-block" | "unknown-block-type" | "block-nesting-too-deep" | "list-nesting-too-deep" | "inline-nesting-too-deep" | "duplicate-id" | "unresolved-reference" | "unresolved-footnote" | "unresolved-cross-document-reference" | "unresolvable-document" | "unchecked-cross-document-reference" | "embed-missing-src" | "ignored-embed-body" | "transclusion-cycle" | "embed-target-not-geml" | "media-target-is-document" | "inline-transclusion-not-inline" | "unsafe-embed-scheme" | "source-attr-conflict" | "unresolvable-table-source" | "table-source-not-a-table" | "unknown-metadata-reference" | "table-src-and-body" | "unknown-table-format" | "bad-compute-formula" | "unlexable-compute-formula" | "compute-error" | "bad-summary-entry" | "summary-unknown-column" | "unlexable-summary-expression" | "summary-error" | "bad-span" | "span-outside-table" | "unknown-diagram-format" | "ignored-diagram-body" | "code-graph-missing-src" | "code-graph-unresolvable-document" | "chart-missing-data" | "chart-data-not-a-table" | "chart-missing-type" | "chart-unknown-type" | "chart-unknown-rows-scope" | "chart-missing-channel" | "chart-empty-channel" | "chart-unknown-column" | "chart-unused-channel" | "chart-missing-summary-row" | "chart-summary-row-unavailable" | "chart-non-numeric-value";
|
|
2
2
|
export interface Diagnostic {
|
|
3
3
|
severity: "error" | "warning";
|
|
4
4
|
code: DiagnosticCode;
|
package/dist/diagnostics.js
CHANGED
|
@@ -24,6 +24,16 @@ export const SEVERITY = {
|
|
|
24
24
|
"unresolved-cross-document-reference": "error",
|
|
25
25
|
"unresolvable-document": "error",
|
|
26
26
|
"unchecked-cross-document-reference": "warning",
|
|
27
|
+
"embed-missing-src": "error",
|
|
28
|
+
"ignored-embed-body": "warning",
|
|
29
|
+
"transclusion-cycle": "error",
|
|
30
|
+
"embed-target-not-geml": "error",
|
|
31
|
+
"media-target-is-document": "error",
|
|
32
|
+
"inline-transclusion-not-inline": "error",
|
|
33
|
+
"unsafe-embed-scheme": "error",
|
|
34
|
+
"source-attr-conflict": "error",
|
|
35
|
+
"unresolvable-table-source": "error",
|
|
36
|
+
"table-source-not-a-table": "error",
|
|
27
37
|
"unknown-metadata-reference": "error",
|
|
28
38
|
"table-src-and-body": "error",
|
|
29
39
|
"unknown-table-format": "warning",
|
package/dist/geml.d.ts
CHANGED
|
@@ -64,7 +64,11 @@ export interface Document {
|
|
|
64
64
|
}
|
|
65
65
|
export interface ParseOptions {
|
|
66
66
|
resolveDoc?: (doc: string) => string | null;
|
|
67
|
+
self?: string;
|
|
67
68
|
}
|
|
69
|
+
export declare function projectableInlines(blocks: Block[], id: string): {
|
|
70
|
+
inlines: Inline[];
|
|
71
|
+
} | "not-inline" | null;
|
|
68
72
|
export declare function parse(source: string, opts?: ParseOptions): Document;
|
|
69
73
|
export interface Span {
|
|
70
74
|
start: number;
|