@commentray/render 0.3.2 → 0.3.4
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/dist/code-browser-client.bundle.js +12 -12
- package/dist/code-browser-client.js +119 -40
- package/dist/code-browser-client.js.map +1 -1
- package/dist/code-browser-nav-rail-doc-hub.html +24 -0
- package/dist/code-browser-scroll-sync.d.ts +1 -1
- package/dist/code-browser-scroll-sync.d.ts.map +1 -1
- package/dist/code-browser-scroll-sync.js +1 -1
- package/dist/code-browser-scroll-sync.js.map +1 -1
- package/dist/code-browser-shell.css +1918 -0
- package/dist/code-browser.d.ts +3 -12
- package/dist/code-browser.d.ts.map +1 -1
- package/dist/code-browser.js +44 -1714
- package/dist/code-browser.js.map +1 -1
- package/dist/commentray-mermaid-events.d.ts +9 -0
- package/dist/commentray-mermaid-events.d.ts.map +1 -0
- package/dist/commentray-mermaid-events.js +9 -0
- package/dist/commentray-mermaid-events.js.map +1 -0
- package/dist/mermaid-runtime-bootstrap.mjs +26 -0
- package/dist/mermaid-runtime-html.d.ts.map +1 -1
- package/dist/mermaid-runtime-html.js +23 -19
- package/dist/mermaid-runtime-html.js.map +1 -1
- package/package.json +2 -2
|
@@ -14,9 +14,10 @@ import { DUAL_PANE_BLOCK_REVEAL_LEAD_CSS_PX, READING_LEAD_ALIGN_TOLERANCE_CSS_PX
|
|
|
14
14
|
import { wireWideModeIntroTour } from "./code-browser-wide-intro-controller.js";
|
|
15
15
|
import { readWebStorageItem, writeWebStorageItem } from "./code-browser-web-storage.js";
|
|
16
16
|
import { dispatchCommentrayMermaidDone, wireBlockStretchBufferSync, } from "./block-stretch-buffer-sync.js";
|
|
17
|
+
import { COMMENTRAY_MERMAID_MODULE_READY_EVENT } from "./commentray-mermaid-events.js";
|
|
17
18
|
/**
|
|
18
19
|
* Hub pages emit `./browse/…` relative to the site root. From `/…/browse/current.html` the browser
|
|
19
|
-
* would otherwise resolve that
|
|
20
|
+
* would otherwise resolve `./browse/…` against that folder and nest a second `browse/` segment.
|
|
20
21
|
*/
|
|
21
22
|
function rewriteHubRelativeBrowseAnchorsIn(root) {
|
|
22
23
|
const path = globalThis.location.pathname;
|
|
@@ -30,30 +31,82 @@ function rewriteHubRelativeBrowseAnchorsIn(root) {
|
|
|
30
31
|
el.href = resolveStaticBrowseHref(raw, path, origin);
|
|
31
32
|
}
|
|
32
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* The Mermaid bundle is loaded via a trailing `type="module"` script (async `import()`). The main
|
|
36
|
+
* client runs as a classic inline script **before** that module executes, so `cy.visit` + an
|
|
37
|
+
* immediate pane flip can call {@link runMermaidOnFreshDocNodes} while `commentrayMermaid` is still
|
|
38
|
+
* undefined. We enqueue roots and flush on {@link COMMENTRAY_MERMAID_MODULE_READY_EVENT}.
|
|
39
|
+
*/
|
|
40
|
+
const pendingMermaidDocRoots = new Set();
|
|
41
|
+
const queuedMermaidDocRoots = new Set();
|
|
42
|
+
let mermaidQueueInFlight = null;
|
|
43
|
+
function collectFreshMermaidPreNodes(roots) {
|
|
44
|
+
const uniq = new Set();
|
|
45
|
+
for (const root of roots) {
|
|
46
|
+
for (const pre of Array.from(root.querySelectorAll("pre.mermaid"))) {
|
|
47
|
+
const wrap = pre.closest(".commentray-mermaid");
|
|
48
|
+
if (wrap !== null && wrap.querySelector("svg") !== null)
|
|
49
|
+
continue;
|
|
50
|
+
uniq.add(pre);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return Array.from(uniq);
|
|
54
|
+
}
|
|
55
|
+
function pumpQueuedMermaidRuns() {
|
|
56
|
+
if (mermaidQueueInFlight)
|
|
57
|
+
return mermaidQueueInFlight;
|
|
58
|
+
mermaidQueueInFlight = (async () => {
|
|
59
|
+
while (queuedMermaidDocRoots.size > 0) {
|
|
60
|
+
const m = globalThis
|
|
61
|
+
.commentrayMermaid;
|
|
62
|
+
if (!m) {
|
|
63
|
+
for (const root of queuedMermaidDocRoots)
|
|
64
|
+
pendingMermaidDocRoots.add(root);
|
|
65
|
+
queuedMermaidDocRoots.clear();
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
const roots = Array.from(queuedMermaidDocRoots);
|
|
69
|
+
queuedMermaidDocRoots.clear();
|
|
70
|
+
const nodes = collectFreshMermaidPreNodes(roots);
|
|
71
|
+
if (nodes.length === 0)
|
|
72
|
+
continue;
|
|
73
|
+
try {
|
|
74
|
+
await m.run({ nodes });
|
|
75
|
+
dispatchCommentrayMermaidDone();
|
|
76
|
+
}
|
|
77
|
+
catch (err) {
|
|
78
|
+
console.error("Commentray: mermaid.run failed", err);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
})().finally(() => {
|
|
82
|
+
mermaidQueueInFlight = null;
|
|
83
|
+
if (queuedMermaidDocRoots.size > 0)
|
|
84
|
+
void pumpQueuedMermaidRuns();
|
|
85
|
+
});
|
|
86
|
+
return mermaidQueueInFlight;
|
|
87
|
+
}
|
|
88
|
+
function queueMermaidRunForDocRoot(docRoot) {
|
|
89
|
+
queuedMermaidDocRoots.add(docRoot);
|
|
90
|
+
return pumpQueuedMermaidRuns();
|
|
91
|
+
}
|
|
92
|
+
function flushPendingMermaidDocRoots() {
|
|
93
|
+
const roots = Array.from(pendingMermaidDocRoots);
|
|
94
|
+
pendingMermaidDocRoots.clear();
|
|
95
|
+
for (const root of roots) {
|
|
96
|
+
void queueMermaidRunForDocRoot(root);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
globalThis.addEventListener(COMMENTRAY_MERMAID_MODULE_READY_EVENT, () => {
|
|
100
|
+
flushPendingMermaidDocRoots();
|
|
101
|
+
});
|
|
33
102
|
function runMermaidOnFreshDocNodes(docBody) {
|
|
34
103
|
if (typeof globalThis.location !== "undefined" && globalThis.location.protocol === "file:")
|
|
35
104
|
return Promise.resolve();
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
/** Do not re-run on wrappers that already have SVG (avoids corrupting output after dual-mobile pane flip). */
|
|
39
|
-
const nodes = allPres.filter((pre) => {
|
|
40
|
-
const wrap = pre.closest(".commentray-mermaid");
|
|
41
|
-
return wrap === null || wrap.querySelector("svg") === null;
|
|
42
|
-
});
|
|
43
|
-
if (nodes.length === 0)
|
|
44
|
-
return Promise.resolve();
|
|
45
|
-
const m = globalThis
|
|
46
|
-
.commentrayMermaid;
|
|
47
|
-
if (!m)
|
|
105
|
+
if (!globalThis.commentrayMermaid) {
|
|
106
|
+
pendingMermaidDocRoots.add(docBody);
|
|
48
107
|
return Promise.resolve();
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
.then(() => {
|
|
52
|
-
dispatchCommentrayMermaidDone();
|
|
53
|
-
})
|
|
54
|
-
.catch((err) => {
|
|
55
|
-
console.error("Commentray: mermaid.run failed", err);
|
|
56
|
-
});
|
|
108
|
+
}
|
|
109
|
+
return queueMermaidRunForDocRoot(docBody);
|
|
57
110
|
}
|
|
58
111
|
function clamp(n, lo, hi) {
|
|
59
112
|
return Math.max(lo, Math.min(hi, n));
|
|
@@ -1038,6 +1091,14 @@ function emptyBrowsePreviewInnerHtml(scope, filePathLabel, mutable) {
|
|
|
1038
1091
|
const hint = emptyBrowsePreviewHint("commentray-and-paths", fb.length, fb.length, true);
|
|
1039
1092
|
return emptySearchBrowsePreviewInnerHtml(hint, fb, hitCtx);
|
|
1040
1093
|
}
|
|
1094
|
+
/**
|
|
1095
|
+
* List rows use `focus({ preventScroll: true })` so the page does not jump; follow with
|
|
1096
|
+
* `scrollIntoView` so overflow panels (`#search-results`, `#documented-files-tree`) still scroll.
|
|
1097
|
+
*/
|
|
1098
|
+
function focusListRowAndReveal(el) {
|
|
1099
|
+
el.focus({ preventScroll: true });
|
|
1100
|
+
el.scrollIntoView({ block: "nearest", inline: "nearest" });
|
|
1101
|
+
}
|
|
1041
1102
|
function wireSearchResultsHitListKeyboard(searchResults, searchInput) {
|
|
1042
1103
|
searchResults.addEventListener("keydown", (e) => {
|
|
1043
1104
|
if (e.isComposing || searchResults.hidden)
|
|
@@ -1052,17 +1113,17 @@ function wireSearchResultsHitListKeyboard(searchResults, searchInput) {
|
|
|
1052
1113
|
if (idx < 0)
|
|
1053
1114
|
return;
|
|
1054
1115
|
if (e.key === "ArrowDown" && idx < hits.length - 1) {
|
|
1055
|
-
hits[idx + 1]
|
|
1116
|
+
focusListRowAndReveal(hits[idx + 1]);
|
|
1056
1117
|
e.preventDefault();
|
|
1057
1118
|
return;
|
|
1058
1119
|
}
|
|
1059
1120
|
if (e.key === "ArrowUp") {
|
|
1060
1121
|
if (idx > 0) {
|
|
1061
|
-
hits[idx - 1]
|
|
1122
|
+
focusListRowAndReveal(hits[idx - 1]);
|
|
1062
1123
|
e.preventDefault();
|
|
1063
1124
|
return;
|
|
1064
1125
|
}
|
|
1065
|
-
searchInput
|
|
1126
|
+
focusListRowAndReveal(searchInput);
|
|
1066
1127
|
e.preventDefault();
|
|
1067
1128
|
}
|
|
1068
1129
|
});
|
|
@@ -1076,7 +1137,7 @@ function wireSearchInputKeyboard(searchInput, searchResults, actions) {
|
|
|
1076
1137
|
if (!searchResults.hidden) {
|
|
1077
1138
|
const hits = listSearchHitButtons(searchResults);
|
|
1078
1139
|
if (hits.length > 0 && document.activeElement === searchInput) {
|
|
1079
|
-
hits[0]
|
|
1140
|
+
focusListRowAndReveal(hits[0]);
|
|
1080
1141
|
e.preventDefault();
|
|
1081
1142
|
return;
|
|
1082
1143
|
}
|
|
@@ -2262,7 +2323,34 @@ function focusDocumentedFilesFilterInput() {
|
|
|
2262
2323
|
const el = document.getElementById("documented-files-filter");
|
|
2263
2324
|
if (!(el instanceof HTMLInputElement))
|
|
2264
2325
|
return;
|
|
2265
|
-
el
|
|
2326
|
+
focusListRowAndReveal(el);
|
|
2327
|
+
}
|
|
2328
|
+
function focusDocumentedFilesHubSummaryIfPresent(hub) {
|
|
2329
|
+
const sum = hub.querySelector("summary");
|
|
2330
|
+
if (sum instanceof HTMLElement)
|
|
2331
|
+
sum.focus({ preventScroll: true });
|
|
2332
|
+
}
|
|
2333
|
+
/** Escape to close; pointer outside `#documented-files-hub` to close (capture). */
|
|
2334
|
+
function wireDocumentedFilesHubDismissalHandlers(hub) {
|
|
2335
|
+
function onEscape(ev) {
|
|
2336
|
+
if (!hub.open || ev.key !== "Escape")
|
|
2337
|
+
return;
|
|
2338
|
+
ev.preventDefault();
|
|
2339
|
+
hub.open = false;
|
|
2340
|
+
focusDocumentedFilesHubSummaryIfPresent(hub);
|
|
2341
|
+
}
|
|
2342
|
+
document.addEventListener("keydown", onEscape, true);
|
|
2343
|
+
document.addEventListener("pointerdown", (ev) => {
|
|
2344
|
+
if (!hub.open)
|
|
2345
|
+
return;
|
|
2346
|
+
const t = ev.target;
|
|
2347
|
+
if (!(t instanceof Node))
|
|
2348
|
+
return;
|
|
2349
|
+
if (hub.contains(t))
|
|
2350
|
+
return;
|
|
2351
|
+
hub.open = false;
|
|
2352
|
+
focusDocumentedFilesHubSummaryIfPresent(hub);
|
|
2353
|
+
}, true);
|
|
2266
2354
|
}
|
|
2267
2355
|
function wireDocumentedFilesTree() {
|
|
2268
2356
|
const hub = document.getElementById("documented-files-hub");
|
|
@@ -2313,16 +2401,7 @@ function wireDocumentedFilesTree() {
|
|
|
2313
2401
|
return;
|
|
2314
2402
|
void hydrateTree();
|
|
2315
2403
|
});
|
|
2316
|
-
|
|
2317
|
-
if (!detailsHub.open || ev.key !== "Escape")
|
|
2318
|
-
return;
|
|
2319
|
-
ev.preventDefault();
|
|
2320
|
-
detailsHub.open = false;
|
|
2321
|
-
const sum = detailsHub.querySelector("summary");
|
|
2322
|
-
if (sum instanceof HTMLElement)
|
|
2323
|
-
sum.focus({ preventScroll: true });
|
|
2324
|
-
}
|
|
2325
|
-
document.addEventListener("keydown", onDocumentedFilesHubEscape, true);
|
|
2404
|
+
wireDocumentedFilesHubDismissalHandlers(detailsHub);
|
|
2326
2405
|
treeMount.addEventListener("keydown", (e) => {
|
|
2327
2406
|
if (!detailsHub.open || e.isComposing)
|
|
2328
2407
|
return;
|
|
@@ -2337,19 +2416,19 @@ function wireDocumentedFilesTree() {
|
|
|
2337
2416
|
return;
|
|
2338
2417
|
if (e.key === "ArrowDown") {
|
|
2339
2418
|
if (idx < links.length - 1) {
|
|
2340
|
-
links[idx + 1]
|
|
2419
|
+
focusListRowAndReveal(links[idx + 1]);
|
|
2341
2420
|
e.preventDefault();
|
|
2342
2421
|
}
|
|
2343
2422
|
return;
|
|
2344
2423
|
}
|
|
2345
2424
|
if (e.key === "ArrowUp") {
|
|
2346
2425
|
if (idx > 0) {
|
|
2347
|
-
links[idx - 1]
|
|
2426
|
+
focusListRowAndReveal(links[idx - 1]);
|
|
2348
2427
|
e.preventDefault();
|
|
2349
2428
|
return;
|
|
2350
2429
|
}
|
|
2351
2430
|
if (filterInput instanceof HTMLInputElement) {
|
|
2352
|
-
filterInput
|
|
2431
|
+
focusListRowAndReveal(filterInput);
|
|
2353
2432
|
e.preventDefault();
|
|
2354
2433
|
}
|
|
2355
2434
|
}
|
|
@@ -2366,7 +2445,7 @@ function wireDocumentedFilesTree() {
|
|
|
2366
2445
|
const links = listDocumentedTreeFileLinks(treeMount);
|
|
2367
2446
|
if (links.length === 0)
|
|
2368
2447
|
return;
|
|
2369
|
-
links[0]
|
|
2448
|
+
focusListRowAndReveal(links[0]);
|
|
2370
2449
|
e.preventDefault();
|
|
2371
2450
|
});
|
|
2372
2451
|
}
|