@geml/geml 1.4.2 → 1.4.3
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 +186 -155
- 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 +29 -29
- package/codemap/build.mjs +609 -609
- package/codemap/cross-stack.mjs +303 -303
- package/codemap/detect.mjs +399 -399
- package/codemap/emit.mjs +480 -480
- package/codemap/entries.mjs +129 -129
- package/codemap/exclude.mjs +52 -52
- package/codemap/find.mjs +63 -63
- package/codemap/foldings.mjs +110 -110
- package/codemap/joern-export.sc +83 -83
- package/codemap/mcp-server.mjs +172 -172
- package/codemap/normalize.mjs +275 -275
- package/codemap/recipe-trust.mjs +103 -103
- package/codemap/refresh.mjs +310 -310
- package/codemap/render-all.mjs +64 -64
- package/codemap/serve.mjs +578 -578
- package/codemap/sfc-virtualize.mjs +367 -367
- package/codemap/verify.mjs +148 -148
- package/dist/chart.d.ts +2 -0
- package/dist/chart.js +15 -15
- package/dist/diagnostics.d.ts +9 -0
- package/dist/diagnostics.js +73 -0
- package/dist/geml.d.ts +2 -5
- package/dist/geml.js +191 -98
- package/dist/history.d.ts +10 -0
- package/dist/history.js +25 -24
- package/dist/inline.js +7 -7
- package/dist/mcp.d.ts +18 -0
- package/dist/mcp.js +528 -0
- package/dist/render.js +136 -136
- package/dist/table.d.ts +2 -0
- package/dist/table.js +11 -11
- package/package.json +62 -62
package/dist/render.js
CHANGED
|
@@ -925,143 +925,143 @@ function trunc(s, n) {
|
|
|
925
925
|
// ---------------------------------------------------------------------------
|
|
926
926
|
// Page shell, inline CSS, inline interactivity JS
|
|
927
927
|
// ---------------------------------------------------------------------------
|
|
928
|
-
export const CSS = `
|
|
929
|
-
:root { --fg:#1f2328; --muted:#656d76; --bd:#d0d7de; --bg:#fff; --accent:#2563eb; --code-bg:#f6f8fa; }
|
|
930
|
-
* { box-sizing: border-box; }
|
|
931
|
-
body { margin:0; color:var(--fg); background:#fafbfc; font:16px/1.6 -apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,"PingFang SC","Microsoft Yahei",sans-serif; }
|
|
932
|
-
main { max-width: 860px; margin: 0 auto; padding: 48px 24px 96px; background:var(--bg); }
|
|
933
|
-
h1,h2,h3,h4,h5,h6 { line-height:1.25; margin:1.6em 0 .6em; scroll-margin-top:16px; }
|
|
934
|
-
h1 { font-size:2em; border-bottom:1px solid var(--bd); padding-bottom:.3em; }
|
|
935
|
-
h2 { font-size:1.5em; border-bottom:1px solid var(--bd); padding-bottom:.3em; }
|
|
936
|
-
h3 { font-size:1.25em; } h4 { font-size:1em; }
|
|
937
|
-
p { margin:.7em 0; }
|
|
938
|
-
a { color:var(--accent); text-decoration:none; } a:hover { text-decoration:underline; }
|
|
939
|
-
code { background:var(--code-bg); padding:.15em .35em; border-radius:6px; font:.88em ui-monospace,SFMono-Regular,Menlo,Consolas,monospace; }
|
|
940
|
-
pre { background:var(--code-bg); padding:14px 16px; border-radius:8px; overflow:auto; }
|
|
941
|
-
pre code { background:none; padding:0; font-size:.85em; }
|
|
942
|
-
pre.output { background:#0d1117; color:#e6edf3; }
|
|
943
|
-
pre.output code { color:inherit; }
|
|
944
|
-
ul,ol { padding-left:1.6em; } li { margin:.2em 0; }
|
|
945
|
-
ul.task-list { list-style:none; padding-left:.2em; }
|
|
946
|
-
li.task input[type=checkbox] { appearance:none; -webkit-appearance:none; width:1.1em; height:1.1em; margin:0 .5em 0 0; vertical-align:-.2em; border:1.5px solid #c8ccd0; border-radius:4px; background:#fff; position:relative; opacity:1; cursor:default; box-sizing:border-box; }
|
|
947
|
-
li.task input[type=checkbox]:checked { background-color:#1f883d; border-color:#1f883d; }
|
|
948
|
-
li.task input[type=checkbox]:checked::after { content:"✓"; position:absolute; top:0; right:0; bottom:0; left:0; display:flex; align-items:center; justify-content:center; color:#fff; font-size:.8em; line-height:1; font-weight:700; }
|
|
949
|
-
aside.callout { border-left:4px solid var(--accent); background:#f0f6ff; padding:.4em 16px; border-radius:0 8px 8px 0; margin:1em 0; }
|
|
950
|
-
aside.aside { border-left-color:#8b949e; background:#f6f8fa; }
|
|
951
|
-
aside.warning { border-left-color:#d97706; background:#fff8f0; }
|
|
952
|
-
aside.callout > :first-child { margin-top:0; } aside.callout > :last-child { margin-bottom:0; }
|
|
953
|
-
figure { margin:1.2em 0; }
|
|
954
|
-
figcaption { color:var(--muted); font-size:.86em; text-align:center; margin-top:.5em; }
|
|
955
|
-
table.geml-table { border-collapse:collapse; width:100%; font-size:.92em; }
|
|
956
|
-
table.geml-table th, table.geml-table td { border:1px solid var(--bd); padding:6px 12px; }
|
|
957
|
-
table.geml-table thead th { background:var(--code-bg); cursor:pointer; user-select:none; white-space:nowrap; }
|
|
958
|
-
table.geml-table thead th::after { content:" \\2195"; color:var(--muted); font-size:.8em; }
|
|
959
|
-
table.geml-table thead th.asc::after { content:" \\2191"; color:var(--accent); }
|
|
960
|
-
table.geml-table thead th.desc::after { content:" \\2193"; color:var(--accent); }
|
|
961
|
-
table.geml-table tbody tr:nth-child(2n) { background:#fafbfc; }
|
|
962
|
-
table.geml-table td.computed { color:#0a7c52; }
|
|
963
|
-
table.geml-table tfoot td { background:var(--code-bg); font-weight:600; border-top:2px solid var(--bd); }
|
|
964
|
-
.table-tools { margin-bottom:6px; } .table-filter { width:240px; max-width:100%; padding:5px 9px; border:1px solid var(--bd); border-radius:7px; font-size:.85em; }
|
|
965
|
-
.table-figure details > summary { cursor:pointer; color:var(--muted); font-size:.86em; padding:4px 0; }
|
|
966
|
-
.table-note { color:var(--muted); font-size:.82em; margin:6px 0 0; }
|
|
967
|
-
.geml-chart { width:100%; height:auto; background:var(--bg); border:1px solid var(--bd); border-radius:8px; }
|
|
968
|
-
.c-title { font-size:15px; font-weight:600; fill:var(--fg); }
|
|
969
|
-
.c-grid { stroke:#eaecef; } .c-axis { stroke:#aab1b8; } .c-tick { font-size:11px; fill:var(--muted); } .c-legend { font-size:12px; fill:var(--fg); }
|
|
970
|
-
.media { max-width:100%; border-radius:8px; }
|
|
971
|
-
.diagram-src { color:var(--muted); } .render-error { color:#cf222e; }
|
|
972
|
-
.math-block { overflow-x:auto; padding:.4em 0; }
|
|
973
|
-
sup.fn a { font-size:.75em; }
|
|
974
|
-
.geml-footer { max-width:860px; margin:0 auto; padding:16px 24px 40px; color:var(--muted); font-size:.82em; }
|
|
975
|
-
.geml-footer code { font-size:.95em; }
|
|
976
|
-
.code-graph { margin:1.4em 0; }
|
|
977
|
-
.cg-mount { border:1px solid var(--bd); border-radius:8px; padding:10px 12px; background:var(--bg); }
|
|
978
|
-
.cg-scroll { overflow:auto; min-height:52vh; max-height:72vh; }
|
|
979
|
-
.cg-svg { display:block; }
|
|
980
|
-
.cg-search-wrap { position:relative; display:inline-block; }
|
|
981
|
-
.cg-search { font:12px/1.4 inherit; padding:2px 7px; border:1px solid var(--bd); border-radius:4px; background:var(--bg); color:var(--fg); min-width:13ch; }
|
|
982
|
-
.cg-search-menu { position:absolute; z-index:30; top:calc(100% + 2px); left:0; min-width:24ch; max-width:52ch; max-height:52vh; overflow:auto; background:var(--bg); border:1px solid var(--bd); border-radius:6px; box-shadow:0 6px 20px rgba(0,0,0,.18); }
|
|
983
|
-
.cg-search-row { display:block; width:100%; text-align:left; padding:4px 9px 4px 18px; border:0; background:none; color:var(--fg); cursor:pointer; font:12px/1.4 inherit; }
|
|
984
|
-
.cg-search-row:hover { background:var(--bd); }
|
|
985
|
-
.cg-search-count { position:sticky; top:0; padding:4px 9px; font-size:11px; opacity:.65; background:var(--bg); border-bottom:1px solid var(--bd); }
|
|
986
|
-
.cg-search-grp { padding:6px 9px 2px; font-size:11px; font-weight:600; opacity:.7; border-top:1px solid var(--bd); }
|
|
987
|
-
.cg-search-grp:first-of-type { border-top:0; }
|
|
988
|
-
.cg-stage { display:flex; gap:10px; align-items:flex-start; }
|
|
989
|
-
.cg-stage .cg-scroll { flex:1 1 auto; min-width:0; }
|
|
990
|
-
.cg-src { flex:0 0 42%; max-width:46%; display:flex; flex-direction:column; border:1px solid var(--bd); border-radius:6px; overflow:hidden; background:var(--bg); }
|
|
991
|
-
.cg-src-hd { display:flex; gap:8px; align-items:center; justify-content:space-between; padding:4px 8px; border-bottom:1px solid var(--bd); color:var(--muted); font:.76em ui-monospace,Consolas,monospace; word-break:break-all; }
|
|
992
|
-
.cg-src-hd button { font:inherit; border:1px solid var(--bd); border-radius:5px; background:transparent; color:var(--muted); cursor:pointer; padding:0 6px; }
|
|
993
|
-
.cg-src-body { margin:0; padding:8px 10px; overflow:auto; max-height:72vh; color:var(--fg); font:12px/1.5 ui-monospace,Consolas,monospace; white-space:pre; }
|
|
994
|
-
.cg-src-note { color:var(--muted); font-style:italic; white-space:pre-wrap; }
|
|
995
|
-
.cg-bar { display:flex; gap:8px; align-items:center; flex-wrap:wrap; font-size:.82em; color:var(--muted); margin-bottom:6px; }
|
|
996
|
-
.cg-bar button { font:inherit; padding:1px 8px; border:1px solid var(--bd); border-radius:5px; background:transparent; cursor:pointer; }
|
|
997
|
-
.cg-crumb .cg-seg { border:0; border-radius:0; padding:0; background:none; color:var(--accent); cursor:pointer; font:inherit; }
|
|
998
|
-
.cg-crumb .cg-seg:hover { text-decoration:underline; }
|
|
999
|
-
.cg-frame { display:block; width:100%; height:72vh; border:0; background:var(--bg); }
|
|
1000
|
-
.cg-flash { color:#b42318; }
|
|
1001
|
-
.cg-legend { display:flex; gap:14px; align-items:center; justify-content:space-between; flex-wrap:wrap; font-size:.75em; color:var(--muted); margin-top:6px; }
|
|
1002
|
-
.cg-upbtn { cursor:pointer; }
|
|
1003
|
-
.cg-upbtn circle { fill:#fff; stroke:#94a3b8; }
|
|
1004
|
-
.cg-upbtn text { font-size:11px; fill:#57606a; }
|
|
1005
|
-
.cg-upbtn:hover circle { stroke:var(--accent); stroke-width:1.6; }
|
|
1006
|
-
.cg-upbtn:hover text { fill:var(--accent); }
|
|
1007
|
-
.cg-uplink { fill:none; stroke:#94a3b8; stroke-dasharray:3 2.5; pointer-events:none; }
|
|
1008
|
-
.cg-groups { display:flex; flex-wrap:wrap; gap:4px 12px; margin-top:6px; font-size:.75em; color:var(--muted); }
|
|
1009
|
-
.cg-chip { display:inline-flex; align-items:center; gap:4px; }
|
|
1010
|
-
.cg-chip i { width:10px; height:10px; border-radius:2px; border:1px solid #94a3b8; display:inline-block; }
|
|
1011
|
-
.cg-note { font-size:.8em; color:#9a6700; }
|
|
1012
|
-
.cg-n rect { fill:#eef2f7; stroke:#94a3b8; }
|
|
1013
|
-
.cg-n text { font-size:12px; fill:var(--fg); font-family:ui-monospace,Consolas,monospace; }
|
|
1014
|
-
.cg-n { cursor:pointer; }
|
|
1015
|
-
.cg-n.root rect { fill:#dbeafe; stroke:#2563eb; stroke-width:2; }
|
|
1016
|
-
.cg-n.leaf { opacity:.45; }
|
|
1017
|
-
.cg-n.test rect { stroke-dasharray:3 2; }
|
|
1018
|
-
.cg-n.grp rect { stroke-width:1.8; }
|
|
1019
|
-
.cg-e { fill:none; stroke:#94a3b8; stroke-width:.9; }
|
|
1020
|
-
.cg-e.cand { stroke-dasharray:2 3; }
|
|
1021
|
-
.cg-e.back { stroke:#dc2626; stroke-dasharray:5 3; }
|
|
1022
|
-
.cg-e.http { stroke:#0891b2; stroke-width:1.5; stroke-dasharray:5 2; } /* cross-stack API link */
|
|
1023
|
-
.cg-e.soft { opacity:.55; }
|
|
1024
|
-
.cg-svg.hl .cg-n { opacity:.22; }
|
|
1025
|
-
.cg-svg.hl .cg-e { opacity:.1; }
|
|
1026
|
-
.cg-svg.hl .cg-n.hl { opacity:1; }
|
|
1027
|
-
.cg-svg.hl .cg-e.hl { opacity:1; stroke-width:1.6; }
|
|
928
|
+
export const CSS = `
|
|
929
|
+
:root { --fg:#1f2328; --muted:#656d76; --bd:#d0d7de; --bg:#fff; --accent:#2563eb; --code-bg:#f6f8fa; }
|
|
930
|
+
* { box-sizing: border-box; }
|
|
931
|
+
body { margin:0; color:var(--fg); background:#fafbfc; font:16px/1.6 -apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,"PingFang SC","Microsoft Yahei",sans-serif; }
|
|
932
|
+
main { max-width: 860px; margin: 0 auto; padding: 48px 24px 96px; background:var(--bg); }
|
|
933
|
+
h1,h2,h3,h4,h5,h6 { line-height:1.25; margin:1.6em 0 .6em; scroll-margin-top:16px; }
|
|
934
|
+
h1 { font-size:2em; border-bottom:1px solid var(--bd); padding-bottom:.3em; }
|
|
935
|
+
h2 { font-size:1.5em; border-bottom:1px solid var(--bd); padding-bottom:.3em; }
|
|
936
|
+
h3 { font-size:1.25em; } h4 { font-size:1em; }
|
|
937
|
+
p { margin:.7em 0; }
|
|
938
|
+
a { color:var(--accent); text-decoration:none; } a:hover { text-decoration:underline; }
|
|
939
|
+
code { background:var(--code-bg); padding:.15em .35em; border-radius:6px; font:.88em ui-monospace,SFMono-Regular,Menlo,Consolas,monospace; }
|
|
940
|
+
pre { background:var(--code-bg); padding:14px 16px; border-radius:8px; overflow:auto; }
|
|
941
|
+
pre code { background:none; padding:0; font-size:.85em; }
|
|
942
|
+
pre.output { background:#0d1117; color:#e6edf3; }
|
|
943
|
+
pre.output code { color:inherit; }
|
|
944
|
+
ul,ol { padding-left:1.6em; } li { margin:.2em 0; }
|
|
945
|
+
ul.task-list { list-style:none; padding-left:.2em; }
|
|
946
|
+
li.task input[type=checkbox] { appearance:none; -webkit-appearance:none; width:1.1em; height:1.1em; margin:0 .5em 0 0; vertical-align:-.2em; border:1.5px solid #c8ccd0; border-radius:4px; background:#fff; position:relative; opacity:1; cursor:default; box-sizing:border-box; }
|
|
947
|
+
li.task input[type=checkbox]:checked { background-color:#1f883d; border-color:#1f883d; }
|
|
948
|
+
li.task input[type=checkbox]:checked::after { content:"✓"; position:absolute; top:0; right:0; bottom:0; left:0; display:flex; align-items:center; justify-content:center; color:#fff; font-size:.8em; line-height:1; font-weight:700; }
|
|
949
|
+
aside.callout { border-left:4px solid var(--accent); background:#f0f6ff; padding:.4em 16px; border-radius:0 8px 8px 0; margin:1em 0; }
|
|
950
|
+
aside.aside { border-left-color:#8b949e; background:#f6f8fa; }
|
|
951
|
+
aside.warning { border-left-color:#d97706; background:#fff8f0; }
|
|
952
|
+
aside.callout > :first-child { margin-top:0; } aside.callout > :last-child { margin-bottom:0; }
|
|
953
|
+
figure { margin:1.2em 0; }
|
|
954
|
+
figcaption { color:var(--muted); font-size:.86em; text-align:center; margin-top:.5em; }
|
|
955
|
+
table.geml-table { border-collapse:collapse; width:100%; font-size:.92em; }
|
|
956
|
+
table.geml-table th, table.geml-table td { border:1px solid var(--bd); padding:6px 12px; }
|
|
957
|
+
table.geml-table thead th { background:var(--code-bg); cursor:pointer; user-select:none; white-space:nowrap; }
|
|
958
|
+
table.geml-table thead th::after { content:" \\2195"; color:var(--muted); font-size:.8em; }
|
|
959
|
+
table.geml-table thead th.asc::after { content:" \\2191"; color:var(--accent); }
|
|
960
|
+
table.geml-table thead th.desc::after { content:" \\2193"; color:var(--accent); }
|
|
961
|
+
table.geml-table tbody tr:nth-child(2n) { background:#fafbfc; }
|
|
962
|
+
table.geml-table td.computed { color:#0a7c52; }
|
|
963
|
+
table.geml-table tfoot td { background:var(--code-bg); font-weight:600; border-top:2px solid var(--bd); }
|
|
964
|
+
.table-tools { margin-bottom:6px; } .table-filter { width:240px; max-width:100%; padding:5px 9px; border:1px solid var(--bd); border-radius:7px; font-size:.85em; }
|
|
965
|
+
.table-figure details > summary { cursor:pointer; color:var(--muted); font-size:.86em; padding:4px 0; }
|
|
966
|
+
.table-note { color:var(--muted); font-size:.82em; margin:6px 0 0; }
|
|
967
|
+
.geml-chart { width:100%; height:auto; background:var(--bg); border:1px solid var(--bd); border-radius:8px; }
|
|
968
|
+
.c-title { font-size:15px; font-weight:600; fill:var(--fg); }
|
|
969
|
+
.c-grid { stroke:#eaecef; } .c-axis { stroke:#aab1b8; } .c-tick { font-size:11px; fill:var(--muted); } .c-legend { font-size:12px; fill:var(--fg); }
|
|
970
|
+
.media { max-width:100%; border-radius:8px; }
|
|
971
|
+
.diagram-src { color:var(--muted); } .render-error { color:#cf222e; }
|
|
972
|
+
.math-block { overflow-x:auto; padding:.4em 0; }
|
|
973
|
+
sup.fn a { font-size:.75em; }
|
|
974
|
+
.geml-footer { max-width:860px; margin:0 auto; padding:16px 24px 40px; color:var(--muted); font-size:.82em; }
|
|
975
|
+
.geml-footer code { font-size:.95em; }
|
|
976
|
+
.code-graph { margin:1.4em 0; }
|
|
977
|
+
.cg-mount { border:1px solid var(--bd); border-radius:8px; padding:10px 12px; background:var(--bg); }
|
|
978
|
+
.cg-scroll { overflow:auto; min-height:52vh; max-height:72vh; }
|
|
979
|
+
.cg-svg { display:block; }
|
|
980
|
+
.cg-search-wrap { position:relative; display:inline-block; }
|
|
981
|
+
.cg-search { font:12px/1.4 inherit; padding:2px 7px; border:1px solid var(--bd); border-radius:4px; background:var(--bg); color:var(--fg); min-width:13ch; }
|
|
982
|
+
.cg-search-menu { position:absolute; z-index:30; top:calc(100% + 2px); left:0; min-width:24ch; max-width:52ch; max-height:52vh; overflow:auto; background:var(--bg); border:1px solid var(--bd); border-radius:6px; box-shadow:0 6px 20px rgba(0,0,0,.18); }
|
|
983
|
+
.cg-search-row { display:block; width:100%; text-align:left; padding:4px 9px 4px 18px; border:0; background:none; color:var(--fg); cursor:pointer; font:12px/1.4 inherit; }
|
|
984
|
+
.cg-search-row:hover { background:var(--bd); }
|
|
985
|
+
.cg-search-count { position:sticky; top:0; padding:4px 9px; font-size:11px; opacity:.65; background:var(--bg); border-bottom:1px solid var(--bd); }
|
|
986
|
+
.cg-search-grp { padding:6px 9px 2px; font-size:11px; font-weight:600; opacity:.7; border-top:1px solid var(--bd); }
|
|
987
|
+
.cg-search-grp:first-of-type { border-top:0; }
|
|
988
|
+
.cg-stage { display:flex; gap:10px; align-items:flex-start; }
|
|
989
|
+
.cg-stage .cg-scroll { flex:1 1 auto; min-width:0; }
|
|
990
|
+
.cg-src { flex:0 0 42%; max-width:46%; display:flex; flex-direction:column; border:1px solid var(--bd); border-radius:6px; overflow:hidden; background:var(--bg); }
|
|
991
|
+
.cg-src-hd { display:flex; gap:8px; align-items:center; justify-content:space-between; padding:4px 8px; border-bottom:1px solid var(--bd); color:var(--muted); font:.76em ui-monospace,Consolas,monospace; word-break:break-all; }
|
|
992
|
+
.cg-src-hd button { font:inherit; border:1px solid var(--bd); border-radius:5px; background:transparent; color:var(--muted); cursor:pointer; padding:0 6px; }
|
|
993
|
+
.cg-src-body { margin:0; padding:8px 10px; overflow:auto; max-height:72vh; color:var(--fg); font:12px/1.5 ui-monospace,Consolas,monospace; white-space:pre; }
|
|
994
|
+
.cg-src-note { color:var(--muted); font-style:italic; white-space:pre-wrap; }
|
|
995
|
+
.cg-bar { display:flex; gap:8px; align-items:center; flex-wrap:wrap; font-size:.82em; color:var(--muted); margin-bottom:6px; }
|
|
996
|
+
.cg-bar button { font:inherit; padding:1px 8px; border:1px solid var(--bd); border-radius:5px; background:transparent; cursor:pointer; }
|
|
997
|
+
.cg-crumb .cg-seg { border:0; border-radius:0; padding:0; background:none; color:var(--accent); cursor:pointer; font:inherit; }
|
|
998
|
+
.cg-crumb .cg-seg:hover { text-decoration:underline; }
|
|
999
|
+
.cg-frame { display:block; width:100%; height:72vh; border:0; background:var(--bg); }
|
|
1000
|
+
.cg-flash { color:#b42318; }
|
|
1001
|
+
.cg-legend { display:flex; gap:14px; align-items:center; justify-content:space-between; flex-wrap:wrap; font-size:.75em; color:var(--muted); margin-top:6px; }
|
|
1002
|
+
.cg-upbtn { cursor:pointer; }
|
|
1003
|
+
.cg-upbtn circle { fill:#fff; stroke:#94a3b8; }
|
|
1004
|
+
.cg-upbtn text { font-size:11px; fill:#57606a; }
|
|
1005
|
+
.cg-upbtn:hover circle { stroke:var(--accent); stroke-width:1.6; }
|
|
1006
|
+
.cg-upbtn:hover text { fill:var(--accent); }
|
|
1007
|
+
.cg-uplink { fill:none; stroke:#94a3b8; stroke-dasharray:3 2.5; pointer-events:none; }
|
|
1008
|
+
.cg-groups { display:flex; flex-wrap:wrap; gap:4px 12px; margin-top:6px; font-size:.75em; color:var(--muted); }
|
|
1009
|
+
.cg-chip { display:inline-flex; align-items:center; gap:4px; }
|
|
1010
|
+
.cg-chip i { width:10px; height:10px; border-radius:2px; border:1px solid #94a3b8; display:inline-block; }
|
|
1011
|
+
.cg-note { font-size:.8em; color:#9a6700; }
|
|
1012
|
+
.cg-n rect { fill:#eef2f7; stroke:#94a3b8; }
|
|
1013
|
+
.cg-n text { font-size:12px; fill:var(--fg); font-family:ui-monospace,Consolas,monospace; }
|
|
1014
|
+
.cg-n { cursor:pointer; }
|
|
1015
|
+
.cg-n.root rect { fill:#dbeafe; stroke:#2563eb; stroke-width:2; }
|
|
1016
|
+
.cg-n.leaf { opacity:.45; }
|
|
1017
|
+
.cg-n.test rect { stroke-dasharray:3 2; }
|
|
1018
|
+
.cg-n.grp rect { stroke-width:1.8; }
|
|
1019
|
+
.cg-e { fill:none; stroke:#94a3b8; stroke-width:.9; }
|
|
1020
|
+
.cg-e.cand { stroke-dasharray:2 3; }
|
|
1021
|
+
.cg-e.back { stroke:#dc2626; stroke-dasharray:5 3; }
|
|
1022
|
+
.cg-e.http { stroke:#0891b2; stroke-width:1.5; stroke-dasharray:5 2; } /* cross-stack API link */
|
|
1023
|
+
.cg-e.soft { opacity:.55; }
|
|
1024
|
+
.cg-svg.hl .cg-n { opacity:.22; }
|
|
1025
|
+
.cg-svg.hl .cg-e { opacity:.1; }
|
|
1026
|
+
.cg-svg.hl .cg-n.hl { opacity:1; }
|
|
1027
|
+
.cg-svg.hl .cg-e.hl { opacity:1; stroke-width:1.6; }
|
|
1028
1028
|
`;
|
|
1029
|
-
export const JS = `
|
|
1030
|
-
(function () {
|
|
1031
|
-
function cmp(a, b) {
|
|
1032
|
-
var na = a.dataset.sort, nb = b.dataset.sort;
|
|
1033
|
-
if (na !== undefined && nb !== undefined) return parseFloat(na) - parseFloat(nb);
|
|
1034
|
-
return (a.textContent || "").localeCompare(b.textContent || "");
|
|
1035
|
-
}
|
|
1036
|
-
document.querySelectorAll("table.geml-table").forEach(function (table) {
|
|
1037
|
-
var tbody = table.tBodies[0];
|
|
1038
|
-
if (!tbody) return;
|
|
1039
|
-
// Sort on header click.
|
|
1040
|
-
var ths = table.tHead ? table.tHead.rows[0].cells : [];
|
|
1041
|
-
Array.prototype.forEach.call(ths, function (th, col) {
|
|
1042
|
-
th.addEventListener("click", function () {
|
|
1043
|
-
var dir = th.classList.contains("asc") ? "desc" : "asc";
|
|
1044
|
-
Array.prototype.forEach.call(ths, function (h) { h.classList.remove("asc", "desc"); });
|
|
1045
|
-
th.classList.add(dir);
|
|
1046
|
-
var rows = Array.prototype.slice.call(tbody.rows);
|
|
1047
|
-
rows.sort(function (r1, r2) {
|
|
1048
|
-
var c = cmp(r1.cells[col], r2.cells[col]);
|
|
1049
|
-
return dir === "asc" ? c : -c;
|
|
1050
|
-
});
|
|
1051
|
-
rows.forEach(function (r) { tbody.appendChild(r); });
|
|
1052
|
-
});
|
|
1053
|
-
});
|
|
1054
|
-
// Filter rows.
|
|
1055
|
-
var fig = table.closest(".table-figure");
|
|
1056
|
-
var input = fig ? fig.querySelector(".table-filter") : null;
|
|
1057
|
-
if (input) input.addEventListener("input", function () {
|
|
1058
|
-
var q = input.value.toLowerCase();
|
|
1059
|
-
Array.prototype.forEach.call(tbody.rows, function (r) {
|
|
1060
|
-
r.style.display = (r.textContent || "").toLowerCase().indexOf(q) >= 0 ? "" : "none";
|
|
1061
|
-
});
|
|
1062
|
-
});
|
|
1063
|
-
});
|
|
1064
|
-
})();
|
|
1029
|
+
export const JS = `
|
|
1030
|
+
(function () {
|
|
1031
|
+
function cmp(a, b) {
|
|
1032
|
+
var na = a.dataset.sort, nb = b.dataset.sort;
|
|
1033
|
+
if (na !== undefined && nb !== undefined) return parseFloat(na) - parseFloat(nb);
|
|
1034
|
+
return (a.textContent || "").localeCompare(b.textContent || "");
|
|
1035
|
+
}
|
|
1036
|
+
document.querySelectorAll("table.geml-table").forEach(function (table) {
|
|
1037
|
+
var tbody = table.tBodies[0];
|
|
1038
|
+
if (!tbody) return;
|
|
1039
|
+
// Sort on header click.
|
|
1040
|
+
var ths = table.tHead ? table.tHead.rows[0].cells : [];
|
|
1041
|
+
Array.prototype.forEach.call(ths, function (th, col) {
|
|
1042
|
+
th.addEventListener("click", function () {
|
|
1043
|
+
var dir = th.classList.contains("asc") ? "desc" : "asc";
|
|
1044
|
+
Array.prototype.forEach.call(ths, function (h) { h.classList.remove("asc", "desc"); });
|
|
1045
|
+
th.classList.add(dir);
|
|
1046
|
+
var rows = Array.prototype.slice.call(tbody.rows);
|
|
1047
|
+
rows.sort(function (r1, r2) {
|
|
1048
|
+
var c = cmp(r1.cells[col], r2.cells[col]);
|
|
1049
|
+
return dir === "asc" ? c : -c;
|
|
1050
|
+
});
|
|
1051
|
+
rows.forEach(function (r) { tbody.appendChild(r); });
|
|
1052
|
+
});
|
|
1053
|
+
});
|
|
1054
|
+
// Filter rows.
|
|
1055
|
+
var fig = table.closest(".table-figure");
|
|
1056
|
+
var input = fig ? fig.querySelector(".table-filter") : null;
|
|
1057
|
+
if (input) input.addEventListener("input", function () {
|
|
1058
|
+
var q = input.value.toLowerCase();
|
|
1059
|
+
Array.prototype.forEach.call(tbody.rows, function (r) {
|
|
1060
|
+
r.style.display = (r.textContent || "").toLowerCase().indexOf(q) >= 0 ? "" : "none";
|
|
1061
|
+
});
|
|
1062
|
+
});
|
|
1063
|
+
});
|
|
1064
|
+
})();
|
|
1065
1065
|
`;
|
|
1066
1066
|
// geml-code-graph runtime: layered layout AT DRAW TIME (GEP-0003 / v2-D8) so
|
|
1067
1067
|
// clicking a node re-roots the view inside the embedded slice. Algorithm as
|
package/dist/table.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type DiagnosticCode } from "./diagnostics.js";
|
|
1
2
|
import { type Value } from "./attrs.js";
|
|
2
3
|
import { type Inline, type RefSink } from "./inline.js";
|
|
3
4
|
export type Align = "left" | "right" | "center";
|
|
@@ -23,6 +24,7 @@ export interface TableModel {
|
|
|
23
24
|
}
|
|
24
25
|
export interface TableDiag {
|
|
25
26
|
severity: "error" | "warning";
|
|
27
|
+
code: DiagnosticCode;
|
|
26
28
|
message: string;
|
|
27
29
|
}
|
|
28
30
|
export interface TableResult {
|
package/dist/table.js
CHANGED
|
@@ -253,7 +253,7 @@ export function parseTable(body, attrs, line, sink) {
|
|
|
253
253
|
const src = typeof attrs["src"] === "string" ? attrs["src"] : undefined;
|
|
254
254
|
if (src !== undefined) {
|
|
255
255
|
if (body.some((l) => l.trim() !== "")) {
|
|
256
|
-
diagnostics.push({ severity: "error", message: "table has both `src` and an inline body; provide one, not both" });
|
|
256
|
+
diagnostics.push({ severity: "error", code: "table-src-and-body", message: "table has both `src` and an inline body; provide one, not both" });
|
|
257
257
|
}
|
|
258
258
|
const headerAttr = attrs["header"];
|
|
259
259
|
const header = headerAttr === undefined ? true : headerAttr === true || headerAttr === 1 || headerAttr === "1";
|
|
@@ -271,7 +271,7 @@ export function parseTable(body, attrs, line, sink) {
|
|
|
271
271
|
}
|
|
272
272
|
else {
|
|
273
273
|
if (fmt !== undefined)
|
|
274
|
-
diagnostics.push({ severity: "warning", message: `unknown table format \`${fmt}\`; parsed as visual grid` });
|
|
274
|
+
diagnostics.push({ severity: "warning", code: "unknown-table-format", message: `unknown table format \`${fmt}\`; parsed as visual grid` });
|
|
275
275
|
raw = parseVisual(body);
|
|
276
276
|
}
|
|
277
277
|
const columns = [...raw.columns];
|
|
@@ -369,7 +369,7 @@ export function parseTable(body, attrs, line, sink) {
|
|
|
369
369
|
for (const f of formulas) {
|
|
370
370
|
const eq = f.indexOf("=");
|
|
371
371
|
if (eq <= 0) {
|
|
372
|
-
diagnostics.push({ severity: "error", message: `bad compute formula \`${f}\` (want \`Name = expr\`)` });
|
|
372
|
+
diagnostics.push({ severity: "error", code: "bad-compute-formula", message: `bad compute formula \`${f}\` (want \`Name = expr\`)` });
|
|
373
373
|
continue;
|
|
374
374
|
}
|
|
375
375
|
const { name, fmt } = splitName(f.slice(0, eq));
|
|
@@ -379,7 +379,7 @@ export function parseTable(body, attrs, line, sink) {
|
|
|
379
379
|
toks = lexExpr(expr);
|
|
380
380
|
}
|
|
381
381
|
catch {
|
|
382
|
-
diagnostics.push({ severity: "error", message: `cannot lex formula \`${f}\`` });
|
|
382
|
+
diagnostics.push({ severity: "error", code: "unlexable-compute-formula", message: `cannot lex formula \`${f}\`` });
|
|
383
383
|
continue;
|
|
384
384
|
}
|
|
385
385
|
// Target is a header name (never a letter reference): match by name only.
|
|
@@ -405,7 +405,7 @@ export function parseTable(body, attrs, line, sink) {
|
|
|
405
405
|
}
|
|
406
406
|
}
|
|
407
407
|
catch (e) {
|
|
408
|
-
diagnostics.push({ severity: "error", message: `compute \`${name}\`: ${e.message}` });
|
|
408
|
+
diagnostics.push({ severity: "error", code: "compute-error", message: `compute \`${name}\`: ${e.message}` });
|
|
409
409
|
failed = true;
|
|
410
410
|
}
|
|
411
411
|
}
|
|
@@ -429,14 +429,14 @@ export function parseTable(body, attrs, line, sink) {
|
|
|
429
429
|
for (const s of summaryDecls) {
|
|
430
430
|
const eq = s.indexOf("=");
|
|
431
431
|
if (eq <= 0) {
|
|
432
|
-
diagnostics.push({ severity: "error", message: `bad summary \`${s}\` (want \`Cell = value\`)` });
|
|
432
|
+
diagnostics.push({ severity: "error", code: "bad-summary-entry", message: `bad summary \`${s}\` (want \`Cell = value\`)` });
|
|
433
433
|
continue;
|
|
434
434
|
}
|
|
435
435
|
const { name, fmt } = splitName(s.slice(0, eq));
|
|
436
436
|
const rhs = s.slice(eq + 1).trim();
|
|
437
437
|
const ci = colIndex(name);
|
|
438
438
|
if (ci < 0) {
|
|
439
|
-
diagnostics.push({ severity: "error", message: `summary targets unknown column \`${name}\`` });
|
|
439
|
+
diagnostics.push({ severity: "error", code: "summary-unknown-column", message: `summary targets unknown column \`${name}\`` });
|
|
440
440
|
continue;
|
|
441
441
|
}
|
|
442
442
|
// String label: `Cell = 'Total'`.
|
|
@@ -451,7 +451,7 @@ export function parseTable(body, attrs, line, sink) {
|
|
|
451
451
|
toks = lexExpr(rhs);
|
|
452
452
|
}
|
|
453
453
|
catch {
|
|
454
|
-
diagnostics.push({ severity: "error", message: `cannot lex summary \`${s}\`` });
|
|
454
|
+
diagnostics.push({ severity: "error", code: "unlexable-summary-expression", message: `cannot lex summary \`${s}\`` });
|
|
455
455
|
continue;
|
|
456
456
|
}
|
|
457
457
|
try {
|
|
@@ -464,7 +464,7 @@ export function parseTable(body, attrs, line, sink) {
|
|
|
464
464
|
catch (e) {
|
|
465
465
|
const msg = /unknown column `(.+)`/.exec(e.message);
|
|
466
466
|
const hint = msg ? `summary \`${name}\`: column \`${msg[1]}\` must be reduced by an aggregate (e.g. sum(${msg[1]}))` : `summary \`${name}\`: ${e.message}`;
|
|
467
|
-
diagnostics.push({ severity: "error", message: hint });
|
|
467
|
+
diagnostics.push({ severity: "error", code: "summary-error", message: hint });
|
|
468
468
|
}
|
|
469
469
|
}
|
|
470
470
|
model.summary = summary;
|
|
@@ -477,12 +477,12 @@ export function parseTable(body, attrs, line, sink) {
|
|
|
477
477
|
for (const sd of spanDecls) {
|
|
478
478
|
const sp = parseSpan(sd);
|
|
479
479
|
if (!sp) {
|
|
480
|
-
diagnostics.push({ severity: "error", message: `bad span \`${sd}\` (want \`rNcM:RxC\`)` });
|
|
480
|
+
diagnostics.push({ severity: "error", code: "bad-span", message: `bad span \`${sd}\` (want \`rNcM:RxC\`)` });
|
|
481
481
|
continue;
|
|
482
482
|
}
|
|
483
483
|
const cell = model.rows[sp.row - 1]?.[sp.col - 1];
|
|
484
484
|
if (!cell) {
|
|
485
|
-
diagnostics.push({ severity: "warning", message: `span \`${sd}\` targets a cell outside the table` });
|
|
485
|
+
diagnostics.push({ severity: "warning", code: "span-outside-table", message: `span \`${sd}\` targets a cell outside the table` });
|
|
486
486
|
continue;
|
|
487
487
|
}
|
|
488
488
|
// A span can never extend past the grid: clamp its extent to the rows/cols
|
package/package.json
CHANGED
|
@@ -1,62 +1,62 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@geml/geml",
|
|
3
|
-
"version": "1.4.
|
|
4
|
-
"publishConfig": {
|
|
5
|
-
"access": "public"
|
|
6
|
-
},
|
|
7
|
-
"description": "GEML(General Expressive Markup Language) — one format, two readers. People and AI agents co-write the same document: plain text that stays legible for people, and addressable, verifiable, and versioned for machines. Reference parser, validator, renderer & CLI for GEML.",
|
|
8
|
-
"type": "module",
|
|
9
|
-
"bin": {
|
|
10
|
-
"geml": "dist/geml.js"
|
|
11
|
-
},
|
|
12
|
-
"main": "dist/geml.js",
|
|
13
|
-
"types": "dist/geml.d.ts",
|
|
14
|
-
"files": [
|
|
15
|
-
"dist",
|
|
16
|
-
"codemap",
|
|
17
|
-
"README.md",
|
|
18
|
-
"LICENSE"
|
|
19
|
-
],
|
|
20
|
-
"engines": {
|
|
21
|
-
"node": ">=22"
|
|
22
|
-
},
|
|
23
|
-
"keywords": [
|
|
24
|
-
"geml",
|
|
25
|
-
"markup",
|
|
26
|
-
"markdown",
|
|
27
|
-
"parser",
|
|
28
|
-
"cli",
|
|
29
|
-
"document",
|
|
30
|
-
"typed-block",
|
|
31
|
-
"ai",
|
|
32
|
-
"agent",
|
|
33
|
-
"llm",
|
|
34
|
-
"addressable",
|
|
35
|
-
"versioning",
|
|
36
|
-
"docs",
|
|
37
|
-
"code-graph"
|
|
38
|
-
],
|
|
39
|
-
"repository": {
|
|
40
|
-
"type": "git",
|
|
41
|
-
"url": "git+https://github.com/geml-spec/geml.git",
|
|
42
|
-
"directory": "geml-parser"
|
|
43
|
-
},
|
|
44
|
-
"homepage": "https://github.com/geml-spec/geml#readme",
|
|
45
|
-
"bugs": {
|
|
46
|
-
"url": "https://github.com/geml-spec/geml/issues"
|
|
47
|
-
},
|
|
48
|
-
"scripts": {
|
|
49
|
-
"build": "tsc",
|
|
50
|
-
"test": "tsc && node test/all.mjs",
|
|
51
|
-
"parse": "node dist/geml.js",
|
|
52
|
-
"coverage": "tsc && c8 --all --include=dist/**/*.js --include=codemap/**/*.mjs --reporter=text --reporter=text-summary node test/all.mjs",
|
|
53
|
-
"coverage:check": "tsc && c8 --all --include=dist/**/*.js --include=codemap/**/*.mjs --check-coverage --lines 95 --statements 95 --functions 95 --branches 95 node test/all.mjs",
|
|
54
|
-
"prepublishOnly": "npm run build"
|
|
55
|
-
},
|
|
56
|
-
"license": "MIT",
|
|
57
|
-
"devDependencies": {
|
|
58
|
-
"@types/node": "^22.19.21",
|
|
59
|
-
"c8": "^10.1.3",
|
|
60
|
-
"typescript": "^5.9.3"
|
|
61
|
-
}
|
|
62
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@geml/geml",
|
|
3
|
+
"version": "1.4.3",
|
|
4
|
+
"publishConfig": {
|
|
5
|
+
"access": "public"
|
|
6
|
+
},
|
|
7
|
+
"description": "GEML(General Expressive Markup Language) — one format, two readers. People and AI agents co-write the same document: plain text that stays legible for people, and addressable, verifiable, and versioned for machines. Reference parser, validator, renderer & CLI for GEML.",
|
|
8
|
+
"type": "module",
|
|
9
|
+
"bin": {
|
|
10
|
+
"geml": "dist/geml.js"
|
|
11
|
+
},
|
|
12
|
+
"main": "dist/geml.js",
|
|
13
|
+
"types": "dist/geml.d.ts",
|
|
14
|
+
"files": [
|
|
15
|
+
"dist",
|
|
16
|
+
"codemap",
|
|
17
|
+
"README.md",
|
|
18
|
+
"LICENSE"
|
|
19
|
+
],
|
|
20
|
+
"engines": {
|
|
21
|
+
"node": ">=22"
|
|
22
|
+
},
|
|
23
|
+
"keywords": [
|
|
24
|
+
"geml",
|
|
25
|
+
"markup",
|
|
26
|
+
"markdown",
|
|
27
|
+
"parser",
|
|
28
|
+
"cli",
|
|
29
|
+
"document",
|
|
30
|
+
"typed-block",
|
|
31
|
+
"ai",
|
|
32
|
+
"agent",
|
|
33
|
+
"llm",
|
|
34
|
+
"addressable",
|
|
35
|
+
"versioning",
|
|
36
|
+
"docs",
|
|
37
|
+
"code-graph"
|
|
38
|
+
],
|
|
39
|
+
"repository": {
|
|
40
|
+
"type": "git",
|
|
41
|
+
"url": "git+https://github.com/geml-spec/geml.git",
|
|
42
|
+
"directory": "geml-parser"
|
|
43
|
+
},
|
|
44
|
+
"homepage": "https://github.com/geml-spec/geml#readme",
|
|
45
|
+
"bugs": {
|
|
46
|
+
"url": "https://github.com/geml-spec/geml/issues"
|
|
47
|
+
},
|
|
48
|
+
"scripts": {
|
|
49
|
+
"build": "tsc",
|
|
50
|
+
"test": "tsc && node test/all.mjs",
|
|
51
|
+
"parse": "node dist/geml.js",
|
|
52
|
+
"coverage": "tsc && c8 --all --include=dist/**/*.js --include=codemap/**/*.mjs --reporter=text --reporter=text-summary node test/all.mjs",
|
|
53
|
+
"coverage:check": "tsc && c8 --all --include=dist/**/*.js --include=codemap/**/*.mjs --check-coverage --lines 95 --statements 95 --functions 95 --branches 95 node test/all.mjs",
|
|
54
|
+
"prepublishOnly": "npm run build"
|
|
55
|
+
},
|
|
56
|
+
"license": "MIT",
|
|
57
|
+
"devDependencies": {
|
|
58
|
+
"@types/node": "^22.19.21",
|
|
59
|
+
"c8": "^10.1.3",
|
|
60
|
+
"typescript": "^5.9.3"
|
|
61
|
+
}
|
|
62
|
+
}
|