@commentray/render 0.3.4 → 0.3.6
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/block-stretch-buffer-sync.d.ts.map +1 -1
- package/dist/block-stretch-buffer-sync.js +21 -1
- package/dist/block-stretch-buffer-sync.js.map +1 -1
- package/dist/code-browser-client.bundle.js +11 -11
- package/dist/code-browser-client.js +134 -44
- package/dist/code-browser-client.js.map +1 -1
- package/dist/code-browser-shell.css +43 -6
- package/package.json +2 -2
|
@@ -13,7 +13,7 @@ import { parseDualPaneScrollSyncStrategy } from "./code-browser-scroll-sync-stra
|
|
|
13
13
|
import { DUAL_PANE_BLOCK_REVEAL_LEAD_CSS_PX, READING_LEAD_ALIGN_TOLERANCE_CSS_PX, READING_VIEWPORT_BOTTOM_EDGE_CSS_PX, readingViewportTopInsetCssPx, } from "./reading-viewport-comfort.js";
|
|
14
14
|
import { wireWideModeIntroTour } from "./code-browser-wide-intro-controller.js";
|
|
15
15
|
import { readWebStorageItem, writeWebStorageItem } from "./code-browser-web-storage.js";
|
|
16
|
-
import { dispatchCommentrayMermaidDone, wireBlockStretchBufferSync, } from "./block-stretch-buffer-sync.js";
|
|
16
|
+
import { applyBlockStretchRowBuffers, dispatchCommentrayMermaidDone, wireBlockStretchBufferSync, } from "./block-stretch-buffer-sync.js";
|
|
17
17
|
import { COMMENTRAY_MERMAID_MODULE_READY_EVENT } from "./commentray-mermaid-events.js";
|
|
18
18
|
/**
|
|
19
19
|
* Hub pages emit `./browse/…` relative to the site root. From `/…/browse/current.html` the browser
|
|
@@ -936,16 +936,16 @@ function emptySearchBrowsePreviewInnerHtml(hint, rows, ctx) {
|
|
|
936
936
|
function scrollDocToMarkdownLine0(docScrollEl, line0, mdLineCount) {
|
|
937
937
|
const el = docScrollEl.querySelector(`#commentray-md-line-${String(line0)}`);
|
|
938
938
|
if (el instanceof HTMLElement) {
|
|
939
|
-
|
|
940
|
-
const maxY = Math.round(Math.max(0, docScrollEl.scrollHeight - docScrollEl.clientHeight));
|
|
941
|
-
docScrollEl.scrollTo({ top: clamp(top, 0, maxY), behavior: "smooth" });
|
|
939
|
+
applyRevealChildInPane(docScrollEl, el, DUAL_PANE_BLOCK_REVEAL_LEAD_CSS_PX);
|
|
942
940
|
return;
|
|
943
941
|
}
|
|
944
942
|
if (mdLineCount <= 1)
|
|
945
943
|
return;
|
|
946
|
-
const
|
|
947
|
-
const
|
|
948
|
-
|
|
944
|
+
const lineClamped = clamp(line0, 0, Math.max(0, mdLineCount - 1));
|
|
945
|
+
const scrollTarget = paneUsesInternalYScroll(docScrollEl) ? docScrollEl : rootScrollingElement();
|
|
946
|
+
const maxScroll = Math.max(0, scrollTarget.scrollHeight - scrollTarget.clientHeight);
|
|
947
|
+
const top = clamp((lineClamped / Math.max(1, mdLineCount - 1)) * maxScroll, 0, maxScroll);
|
|
948
|
+
scrollTarget.scrollTo({ top, behavior: "smooth" });
|
|
949
949
|
}
|
|
950
950
|
function navigateToDocumentedPair(pair, mdLine0) {
|
|
951
951
|
if (pair.staticBrowseUrl?.trim()) {
|
|
@@ -1028,7 +1028,10 @@ function handlePathSearchHit(button, deps) {
|
|
|
1028
1028
|
const hitSp = (button.getAttribute("data-sp-path") ?? "").trim();
|
|
1029
1029
|
const pair = findDocumentedPair(deps.mutable.documentedPairs, hitCr, hitSp);
|
|
1030
1030
|
if (pair && isSameDocumentedPair(pair, deps.filePathLabel, deps.mutable.commentrayPathLabel)) {
|
|
1031
|
-
deps.docScrollEl
|
|
1031
|
+
const scrollTarget = paneUsesInternalYScroll(deps.docScrollEl)
|
|
1032
|
+
? deps.docScrollEl
|
|
1033
|
+
: rootScrollingElement();
|
|
1034
|
+
scrollTarget.scrollTo({ top: 0, behavior: "smooth" });
|
|
1032
1035
|
return;
|
|
1033
1036
|
}
|
|
1034
1037
|
if (pair)
|
|
@@ -2490,6 +2493,38 @@ const DUAL_MOBILE_SINGLE_PANE_MQ = "(max-width: 767px)";
|
|
|
2490
2493
|
function normalizedDualMobilePane(v) {
|
|
2491
2494
|
return v === "code" ? "code" : "doc";
|
|
2492
2495
|
}
|
|
2496
|
+
function splitLocationHashTokens(rawHash) {
|
|
2497
|
+
const hash = rawHash.replace(/^#/, "").trim();
|
|
2498
|
+
if (hash.length === 0)
|
|
2499
|
+
return [];
|
|
2500
|
+
return hash
|
|
2501
|
+
.split(/--|&/)
|
|
2502
|
+
.map((t) => t.trim())
|
|
2503
|
+
.filter((t) => t.length > 0);
|
|
2504
|
+
}
|
|
2505
|
+
function mobilePaneHashToken(pane) {
|
|
2506
|
+
return `mobile-pane-${pane}`;
|
|
2507
|
+
}
|
|
2508
|
+
function mobilePaneFromLocationHash(rawHash) {
|
|
2509
|
+
const tokens = splitLocationHashTokens(rawHash);
|
|
2510
|
+
for (const token of tokens) {
|
|
2511
|
+
if (token === "mobile-pane-code")
|
|
2512
|
+
return "code";
|
|
2513
|
+
if (token === "mobile-pane-doc")
|
|
2514
|
+
return "doc";
|
|
2515
|
+
}
|
|
2516
|
+
return null;
|
|
2517
|
+
}
|
|
2518
|
+
function updateLocationHashToken(token, shouldReplace) {
|
|
2519
|
+
const tokens = splitLocationHashTokens(globalThis.location.hash).filter((t) => !shouldReplace(t));
|
|
2520
|
+
tokens.push(token);
|
|
2521
|
+
const u = new URL(globalThis.location.href);
|
|
2522
|
+
u.hash = tokens.length > 0 ? tokens.join("&") : "";
|
|
2523
|
+
globalThis.history.replaceState(globalThis.history.state, "", u.toString());
|
|
2524
|
+
}
|
|
2525
|
+
function updateLocationHashForMobilePane(pane) {
|
|
2526
|
+
updateLocationHashToken(mobilePaneHashToken(pane), (t) => /^mobile-pane-(?:code|doc)$/.test(t));
|
|
2527
|
+
}
|
|
2493
2528
|
function isNarrowViewport() {
|
|
2494
2529
|
return globalThis.matchMedia(DUAL_MOBILE_SINGLE_PANE_MQ).matches;
|
|
2495
2530
|
}
|
|
@@ -2713,6 +2748,7 @@ function wireSourceMarkdownPaneFlip(shell, codePane, flipBtn, flipScrollBtn, sig
|
|
|
2713
2748
|
if (curPane === "doc") {
|
|
2714
2749
|
shell.setAttribute("data-dual-mobile-pane", "code");
|
|
2715
2750
|
writeWebStorageItem(localStorage, STORAGE_DUAL_MOBILE_PANE, "code");
|
|
2751
|
+
updateLocationHashForMobilePane("code");
|
|
2716
2752
|
}
|
|
2717
2753
|
}
|
|
2718
2754
|
syncSourceMarkdownFlipA11y();
|
|
@@ -2741,6 +2777,9 @@ function wireSourceMarkdownPaneFlip(shell, codePane, flipBtn, flipScrollBtn, sig
|
|
|
2741
2777
|
function wireDualMobilePaneFlip(shell, flipBtn, scrollRunners, flipScrollBtn) {
|
|
2742
2778
|
const mq = globalThis.matchMedia(DUAL_MOBILE_SINGLE_PANE_MQ);
|
|
2743
2779
|
function readStoredPane() {
|
|
2780
|
+
const fromHash = mobilePaneFromLocationHash(globalThis.location.hash);
|
|
2781
|
+
if (fromHash !== null)
|
|
2782
|
+
return fromHash;
|
|
2744
2783
|
return normalizedDualMobilePane(readWebStorageItem(localStorage, STORAGE_DUAL_MOBILE_PANE));
|
|
2745
2784
|
}
|
|
2746
2785
|
function applyForViewport() {
|
|
@@ -2767,6 +2806,7 @@ function wireDualMobilePaneFlip(shell, flipBtn, scrollRunners, flipScrollBtn) {
|
|
|
2767
2806
|
}
|
|
2768
2807
|
shell.setAttribute("data-dual-mobile-pane", next);
|
|
2769
2808
|
writeWebStorageItem(localStorage, STORAGE_DUAL_MOBILE_PANE, next);
|
|
2809
|
+
updateLocationHashForMobilePane(next);
|
|
2770
2810
|
globalThis.requestAnimationFrame(() => {
|
|
2771
2811
|
globalThis.requestAnimationFrame(() => {
|
|
2772
2812
|
if (next === "code") {
|
|
@@ -2793,49 +2833,64 @@ function wireDualMobilePaneFlip(shell, flipBtn, scrollRunners, flipScrollBtn) {
|
|
|
2793
2833
|
wireDualMobilePaneFlipScrollAffordance(flipBtn, flipScrollBtn, mq);
|
|
2794
2834
|
}
|
|
2795
2835
|
mq.addEventListener("change", applyForViewport);
|
|
2836
|
+
globalThis.addEventListener("hashchange", applyForViewport);
|
|
2796
2837
|
applyForViewport();
|
|
2797
2838
|
}
|
|
2798
2839
|
function wireStretchMobilePaneFlip(shell, codePane, flipBtn, flipScrollBtn, onAfterFlip) {
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
if (
|
|
2807
|
-
|
|
2808
|
-
|
|
2840
|
+
const stretchTable = codePane instanceof HTMLTableElement ? codePane : null;
|
|
2841
|
+
let anchorRow = null;
|
|
2842
|
+
let anchorTopBefore = 0;
|
|
2843
|
+
let rootTopBefore = 0;
|
|
2844
|
+
const captureAnchor = () => {
|
|
2845
|
+
const root = rootScrollingElement();
|
|
2846
|
+
rootTopBefore = root.scrollTop;
|
|
2847
|
+
if (stretchTable === null) {
|
|
2848
|
+
anchorRow = null;
|
|
2849
|
+
anchorTopBefore = 0;
|
|
2850
|
+
return;
|
|
2809
2851
|
}
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2852
|
+
const rows = stretchBlockRows(stretchTable);
|
|
2853
|
+
anchorRow = rows.find((row) => row.getBoundingClientRect().bottom > 0) ?? null;
|
|
2854
|
+
anchorTopBefore = anchorRow?.getBoundingClientRect().top ?? 0;
|
|
2855
|
+
};
|
|
2856
|
+
const restoreAnchor = () => {
|
|
2857
|
+
const root = rootScrollingElement();
|
|
2858
|
+
if (anchorRow !== null) {
|
|
2859
|
+
const delta = anchorRow.getBoundingClientRect().top - anchorTopBefore;
|
|
2860
|
+
if (Math.abs(delta) > 0.5) {
|
|
2861
|
+
const maxY = Math.max(0, root.scrollHeight - root.clientHeight);
|
|
2862
|
+
root.scrollTop = clamp(root.scrollTop + delta, 0, maxY);
|
|
2863
|
+
return;
|
|
2864
|
+
}
|
|
2813
2865
|
}
|
|
2814
|
-
|
|
2815
|
-
|
|
2816
|
-
|
|
2817
|
-
|
|
2818
|
-
|
|
2819
|
-
|
|
2820
|
-
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2866
|
+
const maxY = Math.max(0, root.scrollHeight - root.clientHeight);
|
|
2867
|
+
root.scrollTop = clamp(rootTopBefore, 0, maxY);
|
|
2868
|
+
};
|
|
2869
|
+
const applyBuffersAndRestore = () => {
|
|
2870
|
+
if (stretchTable !== null)
|
|
2871
|
+
applyBlockStretchRowBuffers(stretchTable);
|
|
2872
|
+
restoreAnchor();
|
|
2873
|
+
};
|
|
2874
|
+
const runners = {
|
|
2875
|
+
syncFromCodeToDoc: () => { },
|
|
2876
|
+
syncFromDocToCode: () => { },
|
|
2877
|
+
prepareMobileFlipToCode: captureAnchor,
|
|
2878
|
+
prepareMobileFlipToDoc: captureAnchor,
|
|
2879
|
+
finishMobileFlipToCode: () => {
|
|
2880
|
+
applyBuffersAndRestore();
|
|
2881
|
+
onAfterFlip?.();
|
|
2882
|
+
},
|
|
2883
|
+
finishMobileFlipToDoc: () => {
|
|
2884
|
+
applyBuffersAndRestore();
|
|
2885
|
+
onAfterFlip?.();
|
|
2886
|
+
void runMermaidOnFreshDocNodes(shell).then(() => {
|
|
2826
2887
|
requestAnimationFrame(() => {
|
|
2827
|
-
|
|
2888
|
+
applyBuffersAndRestore();
|
|
2828
2889
|
});
|
|
2829
2890
|
});
|
|
2830
|
-
}
|
|
2891
|
+
},
|
|
2831
2892
|
};
|
|
2832
|
-
|
|
2833
|
-
if (flipScrollBtn) {
|
|
2834
|
-
flipScrollBtn.addEventListener("click", runFlip);
|
|
2835
|
-
wireDualMobilePaneFlipScrollAffordance(flipBtn, flipScrollBtn, mq);
|
|
2836
|
-
}
|
|
2837
|
-
mq.addEventListener("change", applyForViewport);
|
|
2838
|
-
applyForViewport();
|
|
2893
|
+
wireDualMobilePaneFlip(shell, flipBtn, runners, flipScrollBtn);
|
|
2839
2894
|
}
|
|
2840
2895
|
/** Multi-angle stretch swaps `#shell` innerHTML; disconnect the previous table observer so listeners do not accumulate. */
|
|
2841
2896
|
let stretchRowBufferSyncHandle = null;
|
|
@@ -3238,6 +3293,27 @@ function initialCommentrayScopePathState(shell, scope, filePathLabel, commentray
|
|
|
3238
3293
|
: [filePathLabel, commentrayPathLabel].filter((s) => s.trim().length > 0).join("\n");
|
|
3239
3294
|
return { documentedPairs, pathRowsForOrdering, pathBlobWide };
|
|
3240
3295
|
}
|
|
3296
|
+
function effectiveCommentrayPathLabelFromDocumentedPairs(scope, filePathLabel, commentrayPathLabel, documentedPairs) {
|
|
3297
|
+
if (scope !== "commentray-and-paths")
|
|
3298
|
+
return commentrayPathLabel;
|
|
3299
|
+
const sourcePath = filePathLabel.trim();
|
|
3300
|
+
if (sourcePath.length === 0)
|
|
3301
|
+
return commentrayPathLabel;
|
|
3302
|
+
const pair = findDocumentedPair(documentedPairs, "", sourcePath);
|
|
3303
|
+
if (!pair)
|
|
3304
|
+
return commentrayPathLabel;
|
|
3305
|
+
const fromShell = commentrayPathLabel.trim();
|
|
3306
|
+
const fromPair = pair.commentrayPath.trim();
|
|
3307
|
+
if (fromPair.length === 0)
|
|
3308
|
+
return commentrayPathLabel;
|
|
3309
|
+
if (fromShell.length === 0)
|
|
3310
|
+
return fromPair;
|
|
3311
|
+
// Older hub HTML can carry placeholder `commentray.md` while documentedPairs already has the real path.
|
|
3312
|
+
if (normPosixPath(fromShell) === "commentray.md" && normPosixPath(fromPair) !== "commentray.md") {
|
|
3313
|
+
return fromPair;
|
|
3314
|
+
}
|
|
3315
|
+
return commentrayPathLabel;
|
|
3316
|
+
}
|
|
3241
3317
|
/**
|
|
3242
3318
|
* Fetched `commentray-nav-search.json` sometimes omits `staticBrowseUrl` on pairs; the hub embed
|
|
3243
3319
|
* carries browse URLs from the same build — merge so search hits open `_site/browse/…`, not GitHub.
|
|
@@ -3466,6 +3542,15 @@ function buildDualPaneSearcherBundle(shell, codePane) {
|
|
|
3466
3542
|
const scrollLinksRef = { current: scrollLinks };
|
|
3467
3543
|
const { scope, filePathLabel, commentrayPathLabel } = readSearchScopeFromShell(shell);
|
|
3468
3544
|
const pathInit = initialCommentrayScopePathState(shell, scope, filePathLabel, commentrayPathLabel);
|
|
3545
|
+
const effectiveCommentrayPathLabel = effectiveCommentrayPathLabelFromDocumentedPairs(scope, filePathLabel, commentrayPathLabel, pathInit.documentedPairs);
|
|
3546
|
+
if (effectiveCommentrayPathLabel.trim().length > 0) {
|
|
3547
|
+
shell.setAttribute("data-search-commentray-path", effectiveCommentrayPathLabel);
|
|
3548
|
+
const docPathEl = document.getElementById("nav-rail-doc-path");
|
|
3549
|
+
if (docPathEl) {
|
|
3550
|
+
docPathEl.textContent = effectiveCommentrayPathLabel;
|
|
3551
|
+
docPathEl.setAttribute("title", effectiveCommentrayPathLabel);
|
|
3552
|
+
}
|
|
3553
|
+
}
|
|
3469
3554
|
const indexState = {
|
|
3470
3555
|
hubNavRows: [],
|
|
3471
3556
|
documentedPairs: pathInit.documentedPairs,
|
|
@@ -3474,7 +3559,7 @@ function buildDualPaneSearcherBundle(shell, codePane) {
|
|
|
3474
3559
|
const mutable = {
|
|
3475
3560
|
rawMd,
|
|
3476
3561
|
mdLines: rawMd.split("\n"),
|
|
3477
|
-
commentrayPathLabel,
|
|
3562
|
+
commentrayPathLabel: effectiveCommentrayPathLabel,
|
|
3478
3563
|
searcher: indexSearchLineRows([]),
|
|
3479
3564
|
pathBlobWide: pathInit.pathBlobWide,
|
|
3480
3565
|
pathRowsForOrdering: indexState.pathRowsForOrdering,
|
|
@@ -3498,7 +3583,7 @@ function buildDualPaneSearcherBundle(shell, codePane) {
|
|
|
3498
3583
|
scrollLinksRef,
|
|
3499
3584
|
scope,
|
|
3500
3585
|
filePathLabel,
|
|
3501
|
-
commentrayPathLabel,
|
|
3586
|
+
commentrayPathLabel: effectiveCommentrayPathLabel,
|
|
3502
3587
|
pathInit,
|
|
3503
3588
|
indexState,
|
|
3504
3589
|
mutable,
|
|
@@ -3766,6 +3851,11 @@ function permalinkHashSuffixFromUi() {
|
|
|
3766
3851
|
pushUnique(`angle-${encodeURIComponent(id)}`);
|
|
3767
3852
|
}
|
|
3768
3853
|
}
|
|
3854
|
+
const shell = document.getElementById("shell");
|
|
3855
|
+
if (shell instanceof HTMLElement && shell.getAttribute("data-mobile-single-pane") === "true") {
|
|
3856
|
+
const pane = normalizedDualMobilePane(shell.getAttribute("data-dual-mobile-pane"));
|
|
3857
|
+
pushUnique(mobilePaneHashToken(pane));
|
|
3858
|
+
}
|
|
3769
3859
|
const activeAnchor = activeCommentrayHashTokenFromViewport();
|
|
3770
3860
|
if (activeAnchor)
|
|
3771
3861
|
pushUnique(activeAnchor);
|