@commentray/render 0.1.2 → 0.3.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/dist/block-stretch-buffer-sync.d.ts +16 -0
- package/dist/block-stretch-buffer-sync.d.ts.map +1 -0
- package/dist/block-stretch-buffer-sync.js +271 -0
- package/dist/block-stretch-buffer-sync.js.map +1 -0
- package/dist/block-stretch-layout.d.ts +18 -5
- package/dist/block-stretch-layout.d.ts.map +1 -1
- package/dist/block-stretch-layout.js +121 -43
- package/dist/block-stretch-layout.js.map +1 -1
- package/dist/browse-page-slug.d.ts +3 -4
- package/dist/browse-page-slug.d.ts.map +1 -1
- package/dist/browse-page-slug.js +3 -4
- package/dist/browse-page-slug.js.map +1 -1
- package/dist/build-commentray-nav-search.d.ts +2 -2
- package/dist/build-commentray-nav-search.d.ts.map +1 -1
- package/dist/build-commentray-nav-search.js +8 -3
- package/dist/build-commentray-nav-search.js.map +1 -1
- package/dist/code-browser-block-rays.d.ts +11 -0
- package/dist/code-browser-block-rays.d.ts.map +1 -1
- package/dist/code-browser-block-rays.js +25 -5
- package/dist/code-browser-block-rays.js.map +1 -1
- package/dist/code-browser-client.bundle.js +12 -11
- package/dist/code-browser-client.js +1484 -265
- package/dist/code-browser-client.js.map +1 -1
- package/dist/code-browser-pair-nav.d.ts +9 -2
- package/dist/code-browser-pair-nav.d.ts.map +1 -1
- package/dist/code-browser-pair-nav.js +53 -14
- package/dist/code-browser-pair-nav.js.map +1 -1
- package/dist/code-browser-scroll-buffer-equalize.d.ts +25 -0
- package/dist/code-browser-scroll-buffer-equalize.d.ts.map +1 -0
- package/dist/code-browser-scroll-buffer-equalize.js +316 -0
- package/dist/code-browser-scroll-buffer-equalize.js.map +1 -0
- package/dist/code-browser-scroll-sync-monotonic.d.ts +17 -0
- package/dist/code-browser-scroll-sync-monotonic.d.ts.map +1 -0
- package/dist/code-browser-scroll-sync-monotonic.js +22 -0
- package/dist/code-browser-scroll-sync-monotonic.js.map +1 -0
- package/dist/code-browser-scroll-sync-strategy.d.ts +12 -0
- package/dist/code-browser-scroll-sync-strategy.d.ts.map +1 -0
- package/dist/code-browser-scroll-sync-strategy.js +28 -0
- package/dist/code-browser-scroll-sync-strategy.js.map +1 -0
- package/dist/code-browser-scroll-sync.d.ts +2 -2
- 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-smooth-reveal-dedup.d.ts +25 -0
- package/dist/code-browser-smooth-reveal-dedup.d.ts.map +1 -0
- package/dist/code-browser-smooth-reveal-dedup.js +25 -0
- package/dist/code-browser-smooth-reveal-dedup.js.map +1 -0
- package/dist/code-browser.d.ts +25 -8
- package/dist/code-browser.d.ts.map +1 -1
- package/dist/code-browser.js +359 -86
- package/dist/code-browser.js.map +1 -1
- package/dist/commentray-anchor-viewport-probe.d.ts +5 -1
- package/dist/commentray-anchor-viewport-probe.d.ts.map +1 -1
- package/dist/commentray-anchor-viewport-probe.js +8 -2
- package/dist/commentray-anchor-viewport-probe.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/inject-md-line-anchors.d.ts +1 -1
- package/dist/inject-md-line-anchors.d.ts.map +1 -1
- package/dist/inject-md-line-anchors.js +9 -5
- package/dist/inject-md-line-anchors.js.map +1 -1
- package/dist/markdown-pipeline.js +1 -1
- package/dist/markdown-pipeline.js.map +1 -1
- package/dist/mermaid-runtime-html.d.ts.map +1 -1
- package/dist/mermaid-runtime-html.js +4 -1
- package/dist/mermaid-runtime-html.js.map +1 -1
- package/dist/reading-viewport-comfort.d.ts +12 -0
- package/dist/reading-viewport-comfort.d.ts.map +1 -0
- package/dist/reading-viewport-comfort.js +14 -0
- package/dist/reading-viewport-comfort.js.map +1 -0
- package/package.json +2 -2
package/dist/code-browser.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { existsSync, readFileSync } from "node:fs";
|
|
2
2
|
import path, { join } from "node:path";
|
|
3
|
-
import { buildBlockScrollLinks, findMonorepoPackagesDir, monorepoLayoutStartDir, normalizeRepoRelativePath, } from "@commentray/core";
|
|
4
|
-
import { tryBuildBlockStretchTableHtml } from "./block-stretch-layout.js";
|
|
3
|
+
import { buildBlockScrollLinks, DEFAULT_STRETCH_BUFFER_SYNC, findMonorepoPackagesDir, monorepoLayoutStartDir, normalizeRepoRelativePath, } from "@commentray/core";
|
|
4
|
+
import { tryBuildBlockStretchTableHtml, } from "./block-stretch-layout.js";
|
|
5
5
|
import { formatCommentrayBuiltAtLocal } from "./build-stamp.js";
|
|
6
6
|
import { escapeHtml } from "./html-utils.js";
|
|
7
7
|
import { commentrayColorThemeHeadBoot } from "./code-browser-color-theme.js";
|
|
@@ -13,6 +13,7 @@ import { renderMarkdownToHtml } from "./markdown-pipeline.js";
|
|
|
13
13
|
import { commentrayRenderVersion } from "./package-version.js";
|
|
14
14
|
import { normPosixPath } from "./code-browser-pair-nav.js";
|
|
15
15
|
import { injectCommentrayDocAnchors, injectSourceMarkdownAnchors, } from "./inject-md-line-anchors.js";
|
|
16
|
+
import { DEFAULT_DUAL_PANE_SCROLL_SYNC_STRATEGY, } from "./code-browser-scroll-sync-strategy.js";
|
|
16
17
|
function renderGeneratorMetaHtml(label) {
|
|
17
18
|
const t = label?.trim();
|
|
18
19
|
if (!t)
|
|
@@ -184,7 +185,7 @@ function renderToolbarDocHubHtml(opts) {
|
|
|
184
185
|
}
|
|
185
186
|
function dualPanePanesInnerHtml(codeHtml, commentrayHtml, sourceMarkdownRenderedHtml) {
|
|
186
187
|
const sourceRenderedPaneHtml = typeof sourceMarkdownRenderedHtml === "string" && sourceMarkdownRenderedHtml.trim().length > 0
|
|
187
|
-
? ` <div class="source-pane source-pane--rendered-md" id="code-pane-markdown-body">${sourceMarkdownRenderedHtml}</div>\n`
|
|
188
|
+
? ` <div class="source-pane source-pane--rendered-md" id="code-pane-markdown-body" data-source-markdown-body="true">${sourceMarkdownRenderedHtml}</div>\n`
|
|
188
189
|
: "";
|
|
189
190
|
return (` <section class="pane--code" id="code-pane" aria-label="Source code">` +
|
|
190
191
|
` <div class="source-pane source-pane--code" id="code-pane-code-body">${codeHtml}</div>\n` +
|
|
@@ -214,6 +215,8 @@ function isMarkdownLikeSource(opts) {
|
|
|
214
215
|
const lang = opts.language.trim().toLowerCase();
|
|
215
216
|
if (lang === "md" || lang === "markdown" || lang === "mdx")
|
|
216
217
|
return true;
|
|
218
|
+
if (lang.length > 0)
|
|
219
|
+
return false;
|
|
217
220
|
const filePath = (opts.filePath ?? "").trim().toLowerCase();
|
|
218
221
|
return filePath.endsWith(".md") || filePath.endsWith(".mdx") || filePath.endsWith(".markdown");
|
|
219
222
|
}
|
|
@@ -252,9 +255,24 @@ function renderShellPairContextHtml(filePath, commentrayPath) {
|
|
|
252
255
|
</div>
|
|
253
256
|
</div>`;
|
|
254
257
|
}
|
|
255
|
-
function
|
|
258
|
+
function shellPairSourcePath(filePath, sourceRelative) {
|
|
259
|
+
const filePathTrimmed = (filePath ?? "").trim();
|
|
260
|
+
if (filePathTrimmed.length > 0)
|
|
261
|
+
return filePathTrimmed;
|
|
262
|
+
return (sourceRelative ?? "").trim();
|
|
263
|
+
}
|
|
264
|
+
function shellPairCommentrayPath(commentrayPath, fallbackCommentrayPath) {
|
|
265
|
+
const commentrayPathTrimmed = (commentrayPath ?? "").trim();
|
|
266
|
+
if (commentrayPathTrimmed.length > 0)
|
|
267
|
+
return commentrayPathTrimmed;
|
|
268
|
+
return (fallbackCommentrayPath ?? "").trim();
|
|
269
|
+
}
|
|
270
|
+
function wrapShellInnerWithPairContext(pairContextHtml, mainHtml) {
|
|
256
271
|
const row = pairContextHtml.trim().length > 0 ? ` ${pairContextHtml.trim()}\n` : "";
|
|
257
|
-
return `${row}
|
|
272
|
+
return `${row}${mainHtml}`;
|
|
273
|
+
}
|
|
274
|
+
function wrapDualShellInner(pairContextHtml, panesHtml) {
|
|
275
|
+
return wrapShellInnerWithPairContext(pairContextHtml, ` <div class="shell__panes">\n${panesHtml} </div>\n`);
|
|
258
276
|
}
|
|
259
277
|
/** IIFE produced by `npm run build -w @commentray/render` (esbuild of `code-browser-client.ts`). */
|
|
260
278
|
function loadCodeBrowserClientBundle() {
|
|
@@ -609,7 +627,7 @@ const CODE_BROWSER_STYLES = `
|
|
|
609
627
|
flex-wrap: wrap;
|
|
610
628
|
align-items: center;
|
|
611
629
|
justify-content: flex-end;
|
|
612
|
-
gap:
|
|
630
|
+
gap: 6px;
|
|
613
631
|
margin-left: auto;
|
|
614
632
|
min-width: 0;
|
|
615
633
|
}
|
|
@@ -1012,6 +1030,11 @@ ${CODE_BROWSER_INTRO_STYLES}
|
|
|
1012
1030
|
margin: -1px -3px;
|
|
1013
1031
|
background: color-mix(in oklab, CanvasText 10%, Canvas);
|
|
1014
1032
|
}
|
|
1033
|
+
.documented-files-tree .tree-file-link:focus-visible {
|
|
1034
|
+
outline: 2px solid color-mix(in oklab, CanvasText 45%, Canvas);
|
|
1035
|
+
outline-offset: 2px;
|
|
1036
|
+
border-radius: 3px;
|
|
1037
|
+
}
|
|
1015
1038
|
.toolbar button {
|
|
1016
1039
|
font: inherit;
|
|
1017
1040
|
font-size: var(--cr-ui-fs);
|
|
@@ -1044,6 +1067,10 @@ ${CODE_BROWSER_INTRO_STYLES}
|
|
|
1044
1067
|
font: inherit;
|
|
1045
1068
|
}
|
|
1046
1069
|
.search-results button.hit:hover { background: color-mix(in oklab, CanvasText 10%, Canvas); }
|
|
1070
|
+
.search-results button.hit:focus-visible {
|
|
1071
|
+
outline: 2px solid color-mix(in oklab, CanvasText 45%, Canvas);
|
|
1072
|
+
outline-offset: 2px;
|
|
1073
|
+
}
|
|
1047
1074
|
.search-results button.hit .meta { opacity: 0.8; font-size: 12px; }
|
|
1048
1075
|
.search-results button.hit .src-tag { opacity: 0.75; font-weight: 500; font-size: 11px; }
|
|
1049
1076
|
.search-results button.hit .snippet {
|
|
@@ -1123,7 +1150,66 @@ ${CODE_BROWSER_INTRO_STYLES}
|
|
|
1123
1150
|
text-overflow: ellipsis;
|
|
1124
1151
|
white-space: nowrap;
|
|
1125
1152
|
}
|
|
1126
|
-
.shell__pair-path--secondary {
|
|
1153
|
+
.shell__pair-path--secondary {
|
|
1154
|
+
opacity: 0.88;
|
|
1155
|
+
text-align: right;
|
|
1156
|
+
}
|
|
1157
|
+
.shell--stretch-rows .shell__pair-context {
|
|
1158
|
+
--shell-pair-gutter-w: 14px;
|
|
1159
|
+
--shell-pair-gutter-half: calc(var(--shell-pair-gutter-w) / 2);
|
|
1160
|
+
display: grid;
|
|
1161
|
+
grid-template-columns:
|
|
1162
|
+
minmax(0, calc(var(--stretch-code-pct, 50%) - var(--shell-pair-gutter-half)))
|
|
1163
|
+
var(--shell-pair-gutter-w)
|
|
1164
|
+
minmax(0, calc(100% - var(--stretch-code-pct, 50%) - var(--shell-pair-gutter-half)));
|
|
1165
|
+
width: 100%;
|
|
1166
|
+
box-sizing: border-box;
|
|
1167
|
+
}
|
|
1168
|
+
.shell--stretch-rows .shell__pair-cell--src,
|
|
1169
|
+
.shell--stretch-rows .shell__pair-cell--doc,
|
|
1170
|
+
.shell--stretch-rows .shell__pair-gutter-spacer {
|
|
1171
|
+
min-width: 0;
|
|
1172
|
+
}
|
|
1173
|
+
.shell--stretch-rows .shell__pair-cell--src {
|
|
1174
|
+
grid-column: 1;
|
|
1175
|
+
padding-left: var(--cr-pane-inline-pad);
|
|
1176
|
+
padding-right: 0;
|
|
1177
|
+
}
|
|
1178
|
+
.shell--stretch-rows .shell__pair-gutter-spacer {
|
|
1179
|
+
grid-column: 2;
|
|
1180
|
+
width: var(--shell-pair-gutter-w);
|
|
1181
|
+
min-width: var(--shell-pair-gutter-w);
|
|
1182
|
+
}
|
|
1183
|
+
.shell--stretch-rows .shell__pair-cell--doc {
|
|
1184
|
+
grid-column: 3;
|
|
1185
|
+
padding-left: var(--cr-pane-inline-pad);
|
|
1186
|
+
padding-right: var(--cr-pane-inline-pad);
|
|
1187
|
+
}
|
|
1188
|
+
.shell[data-mobile-single-pane="true"] .shell__pair-context {
|
|
1189
|
+
display: flex;
|
|
1190
|
+
flex-direction: column;
|
|
1191
|
+
align-items: stretch;
|
|
1192
|
+
gap: 4px;
|
|
1193
|
+
padding: 4px 0 6px;
|
|
1194
|
+
}
|
|
1195
|
+
.shell[data-mobile-single-pane="true"] .shell__pair-cell--src,
|
|
1196
|
+
.shell[data-mobile-single-pane="true"] .shell__pair-cell--doc {
|
|
1197
|
+
width: 100%;
|
|
1198
|
+
padding-right: var(--cr-pane-inline-pad);
|
|
1199
|
+
box-sizing: border-box;
|
|
1200
|
+
}
|
|
1201
|
+
.shell[data-mobile-single-pane="true"][data-dual-mobile-pane="code"] .shell__pair-cell--doc,
|
|
1202
|
+
.shell[data-mobile-single-pane="true"][data-dual-mobile-pane="code"] .shell__pair-gutter-spacer {
|
|
1203
|
+
display: none;
|
|
1204
|
+
}
|
|
1205
|
+
.shell[data-mobile-single-pane="true"][data-dual-mobile-pane="doc"] .shell__pair-cell--src,
|
|
1206
|
+
.shell[data-mobile-single-pane="true"][data-dual-mobile-pane="doc"] .shell__pair-gutter-spacer {
|
|
1207
|
+
display: none;
|
|
1208
|
+
}
|
|
1209
|
+
.shell[data-mobile-single-pane="true"]:not([data-dual-mobile-pane]) .shell__pair-cell--src,
|
|
1210
|
+
.shell[data-mobile-single-pane="true"]:not([data-dual-mobile-pane]) .shell__pair-gutter-spacer {
|
|
1211
|
+
display: none;
|
|
1212
|
+
}
|
|
1127
1213
|
.pane--code {
|
|
1128
1214
|
flex: 0 0 var(--split-pct, 46%);
|
|
1129
1215
|
min-width: 120px; overflow: auto; padding: 12px var(--cr-pane-inline-pad);
|
|
@@ -1261,6 +1347,8 @@ ${CODE_BROWSER_INTRO_STYLES}
|
|
|
1261
1347
|
.doc-pane-body {
|
|
1262
1348
|
flex: 1 1 auto; min-height: 0; overflow: auto;
|
|
1263
1349
|
}
|
|
1350
|
+
/* scroll-behavior: smooth was removed: it interpolates many scroll events per gesture and
|
|
1351
|
+
* exhausts the partner-echo guard in wireBidirectionalScroll, so doc↔code ping-pong returns. */
|
|
1264
1352
|
/* Inline backtick code chips (GitHub-like): prose context only, never fenced pre/code blocks. */
|
|
1265
1353
|
.pane--doc .doc-pane-body :where(p, li, blockquote, td, th, h1, h2, h3, h4, h5, h6) > code,
|
|
1266
1354
|
.shell--stretch-rows .stretch-preamble :where(p, li, blockquote, td, th, h1, h2, h3, h4, h5, h6) > code,
|
|
@@ -1751,6 +1839,22 @@ ${CODE_BROWSER_INTRO_STYLES}
|
|
|
1751
1839
|
flex: 1 1 auto;
|
|
1752
1840
|
padding-left: var(--cr-pane-inline-pad);
|
|
1753
1841
|
}
|
|
1842
|
+
.shell.shell--stretch-rows[data-dual-mobile-pane="code"] .stretch-col-doc,
|
|
1843
|
+
.shell.shell--stretch-rows[data-dual-mobile-pane="doc"] .stretch-col-code,
|
|
1844
|
+
.shell.shell--stretch-rows[data-dual-mobile-pane="code"] td.stretch-doc,
|
|
1845
|
+
.shell.shell--stretch-rows[data-dual-mobile-pane="doc"] td.stretch-code {
|
|
1846
|
+
display: none;
|
|
1847
|
+
}
|
|
1848
|
+
.shell.shell--stretch-rows[data-dual-mobile-pane="code"] td.stretch-code,
|
|
1849
|
+
.shell.shell--stretch-rows[data-dual-mobile-pane="doc"] td.stretch-doc {
|
|
1850
|
+
display: table-cell;
|
|
1851
|
+
width: 100%;
|
|
1852
|
+
padding-left: 0;
|
|
1853
|
+
padding-right: 0;
|
|
1854
|
+
}
|
|
1855
|
+
.shell.shell--stretch-rows[data-dual-mobile-pane] #stretch-gutter {
|
|
1856
|
+
display: none;
|
|
1857
|
+
}
|
|
1754
1858
|
}
|
|
1755
1859
|
.pane--doc { font-size: 15px; line-height: 1.45; }
|
|
1756
1860
|
.pane--doc img { max-width: 100%; height: auto; }
|
|
@@ -1762,9 +1866,8 @@ ${CODE_BROWSER_INTRO_STYLES}
|
|
|
1762
1866
|
.pane--doc .commentray-block-anchor {
|
|
1763
1867
|
display: block;
|
|
1764
1868
|
height: 0;
|
|
1765
|
-
margin:
|
|
1869
|
+
margin: 0;
|
|
1766
1870
|
border: 0;
|
|
1767
|
-
border-top: 1px solid color-mix(in oklab, CanvasText 22%, Canvas);
|
|
1768
1871
|
pointer-events: none;
|
|
1769
1872
|
}
|
|
1770
1873
|
.shell--stretch-rows {
|
|
@@ -1772,15 +1875,17 @@ ${CODE_BROWSER_INTRO_STYLES}
|
|
|
1772
1875
|
min-height: 0;
|
|
1773
1876
|
overflow: auto;
|
|
1774
1877
|
display: block;
|
|
1775
|
-
padding: 0
|
|
1878
|
+
padding: 0 0 20px;
|
|
1776
1879
|
}
|
|
1777
1880
|
.shell--stretch-rows .stretch-preamble {
|
|
1778
1881
|
padding: 8px 4px 16px;
|
|
1779
1882
|
margin-bottom: 8px;
|
|
1780
|
-
border-bottom: 1px solid color-mix(in oklab, CanvasText 12%, Canvas);
|
|
1781
1883
|
font-size: 15px;
|
|
1782
1884
|
line-height: 1.45;
|
|
1783
1885
|
overflow-x: auto;
|
|
1886
|
+
/* overflow-x other than visible makes overflow-y:visible compute to auto, which traps
|
|
1887
|
+
* vertical wheel on this node instead of the shell scrollport when height is ever capped. */
|
|
1888
|
+
overflow-y: hidden;
|
|
1784
1889
|
max-width: 100%;
|
|
1785
1890
|
}
|
|
1786
1891
|
.shell--stretch-rows .stretch-preamble img { max-width: 100%; height: auto; }
|
|
@@ -1789,27 +1894,49 @@ ${CODE_BROWSER_INTRO_STYLES}
|
|
|
1789
1894
|
border-collapse: collapse;
|
|
1790
1895
|
table-layout: fixed;
|
|
1791
1896
|
}
|
|
1792
|
-
.stretch-
|
|
1793
|
-
|
|
1897
|
+
.stretch-grid {
|
|
1898
|
+
position: relative;
|
|
1899
|
+
}
|
|
1900
|
+
.stretch-col-code { width: var(--stretch-code-pct, 50%); }
|
|
1901
|
+
.stretch-col-doc { width: calc(100% - var(--stretch-code-pct, 50%)); }
|
|
1794
1902
|
.block-stretch td.stretch-code {
|
|
1795
1903
|
vertical-align: top;
|
|
1796
1904
|
padding: 0 12px 0 0;
|
|
1797
|
-
|
|
1905
|
+
box-shadow: inset -1px 0 0 color-mix(in oklab, CanvasText 10%, Canvas);
|
|
1906
|
+
}
|
|
1907
|
+
#shell[data-stretch-buffer-sync="flow-synchronizer"] .block-stretch td.stretch-code > .stretch-cell-measure,
|
|
1908
|
+
#shell[data-stretch-buffer-sync="flow-synchronizer"] .block-stretch td.stretch-doc > .stretch-cell-measure {
|
|
1909
|
+
display: block;
|
|
1910
|
+
width: 100%;
|
|
1911
|
+
box-sizing: border-box;
|
|
1912
|
+
height: max-content;
|
|
1913
|
+
max-height: max-content;
|
|
1914
|
+
}
|
|
1915
|
+
#shell[data-stretch-buffer-sync="flow-synchronizer"] .block-stretch td.stretch-doc .stretch-doc-inner {
|
|
1916
|
+
height: max-content;
|
|
1917
|
+
max-height: max-content;
|
|
1918
|
+
}
|
|
1919
|
+
#shell[data-stretch-buffer-sync="flow-synchronizer"] .block-stretch .stretch-code-stack {
|
|
1920
|
+
height: max-content;
|
|
1921
|
+
max-height: max-content;
|
|
1798
1922
|
}
|
|
1799
1923
|
.block-stretch td.stretch-doc {
|
|
1800
1924
|
vertical-align: top;
|
|
1801
1925
|
padding: 0 0 0 12px;
|
|
1802
|
-
|
|
1926
|
+
box-shadow: inset 1px 0 0 color-mix(in oklab, CanvasText 8%, Canvas);
|
|
1803
1927
|
}
|
|
1804
1928
|
.block-stretch td.stretch-doc .stretch-doc-inner {
|
|
1805
1929
|
font-size: 15px;
|
|
1806
1930
|
line-height: 1.45;
|
|
1807
1931
|
min-width: 0;
|
|
1808
1932
|
overflow-x: auto;
|
|
1933
|
+
/* Keep vertical scrolling on the shell; see stretch-preamble rule above. */
|
|
1934
|
+
overflow-y: hidden;
|
|
1809
1935
|
}
|
|
1810
1936
|
.block-stretch td.stretch-doc .stretch-doc-inner img { max-width: 100%; height: auto; }
|
|
1811
1937
|
.block-stretch td.stretch-doc .stretch-doc-inner .commentray-mermaid {
|
|
1812
1938
|
overflow-x: auto;
|
|
1939
|
+
overflow-y: hidden;
|
|
1813
1940
|
max-width: 100%;
|
|
1814
1941
|
}
|
|
1815
1942
|
.block-stretch.wrap td.stretch-doc .stretch-doc-inner {
|
|
@@ -1828,7 +1955,6 @@ ${CODE_BROWSER_INTRO_STYLES}
|
|
|
1828
1955
|
font-size: 13px;
|
|
1829
1956
|
vertical-align: top;
|
|
1830
1957
|
}
|
|
1831
|
-
.block-stretch .stretch-gap-mark { display: inline-block; padding-top: 2px; }
|
|
1832
1958
|
.block-stretch .stretch-code-stack {
|
|
1833
1959
|
display: flex;
|
|
1834
1960
|
flex-direction: column;
|
|
@@ -1878,15 +2004,39 @@ ${CODE_BROWSER_INTRO_STYLES}
|
|
|
1878
2004
|
.block-stretch:not(.wrap) .stretch-doc-inner pre code {
|
|
1879
2005
|
white-space: pre;
|
|
1880
2006
|
}
|
|
2007
|
+
.stretch-gutter {
|
|
2008
|
+
position: absolute;
|
|
2009
|
+
top: 0;
|
|
2010
|
+
bottom: 0;
|
|
2011
|
+
left: var(--stretch-code-pct, 50%);
|
|
2012
|
+
transform: translateX(-50%);
|
|
2013
|
+
width: 14px;
|
|
2014
|
+
cursor: col-resize;
|
|
2015
|
+
touch-action: none;
|
|
2016
|
+
border-left: 1px solid color-mix(in oklab, CanvasText 14%, Canvas);
|
|
2017
|
+
border-right: 1px solid color-mix(in oklab, CanvasText 10%, Canvas);
|
|
2018
|
+
background: color-mix(in oklab, CanvasText 8%, Canvas);
|
|
2019
|
+
border-radius: 999px;
|
|
2020
|
+
--commentray-ray-accent: #3b7dd8;
|
|
2021
|
+
z-index: 6;
|
|
2022
|
+
}
|
|
2023
|
+
@media (prefers-color-scheme: dark) {
|
|
2024
|
+
:root:is(:not([data-commentray-theme]), [data-commentray-theme="system"]) .stretch-gutter {
|
|
2025
|
+
--commentray-ray-accent: #6eb0ff;
|
|
2026
|
+
}
|
|
2027
|
+
}
|
|
2028
|
+
:root[data-commentray-theme="dark"] .stretch-gutter {
|
|
2029
|
+
--commentray-ray-accent: #6eb0ff;
|
|
2030
|
+
}
|
|
1881
2031
|
`;
|
|
1882
2032
|
/** Native tooltip on #search-q (short hint is visible under the search row). */
|
|
1883
2033
|
const CODE_BROWSER_SEARCH_INPUT_TITLE = "Filename, path, or words. Matches this pair (source + commentray lines) first; merges commentray-nav-search.json when the export includes it (indexed paths + commentray lines).";
|
|
1884
2034
|
function buildCodeBrowserPageHtml(p) {
|
|
1885
2035
|
const shellClass = p.layout === "stretch" ? "shell shell--stretch-rows" : "shell";
|
|
1886
|
-
const dualFlipControlHtml = p.layout === "dual"
|
|
2036
|
+
const dualFlipControlHtml = p.layout === "dual" || p.layout === "stretch"
|
|
1887
2037
|
? `<button type="button" id="mobile-pane-flip" class="toolbar-icon-btn toolbar-icon-btn--flip-only-narrow" aria-label="Switch between source code and commentary" title="Switch between source code and commentary">${TOOLBAR_ICON_FLIP_PANES_SVG}</button>`
|
|
1888
2038
|
: "";
|
|
1889
|
-
const dualFlipScrollAffordanceHtml = p.layout === "dual"
|
|
2039
|
+
const dualFlipScrollAffordanceHtml = p.layout === "dual" || p.layout === "stretch"
|
|
1890
2040
|
? `<button type="button" id="mobile-pane-flip-scroll" class="toolbar-icon-btn toolbar-icon-btn--flip-scroll-narrow" hidden aria-label="Switch between source code and commentary" title="Switch between source code and commentary">${TOOLBAR_ICON_FLIP_PANES_SVG}</button>`
|
|
1891
2041
|
: "";
|
|
1892
2042
|
return `<!doctype html>
|
|
@@ -1915,13 +2065,13 @@ ${CODE_BROWSER_STYLES}
|
|
|
1915
2065
|
${p.toolbarSiteHubHtml}
|
|
1916
2066
|
${p.navRailDocumentedHtml}
|
|
1917
2067
|
${p.angleSelectHtml}
|
|
2068
|
+
${dualFlipControlHtml}
|
|
1918
2069
|
<label class="toolbar-wrap-lines" title="Wrap long lines in the source pane; in commentary, wrap long words and fenced code when on (wide tables and diagrams scroll horizontally).">
|
|
1919
2070
|
<input type="checkbox" id="wrap-lines" class="toolbar-wrap-lines__input" />
|
|
1920
2071
|
<span class="toolbar-wrap-lines__box" aria-hidden="true"></span>
|
|
1921
2072
|
<span class="toolbar-wrap-lines__face" aria-hidden="true">${TOOLBAR_ICON_WRAP_SVG}</span>
|
|
1922
2073
|
<span class="toolbar-wrap-lines__caption">Wrap lines</span>
|
|
1923
2074
|
</label>
|
|
1924
|
-
${dualFlipControlHtml}
|
|
1925
2075
|
${p.sourceMarkdownToggleHtml}
|
|
1926
2076
|
${p.toolbarDocHubHtml}
|
|
1927
2077
|
${p.relatedNavHtml}
|
|
@@ -1945,7 +2095,7 @@ ${TOOLBAR_COLOR_THEME_HTML}
|
|
|
1945
2095
|
<div class="search-results" id="search-results" hidden aria-live="polite"></div>
|
|
1946
2096
|
</header>
|
|
1947
2097
|
<main id="main-content" class="app__main" tabindex="-1">
|
|
1948
|
-
<div class="${shellClass}" id="shell" data-layout="${p.layout}"${p.layout === "dual" ? ' data-dual-mobile-pane="doc"' : ""}${p.sourcePaneModeAttr} data-raw-code-b64="${escapeHtml(p.rawCodeB64)}" data-raw-md-b64="${escapeHtml(p.rawMdB64)}" data-scroll-block-links-b64="${escapeHtml(p.scrollBlockLinksB64)}"${p.shellDocumentedPairsAttr}${p.shellSearchAttrs}${p.shellPairIdentityDataAttrs}${p.shellPairDocDataAttr}>
|
|
2098
|
+
<div class="${shellClass}" id="shell" data-layout="${p.layout}"${p.layout === "dual" || p.layout === "stretch" ? ' data-dual-mobile-pane="doc"' : ""}${p.sourcePaneModeAttr} data-raw-code-b64="${escapeHtml(p.rawCodeB64)}" data-raw-md-b64="${escapeHtml(p.rawMdB64)}" data-scroll-block-links-b64="${escapeHtml(p.scrollBlockLinksB64)}"${p.shellDocumentedPairsAttr}${p.shellSearchAttrs}${p.shellPairIdentityDataAttrs}${p.shellPairDocDataAttr}${p.scrollSyncStrategyShellAttr ?? ""}${p.stretchBufferSyncShellAttr ?? ""}>
|
|
1949
2099
|
${p.shellInner}
|
|
1950
2100
|
</div>
|
|
1951
2101
|
</main>
|
|
@@ -1962,6 +2112,27 @@ ${loadCodeBrowserClientBundle()}
|
|
|
1962
2112
|
function firstNonEmpty(values) {
|
|
1963
2113
|
return values.find((v) => v.trim().length > 0);
|
|
1964
2114
|
}
|
|
2115
|
+
function stretchBufferSyncFromOpts(opts) {
|
|
2116
|
+
return opts.stretchBufferSync ?? DEFAULT_STRETCH_BUFFER_SYNC;
|
|
2117
|
+
}
|
|
2118
|
+
function angleBlockStretchRowsPathOk(spec, opts) {
|
|
2119
|
+
const rows = spec.blockStretchRows;
|
|
2120
|
+
if (rows === undefined)
|
|
2121
|
+
return false;
|
|
2122
|
+
const angleCrNorm = normalizeRepoRelativePath(spec.commentrayPathRel.replaceAll("\\", "/"));
|
|
2123
|
+
const primaryNorm = normalizeRepoRelativePath((opts.filePath ?? "").replaceAll("\\", "/"));
|
|
2124
|
+
return (normalizeRepoRelativePath(rows.commentrayPathRel.replaceAll("\\", "/")) === angleCrNorm &&
|
|
2125
|
+
normalizeRepoRelativePath(rows.sourceRelative.replaceAll("\\", "/")) === primaryNorm);
|
|
2126
|
+
}
|
|
2127
|
+
function multiAngleToolbarAngleSelectHtml(multi, defaultId) {
|
|
2128
|
+
const selOpts = multi.angles
|
|
2129
|
+
.map((a) => {
|
|
2130
|
+
const lab = escapeHtml(a.title?.trim() || a.id);
|
|
2131
|
+
return `<option value="${escapeHtml(a.id)}"${a.id === defaultId ? " selected" : ""}>${lab}</option>`;
|
|
2132
|
+
})
|
|
2133
|
+
.join("");
|
|
2134
|
+
return `<span class="toolbar-angle-picker"><label class="toolbar-angle-picker__lab nav-rail__search-label" for="angle-select">Angle</label><select id="angle-select" aria-label="Commentray angle">${selOpts}</select></span>`;
|
|
2135
|
+
}
|
|
1965
2136
|
function resolveMultiAngleDefaultSelection(args) {
|
|
1966
2137
|
const { multi, defaultId, opts, builtAngles } = args;
|
|
1967
2138
|
let defaultMarkdown = opts.commentrayMarkdown;
|
|
@@ -1999,11 +2170,8 @@ function resolveMultiAngleDefaultSelection(args) {
|
|
|
1999
2170
|
}
|
|
2000
2171
|
async function multiAngleJsonRowAndDocHtml(opts, spec) {
|
|
2001
2172
|
const rows = spec.blockStretchRows;
|
|
2173
|
+
const rowsPathOk = angleBlockStretchRowsPathOk(spec, opts);
|
|
2002
2174
|
const angleCrNorm = normalizeRepoRelativePath(spec.commentrayPathRel.replaceAll("\\", "/"));
|
|
2003
|
-
const primaryNorm = normalizeRepoRelativePath((opts.filePath ?? "").replaceAll("\\", "/"));
|
|
2004
|
-
const rowsPathOk = rows !== undefined &&
|
|
2005
|
-
normalizeRepoRelativePath(rows.commentrayPathRel.replaceAll("\\", "/")) === angleCrNorm &&
|
|
2006
|
-
normalizeRepoRelativePath(rows.sourceRelative.replaceAll("\\", "/")) === primaryNorm;
|
|
2007
2175
|
const links = rows !== undefined && rowsPathOk
|
|
2008
2176
|
? buildBlockScrollLinks(rows.index, rows.sourceRelative, angleCrNorm, spec.markdown, opts.code)
|
|
2009
2177
|
: [];
|
|
@@ -2027,6 +2195,85 @@ async function multiAngleJsonRowAndDocHtml(opts, spec) {
|
|
|
2027
2195
|
scrollB64,
|
|
2028
2196
|
};
|
|
2029
2197
|
}
|
|
2198
|
+
/**
|
|
2199
|
+
* When every angle has a valid block index and `tryBuildBlockStretchTableHtml` succeeds for each,
|
|
2200
|
+
* emit one outer scroll (table rows = aligned block “arithmetics”) instead of dual-pane sync.
|
|
2201
|
+
*/
|
|
2202
|
+
async function buildMultiAngleBlockStretchShell(opts, multi) {
|
|
2203
|
+
const defaultId = multi.angles.some((a) => a.id === multi.defaultAngleId)
|
|
2204
|
+
? multi.defaultAngleId
|
|
2205
|
+
: (multi.angles[0]?.id ?? "main");
|
|
2206
|
+
const sourceMarkdownEnabled = isMarkdownLikeSource(opts);
|
|
2207
|
+
const sourceMarkdownUrls = sourceMarkdownEnabled ? sourcePaneOutputUrls(opts) : undefined;
|
|
2208
|
+
const perAngle = [];
|
|
2209
|
+
for (const spec of multi.angles) {
|
|
2210
|
+
if (!angleBlockStretchRowsPathOk(spec, opts))
|
|
2211
|
+
return null;
|
|
2212
|
+
const rows = spec.blockStretchRows;
|
|
2213
|
+
if (rows === undefined)
|
|
2214
|
+
return null;
|
|
2215
|
+
const stretched = await tryBuildBlockStretchTableHtml({
|
|
2216
|
+
code: opts.code,
|
|
2217
|
+
language: opts.language,
|
|
2218
|
+
commentrayMarkdown: spec.markdown,
|
|
2219
|
+
index: rows.index,
|
|
2220
|
+
sourceRelative: rows.sourceRelative,
|
|
2221
|
+
commentrayPathRel: rows.commentrayPathRel,
|
|
2222
|
+
commentrayOutputUrls: opts.commentrayOutputUrls,
|
|
2223
|
+
sourceMarkdownOutputUrls: sourceMarkdownUrls,
|
|
2224
|
+
stretchBufferSync: stretchBufferSyncFromOpts(opts),
|
|
2225
|
+
});
|
|
2226
|
+
if (stretched === null)
|
|
2227
|
+
return null;
|
|
2228
|
+
const { jsonRow, commentrayHtml, scrollB64 } = await multiAngleJsonRowAndDocHtml(opts, spec);
|
|
2229
|
+
const stretchPairHtml = renderShellPairContextHtml(shellPairSourcePath(opts.filePath, rows.sourceRelative), jsonRow.commentrayPathForSearch);
|
|
2230
|
+
const stretchSwapInner = wrapShellInnerWithPairContext(stretchPairHtml, ` ${stretched.preambleHtml}\n ${stretched.tableInnerHtml}\n`);
|
|
2231
|
+
perAngle.push({
|
|
2232
|
+
spec,
|
|
2233
|
+
stretched,
|
|
2234
|
+
jsonRow: {
|
|
2235
|
+
...jsonRow,
|
|
2236
|
+
stretchSwapInnerB64: Buffer.from(stretchSwapInner, "utf8").toString("base64"),
|
|
2237
|
+
},
|
|
2238
|
+
commentrayHtml,
|
|
2239
|
+
scrollB64,
|
|
2240
|
+
});
|
|
2241
|
+
}
|
|
2242
|
+
const builtAngles = perAngle.map((p) => ({
|
|
2243
|
+
spec: p.spec,
|
|
2244
|
+
commentrayHtml: p.commentrayHtml,
|
|
2245
|
+
scrollB64: p.scrollB64,
|
|
2246
|
+
}));
|
|
2247
|
+
const { defaultMarkdown, defaultScrollB64, defaultPathSearch, defaultGh, defaultStaticBrowse } = resolveMultiAngleDefaultSelection({ multi, defaultId, opts, builtAngles });
|
|
2248
|
+
const defaultStretch = perAngle.find((p) => p.spec.id === defaultId) ?? perAngle[0];
|
|
2249
|
+
if (defaultStretch === undefined)
|
|
2250
|
+
return null;
|
|
2251
|
+
const shellInner = wrapShellInnerWithPairContext(renderShellPairContextHtml(shellPairSourcePath(opts.filePath, defaultStretch.spec.blockStretchRows?.sourceRelative), defaultPathSearch), ` ${defaultStretch.stretched.preambleHtml}\n` +
|
|
2252
|
+
` ${defaultStretch.stretched.tableInnerHtml}\n`);
|
|
2253
|
+
const payloadObj = {
|
|
2254
|
+
layoutMode: "stretch",
|
|
2255
|
+
defaultAngleId: defaultId,
|
|
2256
|
+
angles: perAngle.map((p) => p.jsonRow),
|
|
2257
|
+
};
|
|
2258
|
+
const multiAnglePayloadB64 = Buffer.from(JSON.stringify(payloadObj), "utf8").toString("base64");
|
|
2259
|
+
return {
|
|
2260
|
+
layout: "stretch",
|
|
2261
|
+
shellInner,
|
|
2262
|
+
scrollBlockLinksB64: defaultScrollB64,
|
|
2263
|
+
angleSelectHtml: multiAngleToolbarAngleSelectHtml(multi, defaultId),
|
|
2264
|
+
multiAnglePayloadB64,
|
|
2265
|
+
sourceMarkdownToggleEnabled: sourceMarkdownEnabled,
|
|
2266
|
+
sourcePaneDefaultMode: "source",
|
|
2267
|
+
stretchBufferSync: stretchBufferSyncFromOpts(opts),
|
|
2268
|
+
multiShell: {
|
|
2269
|
+
rawMdB64: Buffer.from(defaultMarkdown, "utf8").toString("base64"),
|
|
2270
|
+
scrollBlockLinksB64: defaultScrollB64,
|
|
2271
|
+
commentrayPathForSearch: defaultPathSearch,
|
|
2272
|
+
commentrayOnGithubUrl: defaultGh,
|
|
2273
|
+
...(defaultStaticBrowse.length > 0 ? { commentrayStaticBrowseUrl: defaultStaticBrowse } : {}),
|
|
2274
|
+
},
|
|
2275
|
+
};
|
|
2276
|
+
}
|
|
2030
2277
|
async function buildMultiAngleDualPaneShell(opts, multi) {
|
|
2031
2278
|
const defaultId = multi.angles.some((a) => a.id === multi.defaultAngleId)
|
|
2032
2279
|
? multi.defaultAngleId
|
|
@@ -2050,14 +2297,8 @@ async function buildMultiAngleDualPaneShell(opts, multi) {
|
|
|
2050
2297
|
jsonAngles.push(jsonRow);
|
|
2051
2298
|
}
|
|
2052
2299
|
const { defaultMarkdown, defaultScrollB64, defaultPathSearch, defaultGh, defaultStaticBrowse, defaultPaneHtml, } = resolveMultiAngleDefaultSelection({ multi, defaultId, opts, builtAngles });
|
|
2053
|
-
const
|
|
2054
|
-
|
|
2055
|
-
const lab = escapeHtml(a.title?.trim() || a.id);
|
|
2056
|
-
return `<option value="${escapeHtml(a.id)}"${a.id === defaultId ? " selected" : ""}>${lab}</option>`;
|
|
2057
|
-
})
|
|
2058
|
-
.join("");
|
|
2059
|
-
const angleSelectHtml = `<span class="toolbar-angle-picker"><label class="toolbar-angle-picker__lab nav-rail__search-label" for="angle-select">Angle</label><select id="angle-select" aria-label="Commentray angle">${selOpts}</select></span>`;
|
|
2060
|
-
const pairHtml = renderShellPairContextHtml(opts.filePath, defaultPathSearch);
|
|
2300
|
+
const angleSelectHtml = multiAngleToolbarAngleSelectHtml(multi, defaultId);
|
|
2301
|
+
const pairHtml = renderShellPairContextHtml(shellPairSourcePath(opts.filePath, opts.blockStretchRows?.sourceRelative), defaultPathSearch);
|
|
2061
2302
|
const shellInner = wrapDualShellInner(pairHtml, dualPanePanesInnerHtml(codeHtml, defaultPaneHtml, sourceMarkdownPaneHtml));
|
|
2062
2303
|
const payloadObj = { defaultAngleId: defaultId, angles: jsonAngles };
|
|
2063
2304
|
const multiAnglePayloadB64 = Buffer.from(JSON.stringify(payloadObj), "utf8").toString("base64");
|
|
@@ -2076,26 +2317,47 @@ async function buildMultiAngleDualPaneShell(opts, multi) {
|
|
|
2076
2317
|
sourcePaneDefaultMode: sourceMarkdownEnabled ? "rendered-markdown" : "source",
|
|
2077
2318
|
};
|
|
2078
2319
|
}
|
|
2079
|
-
async function
|
|
2080
|
-
|
|
2081
|
-
|
|
2320
|
+
async function buildDualPaneSingleAngleShell(opts) {
|
|
2321
|
+
const rows = opts.blockStretchRows;
|
|
2322
|
+
const links = rows !== undefined
|
|
2323
|
+
? buildBlockScrollLinks(rows.index, rows.sourceRelative, rows.commentrayPathRel, opts.commentrayMarkdown, opts.code)
|
|
2324
|
+
: [];
|
|
2325
|
+
const mdForDoc = injectCommentrayDocAnchors(opts.commentrayMarkdown, links.length > 0 ? links : undefined);
|
|
2082
2326
|
let scrollBlockLinksB64 = "";
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
if (multiActive && multi) {
|
|
2086
|
-
const built = await buildMultiAngleDualPaneShell(opts, multi);
|
|
2087
|
-
const ms = built.multiShell;
|
|
2088
|
-
return {
|
|
2089
|
-
layout: "dual",
|
|
2090
|
-
shellInner: built.shellInner,
|
|
2091
|
-
scrollBlockLinksB64: ms.scrollBlockLinksB64,
|
|
2092
|
-
angleSelectHtml: built.angleSelectHtml,
|
|
2093
|
-
multiAnglePayloadB64: built.multiAnglePayloadB64,
|
|
2094
|
-
sourceMarkdownToggleEnabled: built.sourceMarkdownToggleEnabled,
|
|
2095
|
-
sourcePaneDefaultMode: built.sourcePaneDefaultMode,
|
|
2096
|
-
multiShell: ms,
|
|
2097
|
-
};
|
|
2327
|
+
if (links.length > 0) {
|
|
2328
|
+
scrollBlockLinksB64 = Buffer.from(JSON.stringify(links), "utf8").toString("base64");
|
|
2098
2329
|
}
|
|
2330
|
+
const sourceMarkdownEnabled = isMarkdownLikeSource(opts);
|
|
2331
|
+
const sourceMdForPane = sourceMarkdownEnabled ? injectSourceMarkdownAnchors(opts.code) : "";
|
|
2332
|
+
const sourcePaneUrls = sourcePaneOutputUrls(opts);
|
|
2333
|
+
const [codeHtml, commentrayHtml, sourceMarkdownPaneHtml] = await Promise.all([
|
|
2334
|
+
renderHighlightedCodeLineRows(opts.code, opts.language),
|
|
2335
|
+
renderMarkdownToHtml(mdForDoc, {
|
|
2336
|
+
commentrayOutputUrls: opts.commentrayOutputUrls,
|
|
2337
|
+
}),
|
|
2338
|
+
sourceMarkdownEnabled
|
|
2339
|
+
? renderMarkdownToHtml(sourceMdForPane, {
|
|
2340
|
+
commentrayOutputUrls: sourcePaneUrls,
|
|
2341
|
+
})
|
|
2342
|
+
: Promise.resolve(""),
|
|
2343
|
+
]);
|
|
2344
|
+
const pairHtml = renderShellPairContextHtml(shellPairSourcePath(opts.filePath, opts.blockStretchRows?.sourceRelative), shellPairCommentrayPath(opts.commentrayPathForSearch, opts.blockStretchRows?.commentrayPathRel));
|
|
2345
|
+
const shellInner = wrapDualShellInner(pairHtml, dualPanePanesInnerHtml(codeHtml, commentrayHtml, sourceMarkdownPaneHtml));
|
|
2346
|
+
return {
|
|
2347
|
+
layout: "dual",
|
|
2348
|
+
shellInner,
|
|
2349
|
+
scrollBlockLinksB64,
|
|
2350
|
+
angleSelectHtml: "",
|
|
2351
|
+
multiAnglePayloadB64: "",
|
|
2352
|
+
sourceMarkdownToggleEnabled: sourceMarkdownEnabled,
|
|
2353
|
+
sourcePaneDefaultMode: sourceMarkdownEnabled ? "rendered-markdown" : "source",
|
|
2354
|
+
};
|
|
2355
|
+
}
|
|
2356
|
+
async function buildSingleAngleCodeBrowserShell(opts, layoutPref) {
|
|
2357
|
+
let layout = "dual";
|
|
2358
|
+
let shellInner = "";
|
|
2359
|
+
const sourceMarkdownEnabled = isMarkdownLikeSource(opts);
|
|
2360
|
+
const sourceMarkdownUrls = sourceMarkdownEnabled ? sourcePaneOutputUrls(opts) : undefined;
|
|
2099
2361
|
if (opts.blockStretchRows && layoutPref !== "dual") {
|
|
2100
2362
|
const stretched = await tryBuildBlockStretchTableHtml({
|
|
2101
2363
|
code: opts.code,
|
|
@@ -2105,45 +2367,24 @@ async function buildCodeBrowserShell(opts, layoutPref) {
|
|
|
2105
2367
|
sourceRelative: opts.blockStretchRows.sourceRelative,
|
|
2106
2368
|
commentrayPathRel: opts.blockStretchRows.commentrayPathRel,
|
|
2107
2369
|
commentrayOutputUrls: opts.commentrayOutputUrls,
|
|
2370
|
+
sourceMarkdownOutputUrls: sourceMarkdownUrls,
|
|
2371
|
+
stretchBufferSync: stretchBufferSyncFromOpts(opts),
|
|
2108
2372
|
});
|
|
2109
2373
|
if (stretched) {
|
|
2110
2374
|
layout = "stretch";
|
|
2111
|
-
shellInner = ` ${stretched.preambleHtml}\n` + ` ${stretched.tableInnerHtml}\n
|
|
2375
|
+
shellInner = wrapShellInnerWithPairContext(renderShellPairContextHtml(shellPairSourcePath(opts.filePath, opts.blockStretchRows?.sourceRelative), shellPairCommentrayPath(opts.commentrayPathForSearch, opts.blockStretchRows?.commentrayPathRel)), ` ${stretched.preambleHtml}\n` + ` ${stretched.tableInnerHtml}\n`);
|
|
2112
2376
|
}
|
|
2113
2377
|
}
|
|
2114
2378
|
if (layout === "dual") {
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
const sourcePaneUrls = sourcePaneOutputUrls(opts);
|
|
2125
|
-
const [codeHtml, commentrayHtml, sourceMarkdownPaneHtml] = await Promise.all([
|
|
2126
|
-
renderHighlightedCodeLineRows(opts.code, opts.language),
|
|
2127
|
-
renderMarkdownToHtml(mdForDoc, {
|
|
2128
|
-
commentrayOutputUrls: opts.commentrayOutputUrls,
|
|
2129
|
-
}),
|
|
2130
|
-
sourceMarkdownEnabled
|
|
2131
|
-
? renderMarkdownToHtml(sourceMdForPane, {
|
|
2132
|
-
commentrayOutputUrls: sourcePaneUrls,
|
|
2133
|
-
})
|
|
2134
|
-
: Promise.resolve(""),
|
|
2135
|
-
]);
|
|
2136
|
-
const pairHtml = renderShellPairContextHtml(opts.filePath, (opts.commentrayPathForSearch ?? "").trim());
|
|
2137
|
-
shellInner = wrapDualShellInner(pairHtml, dualPanePanesInnerHtml(codeHtml, commentrayHtml, sourceMarkdownPaneHtml));
|
|
2138
|
-
return {
|
|
2139
|
-
layout,
|
|
2140
|
-
shellInner,
|
|
2141
|
-
scrollBlockLinksB64,
|
|
2142
|
-
angleSelectHtml: "",
|
|
2143
|
-
multiAnglePayloadB64: "",
|
|
2144
|
-
sourceMarkdownToggleEnabled: sourceMarkdownEnabled,
|
|
2145
|
-
sourcePaneDefaultMode: sourceMarkdownEnabled ? "rendered-markdown" : "source",
|
|
2146
|
-
};
|
|
2379
|
+
return buildDualPaneSingleAngleShell(opts);
|
|
2380
|
+
}
|
|
2381
|
+
const rows = opts.blockStretchRows;
|
|
2382
|
+
const links = rows !== undefined
|
|
2383
|
+
? buildBlockScrollLinks(rows.index, rows.sourceRelative, rows.commentrayPathRel, opts.commentrayMarkdown, opts.code)
|
|
2384
|
+
: [];
|
|
2385
|
+
let scrollBlockLinksB64 = "";
|
|
2386
|
+
if (links.length > 0) {
|
|
2387
|
+
scrollBlockLinksB64 = Buffer.from(JSON.stringify(links), "utf8").toString("base64");
|
|
2147
2388
|
}
|
|
2148
2389
|
return {
|
|
2149
2390
|
layout,
|
|
@@ -2151,10 +2392,35 @@ async function buildCodeBrowserShell(opts, layoutPref) {
|
|
|
2151
2392
|
scrollBlockLinksB64,
|
|
2152
2393
|
angleSelectHtml: "",
|
|
2153
2394
|
multiAnglePayloadB64: "",
|
|
2154
|
-
sourceMarkdownToggleEnabled:
|
|
2395
|
+
sourceMarkdownToggleEnabled: sourceMarkdownEnabled,
|
|
2155
2396
|
sourcePaneDefaultMode: "source",
|
|
2397
|
+
stretchBufferSync: stretchBufferSyncFromOpts(opts),
|
|
2156
2398
|
};
|
|
2157
2399
|
}
|
|
2400
|
+
async function buildCodeBrowserShell(opts, layoutPref) {
|
|
2401
|
+
const multi = opts.multiAngleBrowsing;
|
|
2402
|
+
const multiActive = Boolean(multi && multi.angles.length >= 2);
|
|
2403
|
+
if (multiActive && multi) {
|
|
2404
|
+
if (layoutPref !== "dual") {
|
|
2405
|
+
const stretchMulti = await buildMultiAngleBlockStretchShell(opts, multi);
|
|
2406
|
+
if (stretchMulti !== null)
|
|
2407
|
+
return stretchMulti;
|
|
2408
|
+
}
|
|
2409
|
+
const built = await buildMultiAngleDualPaneShell(opts, multi);
|
|
2410
|
+
const ms = built.multiShell;
|
|
2411
|
+
return {
|
|
2412
|
+
layout: "dual",
|
|
2413
|
+
shellInner: built.shellInner,
|
|
2414
|
+
scrollBlockLinksB64: ms.scrollBlockLinksB64,
|
|
2415
|
+
angleSelectHtml: built.angleSelectHtml,
|
|
2416
|
+
multiAnglePayloadB64: built.multiAnglePayloadB64,
|
|
2417
|
+
sourceMarkdownToggleEnabled: built.sourceMarkdownToggleEnabled,
|
|
2418
|
+
sourcePaneDefaultMode: built.sourcePaneDefaultMode,
|
|
2419
|
+
multiShell: ms,
|
|
2420
|
+
};
|
|
2421
|
+
}
|
|
2422
|
+
return buildSingleAngleCodeBrowserShell(opts, layoutPref);
|
|
2423
|
+
}
|
|
2158
2424
|
function searchChromeFromOptions(opts, commentrayPathOverride) {
|
|
2159
2425
|
const crPath = (commentrayPathOverride ?? opts.commentrayPathForSearch ?? "").trim();
|
|
2160
2426
|
if (opts.staticSearchScope === "commentray-and-paths") {
|
|
@@ -2202,8 +2468,6 @@ function shellPairIdentityDataAttrs(shell, opts) {
|
|
|
2202
2468
|
}
|
|
2203
2469
|
/** Canonical doc target for static validation: same-site `./browse/…` when present, else GitHub blob. */
|
|
2204
2470
|
function shellPairDocDataAttr(shell, opts) {
|
|
2205
|
-
if (shell.layout !== "dual")
|
|
2206
|
-
return "";
|
|
2207
2471
|
const browseRaw = (shell.multiShell?.commentrayStaticBrowseUrl ??
|
|
2208
2472
|
opts.commentrayStaticBrowseUrl ??
|
|
2209
2473
|
"").trim();
|
|
@@ -2263,6 +2527,13 @@ export async function renderCodeBrowserHtml(opts) {
|
|
|
2263
2527
|
const pairIdentityDataAttrs = shellPairIdentityDataAttrs(shell, opts);
|
|
2264
2528
|
const sourceMarkdownToggles = sourceMarkdownToggleControlsHtml(shell.sourceMarkdownToggleEnabled);
|
|
2265
2529
|
const sourcePaneModeAttr = ` data-source-pane-mode="${shell.sourcePaneDefaultMode}"`;
|
|
2530
|
+
const scrollSyncStrategyShellAttr = opts.dualPaneScrollSyncStrategy !== undefined &&
|
|
2531
|
+
opts.dualPaneScrollSyncStrategy !== DEFAULT_DUAL_PANE_SCROLL_SYNC_STRATEGY
|
|
2532
|
+
? ` data-scroll-sync-strategy="${escapeHtml(opts.dualPaneScrollSyncStrategy)}"`
|
|
2533
|
+
: "";
|
|
2534
|
+
const stretchBufferSyncShellAttr = shell.layout === "stretch" && shell.stretchBufferSync === "flow-synchronizer"
|
|
2535
|
+
? ` data-stretch-buffer-sync="flow-synchronizer"`
|
|
2536
|
+
: "";
|
|
2266
2537
|
return buildCodeBrowserPageHtml({
|
|
2267
2538
|
title,
|
|
2268
2539
|
metaDescriptionHtml,
|
|
@@ -2291,6 +2562,8 @@ export async function renderCodeBrowserHtml(opts) {
|
|
|
2291
2562
|
sourceMarkdownToggleHtml: sourceMarkdownToggles.sourceMarkdownToggleHtml,
|
|
2292
2563
|
sourceMarkdownFlipScrollAffordanceHtml: sourceMarkdownToggles.sourceMarkdownFlipScrollAffordanceHtml,
|
|
2293
2564
|
sourcePaneModeAttr,
|
|
2565
|
+
scrollSyncStrategyShellAttr,
|
|
2566
|
+
stretchBufferSyncShellAttr,
|
|
2294
2567
|
});
|
|
2295
2568
|
}
|
|
2296
2569
|
//# sourceMappingURL=code-browser.js.map
|