@commentray/render 0.2.0 → 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.js +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 +1366 -257
- 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 +350 -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
|
}
|
|
@@ -1132,7 +1150,66 @@ ${CODE_BROWSER_INTRO_STYLES}
|
|
|
1132
1150
|
text-overflow: ellipsis;
|
|
1133
1151
|
white-space: nowrap;
|
|
1134
1152
|
}
|
|
1135
|
-
.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
|
+
}
|
|
1136
1213
|
.pane--code {
|
|
1137
1214
|
flex: 0 0 var(--split-pct, 46%);
|
|
1138
1215
|
min-width: 120px; overflow: auto; padding: 12px var(--cr-pane-inline-pad);
|
|
@@ -1270,6 +1347,8 @@ ${CODE_BROWSER_INTRO_STYLES}
|
|
|
1270
1347
|
.doc-pane-body {
|
|
1271
1348
|
flex: 1 1 auto; min-height: 0; overflow: auto;
|
|
1272
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. */
|
|
1273
1352
|
/* Inline backtick code chips (GitHub-like): prose context only, never fenced pre/code blocks. */
|
|
1274
1353
|
.pane--doc .doc-pane-body :where(p, li, blockquote, td, th, h1, h2, h3, h4, h5, h6) > code,
|
|
1275
1354
|
.shell--stretch-rows .stretch-preamble :where(p, li, blockquote, td, th, h1, h2, h3, h4, h5, h6) > code,
|
|
@@ -1760,6 +1839,22 @@ ${CODE_BROWSER_INTRO_STYLES}
|
|
|
1760
1839
|
flex: 1 1 auto;
|
|
1761
1840
|
padding-left: var(--cr-pane-inline-pad);
|
|
1762
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
|
+
}
|
|
1763
1858
|
}
|
|
1764
1859
|
.pane--doc { font-size: 15px; line-height: 1.45; }
|
|
1765
1860
|
.pane--doc img { max-width: 100%; height: auto; }
|
|
@@ -1771,9 +1866,8 @@ ${CODE_BROWSER_INTRO_STYLES}
|
|
|
1771
1866
|
.pane--doc .commentray-block-anchor {
|
|
1772
1867
|
display: block;
|
|
1773
1868
|
height: 0;
|
|
1774
|
-
margin:
|
|
1869
|
+
margin: 0;
|
|
1775
1870
|
border: 0;
|
|
1776
|
-
border-top: 1px solid color-mix(in oklab, CanvasText 22%, Canvas);
|
|
1777
1871
|
pointer-events: none;
|
|
1778
1872
|
}
|
|
1779
1873
|
.shell--stretch-rows {
|
|
@@ -1781,15 +1875,17 @@ ${CODE_BROWSER_INTRO_STYLES}
|
|
|
1781
1875
|
min-height: 0;
|
|
1782
1876
|
overflow: auto;
|
|
1783
1877
|
display: block;
|
|
1784
|
-
padding: 0
|
|
1878
|
+
padding: 0 0 20px;
|
|
1785
1879
|
}
|
|
1786
1880
|
.shell--stretch-rows .stretch-preamble {
|
|
1787
1881
|
padding: 8px 4px 16px;
|
|
1788
1882
|
margin-bottom: 8px;
|
|
1789
|
-
border-bottom: 1px solid color-mix(in oklab, CanvasText 12%, Canvas);
|
|
1790
1883
|
font-size: 15px;
|
|
1791
1884
|
line-height: 1.45;
|
|
1792
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;
|
|
1793
1889
|
max-width: 100%;
|
|
1794
1890
|
}
|
|
1795
1891
|
.shell--stretch-rows .stretch-preamble img { max-width: 100%; height: auto; }
|
|
@@ -1798,27 +1894,49 @@ ${CODE_BROWSER_INTRO_STYLES}
|
|
|
1798
1894
|
border-collapse: collapse;
|
|
1799
1895
|
table-layout: fixed;
|
|
1800
1896
|
}
|
|
1801
|
-
.stretch-
|
|
1802
|
-
|
|
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%)); }
|
|
1803
1902
|
.block-stretch td.stretch-code {
|
|
1804
1903
|
vertical-align: top;
|
|
1805
1904
|
padding: 0 12px 0 0;
|
|
1806
|
-
|
|
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;
|
|
1807
1922
|
}
|
|
1808
1923
|
.block-stretch td.stretch-doc {
|
|
1809
1924
|
vertical-align: top;
|
|
1810
1925
|
padding: 0 0 0 12px;
|
|
1811
|
-
|
|
1926
|
+
box-shadow: inset 1px 0 0 color-mix(in oklab, CanvasText 8%, Canvas);
|
|
1812
1927
|
}
|
|
1813
1928
|
.block-stretch td.stretch-doc .stretch-doc-inner {
|
|
1814
1929
|
font-size: 15px;
|
|
1815
1930
|
line-height: 1.45;
|
|
1816
1931
|
min-width: 0;
|
|
1817
1932
|
overflow-x: auto;
|
|
1933
|
+
/* Keep vertical scrolling on the shell; see stretch-preamble rule above. */
|
|
1934
|
+
overflow-y: hidden;
|
|
1818
1935
|
}
|
|
1819
1936
|
.block-stretch td.stretch-doc .stretch-doc-inner img { max-width: 100%; height: auto; }
|
|
1820
1937
|
.block-stretch td.stretch-doc .stretch-doc-inner .commentray-mermaid {
|
|
1821
1938
|
overflow-x: auto;
|
|
1939
|
+
overflow-y: hidden;
|
|
1822
1940
|
max-width: 100%;
|
|
1823
1941
|
}
|
|
1824
1942
|
.block-stretch.wrap td.stretch-doc .stretch-doc-inner {
|
|
@@ -1837,7 +1955,6 @@ ${CODE_BROWSER_INTRO_STYLES}
|
|
|
1837
1955
|
font-size: 13px;
|
|
1838
1956
|
vertical-align: top;
|
|
1839
1957
|
}
|
|
1840
|
-
.block-stretch .stretch-gap-mark { display: inline-block; padding-top: 2px; }
|
|
1841
1958
|
.block-stretch .stretch-code-stack {
|
|
1842
1959
|
display: flex;
|
|
1843
1960
|
flex-direction: column;
|
|
@@ -1887,15 +2004,39 @@ ${CODE_BROWSER_INTRO_STYLES}
|
|
|
1887
2004
|
.block-stretch:not(.wrap) .stretch-doc-inner pre code {
|
|
1888
2005
|
white-space: pre;
|
|
1889
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
|
+
}
|
|
1890
2031
|
`;
|
|
1891
2032
|
/** Native tooltip on #search-q (short hint is visible under the search row). */
|
|
1892
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).";
|
|
1893
2034
|
function buildCodeBrowserPageHtml(p) {
|
|
1894
2035
|
const shellClass = p.layout === "stretch" ? "shell shell--stretch-rows" : "shell";
|
|
1895
|
-
const dualFlipControlHtml = p.layout === "dual"
|
|
2036
|
+
const dualFlipControlHtml = p.layout === "dual" || p.layout === "stretch"
|
|
1896
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>`
|
|
1897
2038
|
: "";
|
|
1898
|
-
const dualFlipScrollAffordanceHtml = p.layout === "dual"
|
|
2039
|
+
const dualFlipScrollAffordanceHtml = p.layout === "dual" || p.layout === "stretch"
|
|
1899
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>`
|
|
1900
2041
|
: "";
|
|
1901
2042
|
return `<!doctype html>
|
|
@@ -1924,13 +2065,13 @@ ${CODE_BROWSER_STYLES}
|
|
|
1924
2065
|
${p.toolbarSiteHubHtml}
|
|
1925
2066
|
${p.navRailDocumentedHtml}
|
|
1926
2067
|
${p.angleSelectHtml}
|
|
2068
|
+
${dualFlipControlHtml}
|
|
1927
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).">
|
|
1928
2070
|
<input type="checkbox" id="wrap-lines" class="toolbar-wrap-lines__input" />
|
|
1929
2071
|
<span class="toolbar-wrap-lines__box" aria-hidden="true"></span>
|
|
1930
2072
|
<span class="toolbar-wrap-lines__face" aria-hidden="true">${TOOLBAR_ICON_WRAP_SVG}</span>
|
|
1931
2073
|
<span class="toolbar-wrap-lines__caption">Wrap lines</span>
|
|
1932
2074
|
</label>
|
|
1933
|
-
${dualFlipControlHtml}
|
|
1934
2075
|
${p.sourceMarkdownToggleHtml}
|
|
1935
2076
|
${p.toolbarDocHubHtml}
|
|
1936
2077
|
${p.relatedNavHtml}
|
|
@@ -1954,7 +2095,7 @@ ${TOOLBAR_COLOR_THEME_HTML}
|
|
|
1954
2095
|
<div class="search-results" id="search-results" hidden aria-live="polite"></div>
|
|
1955
2096
|
</header>
|
|
1956
2097
|
<main id="main-content" class="app__main" tabindex="-1">
|
|
1957
|
-
<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 ?? ""}>
|
|
1958
2099
|
${p.shellInner}
|
|
1959
2100
|
</div>
|
|
1960
2101
|
</main>
|
|
@@ -1971,6 +2112,27 @@ ${loadCodeBrowserClientBundle()}
|
|
|
1971
2112
|
function firstNonEmpty(values) {
|
|
1972
2113
|
return values.find((v) => v.trim().length > 0);
|
|
1973
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
|
+
}
|
|
1974
2136
|
function resolveMultiAngleDefaultSelection(args) {
|
|
1975
2137
|
const { multi, defaultId, opts, builtAngles } = args;
|
|
1976
2138
|
let defaultMarkdown = opts.commentrayMarkdown;
|
|
@@ -2008,11 +2170,8 @@ function resolveMultiAngleDefaultSelection(args) {
|
|
|
2008
2170
|
}
|
|
2009
2171
|
async function multiAngleJsonRowAndDocHtml(opts, spec) {
|
|
2010
2172
|
const rows = spec.blockStretchRows;
|
|
2173
|
+
const rowsPathOk = angleBlockStretchRowsPathOk(spec, opts);
|
|
2011
2174
|
const angleCrNorm = normalizeRepoRelativePath(spec.commentrayPathRel.replaceAll("\\", "/"));
|
|
2012
|
-
const primaryNorm = normalizeRepoRelativePath((opts.filePath ?? "").replaceAll("\\", "/"));
|
|
2013
|
-
const rowsPathOk = rows !== undefined &&
|
|
2014
|
-
normalizeRepoRelativePath(rows.commentrayPathRel.replaceAll("\\", "/")) === angleCrNorm &&
|
|
2015
|
-
normalizeRepoRelativePath(rows.sourceRelative.replaceAll("\\", "/")) === primaryNorm;
|
|
2016
2175
|
const links = rows !== undefined && rowsPathOk
|
|
2017
2176
|
? buildBlockScrollLinks(rows.index, rows.sourceRelative, angleCrNorm, spec.markdown, opts.code)
|
|
2018
2177
|
: [];
|
|
@@ -2036,6 +2195,85 @@ async function multiAngleJsonRowAndDocHtml(opts, spec) {
|
|
|
2036
2195
|
scrollB64,
|
|
2037
2196
|
};
|
|
2038
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
|
+
}
|
|
2039
2277
|
async function buildMultiAngleDualPaneShell(opts, multi) {
|
|
2040
2278
|
const defaultId = multi.angles.some((a) => a.id === multi.defaultAngleId)
|
|
2041
2279
|
? multi.defaultAngleId
|
|
@@ -2059,14 +2297,8 @@ async function buildMultiAngleDualPaneShell(opts, multi) {
|
|
|
2059
2297
|
jsonAngles.push(jsonRow);
|
|
2060
2298
|
}
|
|
2061
2299
|
const { defaultMarkdown, defaultScrollB64, defaultPathSearch, defaultGh, defaultStaticBrowse, defaultPaneHtml, } = resolveMultiAngleDefaultSelection({ multi, defaultId, opts, builtAngles });
|
|
2062
|
-
const
|
|
2063
|
-
|
|
2064
|
-
const lab = escapeHtml(a.title?.trim() || a.id);
|
|
2065
|
-
return `<option value="${escapeHtml(a.id)}"${a.id === defaultId ? " selected" : ""}>${lab}</option>`;
|
|
2066
|
-
})
|
|
2067
|
-
.join("");
|
|
2068
|
-
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>`;
|
|
2069
|
-
const pairHtml = renderShellPairContextHtml(opts.filePath, defaultPathSearch);
|
|
2300
|
+
const angleSelectHtml = multiAngleToolbarAngleSelectHtml(multi, defaultId);
|
|
2301
|
+
const pairHtml = renderShellPairContextHtml(shellPairSourcePath(opts.filePath, opts.blockStretchRows?.sourceRelative), defaultPathSearch);
|
|
2070
2302
|
const shellInner = wrapDualShellInner(pairHtml, dualPanePanesInnerHtml(codeHtml, defaultPaneHtml, sourceMarkdownPaneHtml));
|
|
2071
2303
|
const payloadObj = { defaultAngleId: defaultId, angles: jsonAngles };
|
|
2072
2304
|
const multiAnglePayloadB64 = Buffer.from(JSON.stringify(payloadObj), "utf8").toString("base64");
|
|
@@ -2085,26 +2317,47 @@ async function buildMultiAngleDualPaneShell(opts, multi) {
|
|
|
2085
2317
|
sourcePaneDefaultMode: sourceMarkdownEnabled ? "rendered-markdown" : "source",
|
|
2086
2318
|
};
|
|
2087
2319
|
}
|
|
2088
|
-
async function
|
|
2089
|
-
|
|
2090
|
-
|
|
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);
|
|
2091
2326
|
let scrollBlockLinksB64 = "";
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
if (multiActive && multi) {
|
|
2095
|
-
const built = await buildMultiAngleDualPaneShell(opts, multi);
|
|
2096
|
-
const ms = built.multiShell;
|
|
2097
|
-
return {
|
|
2098
|
-
layout: "dual",
|
|
2099
|
-
shellInner: built.shellInner,
|
|
2100
|
-
scrollBlockLinksB64: ms.scrollBlockLinksB64,
|
|
2101
|
-
angleSelectHtml: built.angleSelectHtml,
|
|
2102
|
-
multiAnglePayloadB64: built.multiAnglePayloadB64,
|
|
2103
|
-
sourceMarkdownToggleEnabled: built.sourceMarkdownToggleEnabled,
|
|
2104
|
-
sourcePaneDefaultMode: built.sourcePaneDefaultMode,
|
|
2105
|
-
multiShell: ms,
|
|
2106
|
-
};
|
|
2327
|
+
if (links.length > 0) {
|
|
2328
|
+
scrollBlockLinksB64 = Buffer.from(JSON.stringify(links), "utf8").toString("base64");
|
|
2107
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;
|
|
2108
2361
|
if (opts.blockStretchRows && layoutPref !== "dual") {
|
|
2109
2362
|
const stretched = await tryBuildBlockStretchTableHtml({
|
|
2110
2363
|
code: opts.code,
|
|
@@ -2114,45 +2367,24 @@ async function buildCodeBrowserShell(opts, layoutPref) {
|
|
|
2114
2367
|
sourceRelative: opts.blockStretchRows.sourceRelative,
|
|
2115
2368
|
commentrayPathRel: opts.blockStretchRows.commentrayPathRel,
|
|
2116
2369
|
commentrayOutputUrls: opts.commentrayOutputUrls,
|
|
2370
|
+
sourceMarkdownOutputUrls: sourceMarkdownUrls,
|
|
2371
|
+
stretchBufferSync: stretchBufferSyncFromOpts(opts),
|
|
2117
2372
|
});
|
|
2118
2373
|
if (stretched) {
|
|
2119
2374
|
layout = "stretch";
|
|
2120
|
-
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`);
|
|
2121
2376
|
}
|
|
2122
2377
|
}
|
|
2123
2378
|
if (layout === "dual") {
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
const sourcePaneUrls = sourcePaneOutputUrls(opts);
|
|
2134
|
-
const [codeHtml, commentrayHtml, sourceMarkdownPaneHtml] = await Promise.all([
|
|
2135
|
-
renderHighlightedCodeLineRows(opts.code, opts.language),
|
|
2136
|
-
renderMarkdownToHtml(mdForDoc, {
|
|
2137
|
-
commentrayOutputUrls: opts.commentrayOutputUrls,
|
|
2138
|
-
}),
|
|
2139
|
-
sourceMarkdownEnabled
|
|
2140
|
-
? renderMarkdownToHtml(sourceMdForPane, {
|
|
2141
|
-
commentrayOutputUrls: sourcePaneUrls,
|
|
2142
|
-
})
|
|
2143
|
-
: Promise.resolve(""),
|
|
2144
|
-
]);
|
|
2145
|
-
const pairHtml = renderShellPairContextHtml(opts.filePath, (opts.commentrayPathForSearch ?? "").trim());
|
|
2146
|
-
shellInner = wrapDualShellInner(pairHtml, dualPanePanesInnerHtml(codeHtml, commentrayHtml, sourceMarkdownPaneHtml));
|
|
2147
|
-
return {
|
|
2148
|
-
layout,
|
|
2149
|
-
shellInner,
|
|
2150
|
-
scrollBlockLinksB64,
|
|
2151
|
-
angleSelectHtml: "",
|
|
2152
|
-
multiAnglePayloadB64: "",
|
|
2153
|
-
sourceMarkdownToggleEnabled: sourceMarkdownEnabled,
|
|
2154
|
-
sourcePaneDefaultMode: sourceMarkdownEnabled ? "rendered-markdown" : "source",
|
|
2155
|
-
};
|
|
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");
|
|
2156
2388
|
}
|
|
2157
2389
|
return {
|
|
2158
2390
|
layout,
|
|
@@ -2160,10 +2392,35 @@ async function buildCodeBrowserShell(opts, layoutPref) {
|
|
|
2160
2392
|
scrollBlockLinksB64,
|
|
2161
2393
|
angleSelectHtml: "",
|
|
2162
2394
|
multiAnglePayloadB64: "",
|
|
2163
|
-
sourceMarkdownToggleEnabled:
|
|
2395
|
+
sourceMarkdownToggleEnabled: sourceMarkdownEnabled,
|
|
2164
2396
|
sourcePaneDefaultMode: "source",
|
|
2397
|
+
stretchBufferSync: stretchBufferSyncFromOpts(opts),
|
|
2165
2398
|
};
|
|
2166
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
|
+
}
|
|
2167
2424
|
function searchChromeFromOptions(opts, commentrayPathOverride) {
|
|
2168
2425
|
const crPath = (commentrayPathOverride ?? opts.commentrayPathForSearch ?? "").trim();
|
|
2169
2426
|
if (opts.staticSearchScope === "commentray-and-paths") {
|
|
@@ -2211,8 +2468,6 @@ function shellPairIdentityDataAttrs(shell, opts) {
|
|
|
2211
2468
|
}
|
|
2212
2469
|
/** Canonical doc target for static validation: same-site `./browse/…` when present, else GitHub blob. */
|
|
2213
2470
|
function shellPairDocDataAttr(shell, opts) {
|
|
2214
|
-
if (shell.layout !== "dual")
|
|
2215
|
-
return "";
|
|
2216
2471
|
const browseRaw = (shell.multiShell?.commentrayStaticBrowseUrl ??
|
|
2217
2472
|
opts.commentrayStaticBrowseUrl ??
|
|
2218
2473
|
"").trim();
|
|
@@ -2272,6 +2527,13 @@ export async function renderCodeBrowserHtml(opts) {
|
|
|
2272
2527
|
const pairIdentityDataAttrs = shellPairIdentityDataAttrs(shell, opts);
|
|
2273
2528
|
const sourceMarkdownToggles = sourceMarkdownToggleControlsHtml(shell.sourceMarkdownToggleEnabled);
|
|
2274
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
|
+
: "";
|
|
2275
2537
|
return buildCodeBrowserPageHtml({
|
|
2276
2538
|
title,
|
|
2277
2539
|
metaDescriptionHtml,
|
|
@@ -2300,6 +2562,8 @@ export async function renderCodeBrowserHtml(opts) {
|
|
|
2300
2562
|
sourceMarkdownToggleHtml: sourceMarkdownToggles.sourceMarkdownToggleHtml,
|
|
2301
2563
|
sourceMarkdownFlipScrollAffordanceHtml: sourceMarkdownToggles.sourceMarkdownFlipScrollAffordanceHtml,
|
|
2302
2564
|
sourcePaneModeAttr,
|
|
2565
|
+
scrollSyncStrategyShellAttr,
|
|
2566
|
+
stretchBufferSyncShellAttr,
|
|
2303
2567
|
});
|
|
2304
2568
|
}
|
|
2305
2569
|
//# sourceMappingURL=code-browser.js.map
|