@commentray/render 0.0.9 → 0.1.1
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/README.md +1 -1
- package/dist/block-stretch-layout.d.ts.map +1 -1
- package/dist/block-stretch-layout.js +2 -1
- package/dist/block-stretch-layout.js.map +1 -1
- package/dist/browse-page-slug.d.ts +6 -1
- package/dist/browse-page-slug.d.ts.map +1 -1
- package/dist/browse-page-slug.js +6 -1
- package/dist/browse-page-slug.js.map +1 -1
- package/dist/browse-pair-html-test-fixtures.d.ts +10 -0
- package/dist/browse-pair-html-test-fixtures.d.ts.map +1 -0
- package/dist/browse-pair-html-test-fixtures.js +19 -0
- package/dist/browse-pair-html-test-fixtures.js.map +1 -0
- package/dist/build-commentray-nav-search.d.ts +4 -4
- package/dist/build-commentray-nav-search.js +1 -1
- package/dist/code-browser-block-rays.d.ts +29 -0
- package/dist/code-browser-block-rays.d.ts.map +1 -1
- package/dist/code-browser-block-rays.js +120 -0
- package/dist/code-browser-block-rays.js.map +1 -1
- package/dist/code-browser-client.bundle.js +24 -11
- package/dist/code-browser-client.js +766 -116
- package/dist/code-browser-client.js.map +1 -1
- package/dist/code-browser-intro.css +187 -0
- package/dist/code-browser-pair-nav.d.ts +3 -3
- package/dist/code-browser-pair-nav.d.ts.map +1 -1
- package/dist/code-browser-pair-nav.js +25 -13
- package/dist/code-browser-pair-nav.js.map +1 -1
- package/dist/code-browser-wide-intro-controller.d.ts +4 -0
- package/dist/code-browser-wide-intro-controller.d.ts.map +1 -0
- package/dist/code-browser-wide-intro-controller.js +148 -0
- package/dist/code-browser-wide-intro-controller.js.map +1 -0
- package/dist/code-browser-wide-intro-layout.d.ts +3 -0
- package/dist/code-browser-wide-intro-layout.d.ts.map +1 -0
- package/dist/code-browser-wide-intro-layout.js +84 -0
- package/dist/code-browser-wide-intro-layout.js.map +1 -0
- package/dist/code-browser-wide-intro-steps.d.ts +11 -0
- package/dist/code-browser-wide-intro-steps.d.ts.map +1 -0
- package/dist/code-browser-wide-intro-steps.js +108 -0
- package/dist/code-browser-wide-intro-steps.js.map +1 -0
- package/dist/code-browser-wide-intro-ui.d.ts +14 -0
- package/dist/code-browser-wide-intro-ui.d.ts.map +1 -0
- package/dist/code-browser-wide-intro-ui.js +67 -0
- package/dist/code-browser-wide-intro-ui.js.map +1 -0
- package/dist/code-browser.d.ts +18 -4
- package/dist/code-browser.d.ts.map +1 -1
- package/dist/code-browser.js +506 -154
- package/dist/code-browser.js.map +1 -1
- package/dist/commentray-anchor-viewport-probe.d.ts +9 -0
- package/dist/commentray-anchor-viewport-probe.d.ts.map +1 -0
- package/dist/commentray-anchor-viewport-probe.js +13 -0
- package/dist/commentray-anchor-viewport-probe.js.map +1 -0
- package/dist/commentray-preview-html.d.ts +13 -0
- package/dist/commentray-preview-html.d.ts.map +1 -0
- package/dist/commentray-preview-html.js +12 -0
- package/dist/commentray-preview-html.js.map +1 -0
- package/dist/companion-markdown-preview-entry.d.ts +7 -0
- package/dist/companion-markdown-preview-entry.d.ts.map +1 -0
- package/dist/companion-markdown-preview-entry.js +6 -0
- package/dist/companion-markdown-preview-entry.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/inject-md-line-anchors.d.ts +18 -0
- package/dist/inject-md-line-anchors.d.ts.map +1 -0
- package/dist/inject-md-line-anchors.js +250 -0
- package/dist/inject-md-line-anchors.js.map +1 -0
- package/dist/inline-favicon.js +15 -15
- package/dist/markdown-pipeline.d.ts +5 -0
- package/dist/markdown-pipeline.d.ts.map +1 -1
- package/dist/markdown-pipeline.js +47 -1
- package/dist/markdown-pipeline.js.map +1 -1
- package/dist/side-by-side-layout-css.d.ts +1 -1
- package/dist/side-by-side-layout-css.d.ts.map +1 -1
- package/dist/side-by-side-layout-css.js +48 -0
- package/dist/side-by-side-layout-css.js.map +1 -1
- package/package.json +8 -3
- package/dist/code-browser-client.d.ts +0 -2
- package/dist/side-by-side-layout.css +0 -58
- package/dist/side-by-side-layout.embedded.d.ts +0 -3
- package/dist/side-by-side-layout.embedded.d.ts.map +0 -1
- package/dist/side-by-side-layout.embedded.js +0 -3
- package/dist/side-by-side-layout.embedded.js.map +0 -1
package/dist/code-browser.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
-
import { join } from "node:path";
|
|
3
|
-
import {
|
|
2
|
+
import path, { join } from "node:path";
|
|
3
|
+
import { buildBlockScrollLinks, findMonorepoPackagesDir, monorepoLayoutStartDir, normalizeRepoRelativePath, } from "@commentray/core";
|
|
4
4
|
import { tryBuildBlockStretchTableHtml } from "./block-stretch-layout.js";
|
|
5
5
|
import { formatCommentrayBuiltAtLocal } from "./build-stamp.js";
|
|
6
6
|
import { escapeHtml } from "./html-utils.js";
|
|
@@ -11,12 +11,28 @@ import { COMMENTRAY_FAVICON_LINK_HTML } from "./inline-favicon.js";
|
|
|
11
11
|
import { mermaidRuntimeScriptHtml } from "./mermaid-runtime-html.js";
|
|
12
12
|
import { renderMarkdownToHtml } from "./markdown-pipeline.js";
|
|
13
13
|
import { commentrayRenderVersion } from "./package-version.js";
|
|
14
|
+
import { normPosixPath } from "./code-browser-pair-nav.js";
|
|
15
|
+
import { injectCommentrayDocAnchors, injectSourceMarkdownAnchors, } from "./inject-md-line-anchors.js";
|
|
14
16
|
function renderGeneratorMetaHtml(label) {
|
|
15
17
|
const t = label?.trim();
|
|
16
18
|
if (!t)
|
|
17
19
|
return "";
|
|
18
20
|
return `<meta name="generator" content="${escapeHtml(t)}" />\n `;
|
|
19
21
|
}
|
|
22
|
+
/** Accepts short or full SHA; returns lowercase hex or undefined if the string is not a Git object name. */
|
|
23
|
+
function normalizePagesBuildCommitSha(raw) {
|
|
24
|
+
const t = raw?.trim();
|
|
25
|
+
if (!t)
|
|
26
|
+
return undefined;
|
|
27
|
+
const lower = t.toLowerCase();
|
|
28
|
+
if (!/^[0-9a-f]{7,40}$/.test(lower))
|
|
29
|
+
return undefined;
|
|
30
|
+
return lower;
|
|
31
|
+
}
|
|
32
|
+
function footerCommitSuffixHtml(commitSha) {
|
|
33
|
+
const esc = escapeHtml(commitSha);
|
|
34
|
+
return ` · <code class="app__footer-attribution__sha" translate="no">${esc}</code>`;
|
|
35
|
+
}
|
|
20
36
|
const META_DESCRIPTION_MAX_LEN = 320;
|
|
21
37
|
function codeBrowserMetaDescription(opts, title) {
|
|
22
38
|
const custom = opts.metaDescription?.trim();
|
|
@@ -29,105 +45,6 @@ function renderMetaDescriptionHtml(opts, title) {
|
|
|
29
45
|
const content = codeBrowserMetaDescription(opts, title);
|
|
30
46
|
return `<meta name="description" content="${escapeHtml(content)}" />\n `;
|
|
31
47
|
}
|
|
32
|
-
/** Single capture: marker id (avoid a wrapping group around the whole comment — that shifted indices). */
|
|
33
|
-
const BLOCK_MARKER_HTML_LINE = new RegExp(`^<!--\\s*commentray:block\\s+id=(${MARKER_ID_BODY})\\s*-->$`, "i");
|
|
34
|
-
function trimEndSpacesTabs(s) {
|
|
35
|
-
let end = s.length;
|
|
36
|
-
while (end > 0) {
|
|
37
|
-
const c = s[end - 1];
|
|
38
|
-
if (c !== " " && c !== "\t")
|
|
39
|
-
break;
|
|
40
|
-
end--;
|
|
41
|
-
}
|
|
42
|
-
return s.slice(0, end);
|
|
43
|
-
}
|
|
44
|
-
function isSetextUnderlineLine(line) {
|
|
45
|
-
const t = trimEndSpacesTabs(line);
|
|
46
|
-
return /^\s{0,3}=+\s*$/.test(t) || /^\s{0,3}-+\s*$/.test(t);
|
|
47
|
-
}
|
|
48
|
-
function isThematicBreakLine(line) {
|
|
49
|
-
const t = trimEndSpacesTabs(line);
|
|
50
|
-
return (/^\s{0,3}(?:\*[ \t]*){3,}\s*$/.test(t) ||
|
|
51
|
-
/^\s{0,3}(?:-[ \t]*){3,}\s*$/.test(t) ||
|
|
52
|
-
/^\s{0,3}(?:_[ \t]*){3,}\s*$/.test(t));
|
|
53
|
-
}
|
|
54
|
-
function parseFenceDelimiter(line) {
|
|
55
|
-
const t = trimEndSpacesTabs(line);
|
|
56
|
-
const m = /^(\s{0,3})(`{3,}|~{3,})(.*)$/.exec(t);
|
|
57
|
-
if (!m)
|
|
58
|
-
return null;
|
|
59
|
-
const run = m[2];
|
|
60
|
-
const head = run[0];
|
|
61
|
-
if (head !== "`" && head !== "~")
|
|
62
|
-
return null;
|
|
63
|
-
const ch = head === "`" ? "`" : "~";
|
|
64
|
-
return { ch, runLen: run.length, rest: m[3] ?? "" };
|
|
65
|
-
}
|
|
66
|
-
function isClosingFenceLine(info, open) {
|
|
67
|
-
if (info.ch !== open.ch || info.runLen < open.len)
|
|
68
|
-
return false;
|
|
69
|
-
return info.rest.trim() === "";
|
|
70
|
-
}
|
|
71
|
-
function lineAnchorHtml(mdLine0) {
|
|
72
|
-
const mdLine = String(mdLine0);
|
|
73
|
-
return `<span class="commentray-line-anchor" data-commentray-md-line="${mdLine}" id="commentray-md-line-${mdLine}" aria-hidden="true"></span>`;
|
|
74
|
-
}
|
|
75
|
-
function appendMdLineAnchorWhenAllowed(line, mdLine0) {
|
|
76
|
-
if (isSetextUnderlineLine(line) || isThematicBreakLine(line))
|
|
77
|
-
return line;
|
|
78
|
-
/** Blank lines must stay blank: a line that is only `<span …>` breaks CommonMark HTML / paragraph starts after block markers. */
|
|
79
|
-
if (line === "")
|
|
80
|
-
return "";
|
|
81
|
-
return `${line}${lineAnchorHtml(mdLine0)}`;
|
|
82
|
-
}
|
|
83
|
-
/**
|
|
84
|
-
* Inserts per-line anchors for search / hash jumps and block separator anchors after each
|
|
85
|
-
* `<!-- commentray:block … -->` line (optional index attrs).
|
|
86
|
-
*
|
|
87
|
-
* Anchors are appended to the line when safe. A **leading** `<span>` breaks CommonMark block
|
|
88
|
-
* recognition (`#` headings, lists, thematic breaks, fences). Fenced code lines must not get a
|
|
89
|
-
* trailing anchor either (would corrupt fence delimiters or appear inside code).
|
|
90
|
-
*/
|
|
91
|
-
function injectCommentrayDocAnchors(markdown, links) {
|
|
92
|
-
const byId = links ? new Map(links.map((l) => [l.id, l])) : undefined;
|
|
93
|
-
const lines = markdown.split("\n");
|
|
94
|
-
let fence = null;
|
|
95
|
-
const out = [];
|
|
96
|
-
for (let i = 0; i < lines.length; i++) {
|
|
97
|
-
const line = lines[i];
|
|
98
|
-
const delim = parseFenceDelimiter(line);
|
|
99
|
-
if (fence) {
|
|
100
|
-
if (delim && isClosingFenceLine(delim, fence)) {
|
|
101
|
-
fence = null;
|
|
102
|
-
out.push(line);
|
|
103
|
-
continue;
|
|
104
|
-
}
|
|
105
|
-
out.push(line);
|
|
106
|
-
continue;
|
|
107
|
-
}
|
|
108
|
-
if (delim) {
|
|
109
|
-
fence = { ch: delim.ch, len: delim.runLen };
|
|
110
|
-
out.push(line);
|
|
111
|
-
continue;
|
|
112
|
-
}
|
|
113
|
-
const m = BLOCK_MARKER_HTML_LINE.exec(line);
|
|
114
|
-
if (m?.[1]) {
|
|
115
|
-
const id = m[1];
|
|
116
|
-
const link = byId?.get(id);
|
|
117
|
-
const attrs = link !== undefined
|
|
118
|
-
? ` data-source-start="${String(link.sourceStart)}" data-commentray-line="${String(link.commentrayLine)}"`
|
|
119
|
-
: "";
|
|
120
|
-
/** One `push` with embedded `\n\n` merged poorly with `join("\\n")`; keep real blank lines around raw `<div>`. */
|
|
121
|
-
out.push(`${line}${lineAnchorHtml(i)}`);
|
|
122
|
-
out.push("");
|
|
123
|
-
out.push(`<div id="commentray-block-${escapeHtml(id)}" class="commentray-block-anchor" aria-hidden="true"${attrs}></div>`);
|
|
124
|
-
out.push("");
|
|
125
|
-
continue;
|
|
126
|
-
}
|
|
127
|
-
out.push(appendMdLineAnchorWhenAllowed(line, i));
|
|
128
|
-
}
|
|
129
|
-
return out.join("\n");
|
|
130
|
-
}
|
|
131
48
|
/** GitHub “mark” glyph (Octicons-style path), MIT-licensed silhouette. */
|
|
132
49
|
const GITHUB_MARK_SVG = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="20" height="20" fill="currentColor" aria-hidden="true">' +
|
|
133
50
|
'<path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"/>' +
|
|
@@ -159,6 +76,25 @@ const TOOLBAR_ICON_FLIP_PANES_SVG = '<svg xmlns="http://www.w3.org/2000/svg" vie
|
|
|
159
76
|
'<path d="M10.5 12H6l2.5-2.5M6 12l2.5 2.5"/>' +
|
|
160
77
|
'<path d="M13.5 12H18l-2.5-2.5M18 12l-2.5 2.5"/>' +
|
|
161
78
|
"</svg>";
|
|
79
|
+
/** Source markdown mode flip: rendered page <-> plain markdown rows. */
|
|
80
|
+
const TOOLBAR_ICON_FLIP_SOURCE_MARKDOWN_SVG = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">' +
|
|
81
|
+
'<rect x="3" y="4" width="8" height="16" rx="1.5"/>' +
|
|
82
|
+
'<path d="M6 8h2M6 11h2M6 14h2"/>' +
|
|
83
|
+
'<rect x="13" y="4" width="8" height="16" rx="1.5"/>' +
|
|
84
|
+
'<path d="m15.5 12 2-2 2 2"/>' +
|
|
85
|
+
'<path d="m19.5 12-2 2-2-2"/>' +
|
|
86
|
+
"</svg>";
|
|
87
|
+
/** Link/share glyph for copying a permalink to the current documentation pair. */
|
|
88
|
+
const TOOLBAR_ICON_SHARE_LINK_SVG = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">' +
|
|
89
|
+
'<path d="M10 14a5 5 0 0 0 7.07 0l2.83-2.83a5 5 0 0 0-7.07-7.07L10 6"/>' +
|
|
90
|
+
'<path d="M14 10a5 5 0 0 0-7.07 0L4.1 12.83a5 5 0 0 0 7.07 7.07L14 17"/>' +
|
|
91
|
+
"</svg>";
|
|
92
|
+
/** Help glyph for re-running the onboarding walkthrough. */
|
|
93
|
+
const TOOLBAR_ICON_HELP_TOUR_SVG = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">' +
|
|
94
|
+
'<circle cx="12" cy="12" r="9"/>' +
|
|
95
|
+
'<path d="M9.1 9a3 3 0 1 1 4.92 2.3c-.8.6-1.52 1.08-1.52 2.2"/>' +
|
|
96
|
+
'<circle cx="12" cy="17" r="0.8" fill="currentColor" stroke="none"/>' +
|
|
97
|
+
"</svg>";
|
|
162
98
|
function safeExternalHttpUrl(url) {
|
|
163
99
|
const t = url?.trim();
|
|
164
100
|
if (!t)
|
|
@@ -194,9 +130,10 @@ function buildToolbarEndHtml(githubRepoUrl, siteHubUrl) {
|
|
|
194
130
|
return "";
|
|
195
131
|
}
|
|
196
132
|
function renderPageFooterHtml(input) {
|
|
197
|
-
const { builtAt, toolHomeUrl, commentrayRenderSemver } = input;
|
|
133
|
+
const { builtAt, toolHomeUrl, commentrayRenderSemver, pagesBuildCommitSha } = input;
|
|
198
134
|
const iso = builtAt.toISOString();
|
|
199
135
|
const human = formatCommentrayBuiltAtLocal(builtAt);
|
|
136
|
+
const commitSuffix = pagesBuildCommitSha ? footerCommitSuffixHtml(pagesBuildCommitSha) : "";
|
|
200
137
|
const tool = safeExternalHttpUrl(toolHomeUrl);
|
|
201
138
|
if (tool) {
|
|
202
139
|
const te = escapeHtml(tool);
|
|
@@ -206,11 +143,14 @@ function renderPageFooterHtml(input) {
|
|
|
206
143
|
`Rendered with <a href="${te}" target="_blank" rel="noopener noreferrer">Commentray</a> ` +
|
|
207
144
|
`<span class="app__footer-attribution__version" translate="no">v${ver}</span>: ` +
|
|
208
145
|
`<time datetime="${escapeHtml(iso)}">${escapeHtml(human)}</time>` +
|
|
146
|
+
commitSuffix +
|
|
209
147
|
`</p>` +
|
|
210
148
|
`</footer>`);
|
|
211
149
|
}
|
|
212
150
|
return (`<footer class="app__footer" role="contentinfo">` +
|
|
213
|
-
`<p class="app__footer-line">HTML generated <time datetime="${escapeHtml(iso)}">${escapeHtml(human)}</time
|
|
151
|
+
`<p class="app__footer-line">HTML generated <time datetime="${escapeHtml(iso)}">${escapeHtml(human)}</time>` +
|
|
152
|
+
commitSuffix +
|
|
153
|
+
`</p>` +
|
|
214
154
|
`</footer>`);
|
|
215
155
|
}
|
|
216
156
|
function renderRelatedGithubNavHtml(links) {
|
|
@@ -242,9 +182,13 @@ function renderToolbarDocHubHtml(opts) {
|
|
|
242
182
|
: "";
|
|
243
183
|
return { toolbarDocHubHtml, navRailDocumentedHtml };
|
|
244
184
|
}
|
|
245
|
-
function dualPanePanesInnerHtml(codeHtml, commentrayHtml) {
|
|
185
|
+
function dualPanePanesInnerHtml(codeHtml, commentrayHtml, sourceMarkdownRenderedHtml) {
|
|
186
|
+
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
|
+
: "";
|
|
246
189
|
return (` <section class="pane--code" id="code-pane" aria-label="Source code">` +
|
|
247
|
-
`
|
|
190
|
+
` <div class="source-pane source-pane--code" id="code-pane-code-body">${codeHtml}</div>\n` +
|
|
191
|
+
sourceRenderedPaneHtml +
|
|
248
192
|
` </section>\n` +
|
|
249
193
|
` <div class="gutter" id="gutter" role="separator" aria-orientation="vertical" aria-label="Resize panes"></div>\n` +
|
|
250
194
|
` <section class="pane--doc commentray" id="doc-pane" aria-label="Commentray">\n` +
|
|
@@ -253,7 +197,42 @@ function dualPanePanesInnerHtml(codeHtml, commentrayHtml) {
|
|
|
253
197
|
` </div>\n` +
|
|
254
198
|
` </section>\n`);
|
|
255
199
|
}
|
|
256
|
-
|
|
200
|
+
function sourceMarkdownToggleControlsHtml(enabled) {
|
|
201
|
+
if (!enabled) {
|
|
202
|
+
return { sourceMarkdownToggleHtml: "", sourceMarkdownFlipScrollAffordanceHtml: "" };
|
|
203
|
+
}
|
|
204
|
+
const label = "Switch source pane between rendered markdown and markdown source";
|
|
205
|
+
const title = "Switch source pane between rendered markdown and markdown source";
|
|
206
|
+
const btn = `<button type="button" id="source-markdown-pane-flip" class="toolbar-source-render-toggle" aria-controls="code-pane" aria-pressed="false" aria-label="${label}" title="${title}"><span class="toolbar-source-render-toggle__box" aria-hidden="true"></span><span class="toolbar-source-render-toggle__face" aria-hidden="true">${TOOLBAR_ICON_FLIP_SOURCE_MARKDOWN_SVG}</span><span class="toolbar-source-render-toggle__caption">Render</span></button>`;
|
|
207
|
+
const floating = `<button type="button" id="source-markdown-pane-flip-scroll" class="toolbar-icon-btn toolbar-icon-btn--source-markdown-scroll-narrow" hidden aria-controls="code-pane" aria-pressed="false" aria-label="${label}" title="${title}">${TOOLBAR_ICON_FLIP_SOURCE_MARKDOWN_SVG}</button>`;
|
|
208
|
+
return {
|
|
209
|
+
sourceMarkdownToggleHtml: btn,
|
|
210
|
+
sourceMarkdownFlipScrollAffordanceHtml: floating,
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
function isMarkdownLikeSource(opts) {
|
|
214
|
+
const lang = opts.language.trim().toLowerCase();
|
|
215
|
+
if (lang === "md" || lang === "markdown" || lang === "mdx")
|
|
216
|
+
return true;
|
|
217
|
+
const filePath = (opts.filePath ?? "").trim().toLowerCase();
|
|
218
|
+
return filePath.endsWith(".md") || filePath.endsWith(".mdx") || filePath.endsWith(".markdown");
|
|
219
|
+
}
|
|
220
|
+
/** For source-pane Markdown, resolve local links from the source file directory (repo tree), not companion storage. */
|
|
221
|
+
function sourcePaneOutputUrls(opts) {
|
|
222
|
+
const out = opts.commentrayOutputUrls;
|
|
223
|
+
if (!out)
|
|
224
|
+
return undefined;
|
|
225
|
+
const srcRel = (opts.filePath ?? "").trim();
|
|
226
|
+
if (srcRel.length === 0)
|
|
227
|
+
return out;
|
|
228
|
+
const repoRoot = path.resolve(out.repoRootAbs);
|
|
229
|
+
const candidate = path.resolve(repoRoot, srcRel);
|
|
230
|
+
const rel = path.relative(repoRoot, candidate);
|
|
231
|
+
if (rel.startsWith("..") || path.isAbsolute(rel))
|
|
232
|
+
return out;
|
|
233
|
+
return { ...out, markdownUrlBaseDirAbs: path.dirname(candidate) };
|
|
234
|
+
}
|
|
235
|
+
/** Pair paths above the panes; column widths track the resizable split via `--split-pct`. */
|
|
257
236
|
function renderShellPairContextHtml(filePath, commentrayPath) {
|
|
258
237
|
const fpRaw = (filePath ?? "").trim();
|
|
259
238
|
const crRaw = (commentrayPath ?? "").trim();
|
|
@@ -265,12 +244,10 @@ function renderShellPairContextHtml(filePath, commentrayPath) {
|
|
|
265
244
|
const crDisp = crRaw.length > 0 ? cr : "—";
|
|
266
245
|
return `<div class="shell__pair-context" aria-label="Current documentation pair">
|
|
267
246
|
<div class="shell__pair-cell shell__pair-cell--src">
|
|
268
|
-
<span class="shell__pair-lab">Src</span>
|
|
269
247
|
<span class="shell__pair-path" title="${fp}">${fpDisp}</span>
|
|
270
248
|
</div>
|
|
271
249
|
<div class="shell__pair-gutter-spacer" aria-hidden="true"></div>
|
|
272
250
|
<div class="shell__pair-cell shell__pair-cell--doc">
|
|
273
|
-
<span class="shell__pair-lab">Doc</span>
|
|
274
251
|
<span class="shell__pair-path shell__pair-path--secondary" id="nav-rail-doc-path" title="${cr}">${crDisp}</span>
|
|
275
252
|
</div>
|
|
276
253
|
</div>`;
|
|
@@ -292,6 +269,19 @@ function loadCodeBrowserClientBundle() {
|
|
|
292
269
|
}
|
|
293
270
|
throw new Error("Missing code-browser-client.bundle.js. Run `npm run build -w @commentray/render` to bundle the browser client.");
|
|
294
271
|
}
|
|
272
|
+
/** Intro-tour specific stylesheet; kept in a dedicated CSS file for easier tweaking. */
|
|
273
|
+
function loadCodeBrowserIntroStyles() {
|
|
274
|
+
const packagesDir = findMonorepoPackagesDir(monorepoLayoutStartDir(import.meta.url));
|
|
275
|
+
const renderDistDir = join(packagesDir, "render", "dist");
|
|
276
|
+
const inDist = join(renderDistDir, "code-browser-intro.css");
|
|
277
|
+
const fromSrc = join(packagesDir, "render", "src", "code-browser-intro.css");
|
|
278
|
+
for (const p of [inDist, fromSrc]) {
|
|
279
|
+
if (existsSync(p)) {
|
|
280
|
+
return readFileSync(p, "utf8");
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
throw new Error("Missing code-browser-intro.css. Ensure the render package includes intro tour styles.");
|
|
284
|
+
}
|
|
295
285
|
/**
|
|
296
286
|
* Compact theme control: primary click opens a menu (readme.io–style), secondary click cycles
|
|
297
287
|
* system → light → dark. Paired with {@link ./code-browser-color-theme.ts} and the client bundle.
|
|
@@ -309,6 +299,11 @@ const TOOLBAR_COLOR_THEME_HTML = ` <div class="toolbar-theme">
|
|
|
309
299
|
</div>
|
|
310
300
|
</div>
|
|
311
301
|
`;
|
|
302
|
+
const TOOLBAR_SHARE_LINK_HTML = ` <button type="button" id="commentray-share-link" class="toolbar-theme__trigger toolbar-share-link-btn" aria-label="Copy shareable permalink" title="Copy shareable permalink">${TOOLBAR_ICON_SHARE_LINK_SVG}</button>
|
|
303
|
+
`;
|
|
304
|
+
const TOOLBAR_HELP_TOUR_HTML = ` <button type="button" id="commentray-help-tour" class="toolbar-theme__trigger toolbar-help-tour-btn" aria-label="Restart onboarding walkthrough" title="Restart onboarding walkthrough">${TOOLBAR_ICON_HELP_TOUR_SVG}</button>
|
|
305
|
+
`;
|
|
306
|
+
const CODE_BROWSER_INTRO_STYLES = loadCodeBrowserIntroStyles();
|
|
312
307
|
const CODE_BROWSER_STYLES = `
|
|
313
308
|
:root {
|
|
314
309
|
--cr-control-h: 32px;
|
|
@@ -653,7 +648,15 @@ const CODE_BROWSER_STYLES = `
|
|
|
653
648
|
text-underline-offset: 2px;
|
|
654
649
|
}
|
|
655
650
|
.app__footer-attribution__version { font-weight: 600; }
|
|
651
|
+
.app__footer-attribution__sha {
|
|
652
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
|
653
|
+
font-size: 0.95em;
|
|
654
|
+
font-weight: 500;
|
|
655
|
+
padding: 0 2px;
|
|
656
|
+
word-break: break-all;
|
|
657
|
+
}
|
|
656
658
|
.toolbar label { display: inline-flex; align-items: center; gap: 6px; cursor: pointer; user-select: none; }
|
|
659
|
+
.toolbar label[hidden] { display: none !important; }
|
|
657
660
|
.toolbar-wrap-lines {
|
|
658
661
|
position: relative;
|
|
659
662
|
margin: 0;
|
|
@@ -772,6 +775,80 @@ const CODE_BROWSER_STYLES = `
|
|
|
772
775
|
outline: 2px solid color-mix(in oklab, CanvasText 45%, Canvas);
|
|
773
776
|
outline-offset: 2px;
|
|
774
777
|
}
|
|
778
|
+
.toolbar-source-render-toggle {
|
|
779
|
+
position: relative;
|
|
780
|
+
margin: 0;
|
|
781
|
+
min-height: var(--cr-control-h);
|
|
782
|
+
padding: 0 12px 0 10px;
|
|
783
|
+
border-radius: var(--cr-control-radius);
|
|
784
|
+
border: 1px solid color-mix(in oklab, CanvasText 16%, Canvas);
|
|
785
|
+
background: Canvas;
|
|
786
|
+
display: inline-flex;
|
|
787
|
+
flex-direction: row;
|
|
788
|
+
align-items: center;
|
|
789
|
+
justify-content: flex-start;
|
|
790
|
+
gap: 8px;
|
|
791
|
+
font-size: var(--cr-ui-fs);
|
|
792
|
+
font-weight: 500;
|
|
793
|
+
color: color-mix(in oklab, CanvasText 88%, Canvas);
|
|
794
|
+
cursor: pointer;
|
|
795
|
+
}
|
|
796
|
+
.toolbar-source-render-toggle:hover {
|
|
797
|
+
background: color-mix(in oklab, CanvasText 6%, Canvas);
|
|
798
|
+
}
|
|
799
|
+
.toolbar-source-render-toggle__box {
|
|
800
|
+
flex: 0 0 auto;
|
|
801
|
+
width: 16px;
|
|
802
|
+
height: 16px;
|
|
803
|
+
box-sizing: border-box;
|
|
804
|
+
border: 1.5px solid color-mix(in oklab, CanvasText 38%, Canvas);
|
|
805
|
+
border-radius: 3px;
|
|
806
|
+
background: Canvas;
|
|
807
|
+
display: inline-flex;
|
|
808
|
+
align-items: center;
|
|
809
|
+
justify-content: center;
|
|
810
|
+
color: CanvasText;
|
|
811
|
+
}
|
|
812
|
+
.toolbar-source-render-toggle[aria-pressed="true"] .toolbar-source-render-toggle__box {
|
|
813
|
+
border-color: color-mix(in oklab, CanvasText 52%, Canvas);
|
|
814
|
+
background: color-mix(in oklab, CanvasText 6%, Canvas);
|
|
815
|
+
}
|
|
816
|
+
.toolbar-source-render-toggle__box::after {
|
|
817
|
+
content: "";
|
|
818
|
+
display: none;
|
|
819
|
+
width: 4px;
|
|
820
|
+
height: 9px;
|
|
821
|
+
margin-top: -2px;
|
|
822
|
+
border: solid currentColor;
|
|
823
|
+
border-width: 0 2px 2px 0;
|
|
824
|
+
transform: rotate(45deg);
|
|
825
|
+
}
|
|
826
|
+
.toolbar-source-render-toggle[aria-pressed="true"] .toolbar-source-render-toggle__box::after {
|
|
827
|
+
display: block;
|
|
828
|
+
}
|
|
829
|
+
.toolbar-source-render-toggle__face {
|
|
830
|
+
display: none;
|
|
831
|
+
align-items: center;
|
|
832
|
+
justify-content: center;
|
|
833
|
+
min-height: var(--cr-control-h);
|
|
834
|
+
min-width: var(--cr-control-h);
|
|
835
|
+
color: color-mix(in oklab, CanvasText 82%, Canvas);
|
|
836
|
+
}
|
|
837
|
+
.toolbar-source-render-toggle__caption {
|
|
838
|
+
white-space: nowrap;
|
|
839
|
+
}
|
|
840
|
+
.toolbar-source-render-toggle[aria-pressed="true"] {
|
|
841
|
+
color: CanvasText;
|
|
842
|
+
background: color-mix(in oklab, CanvasText 10%, Canvas);
|
|
843
|
+
}
|
|
844
|
+
.toolbar-source-render-toggle:focus-visible {
|
|
845
|
+
outline: 2px solid color-mix(in oklab, CanvasText 45%, Canvas);
|
|
846
|
+
outline-offset: 2px;
|
|
847
|
+
}
|
|
848
|
+
.toolbar-icon-btn--source-markdown {
|
|
849
|
+
display: inline-flex;
|
|
850
|
+
}
|
|
851
|
+
${CODE_BROWSER_INTRO_STYLES}
|
|
775
852
|
.toolbar label input:focus-visible {
|
|
776
853
|
outline: 2px solid color-mix(in oklab, CanvasText 45%, Canvas);
|
|
777
854
|
outline-offset: 2px;
|
|
@@ -810,6 +887,16 @@ const CODE_BROWSER_STYLES = `
|
|
|
810
887
|
outline: 2px solid color-mix(in oklab, CanvasText 45%, Canvas);
|
|
811
888
|
outline-offset: 2px;
|
|
812
889
|
}
|
|
890
|
+
.toolbar-theme__trigger svg {
|
|
891
|
+
width: var(--cr-icon-inner);
|
|
892
|
+
height: var(--cr-icon-inner);
|
|
893
|
+
display: block;
|
|
894
|
+
flex: 0 0 auto;
|
|
895
|
+
}
|
|
896
|
+
.toolbar-share-link-btn[data-copied="true"] {
|
|
897
|
+
background: color-mix(in oklab, #2ea043 24%, Canvas);
|
|
898
|
+
border-color: color-mix(in oklab, #2ea043 48%, CanvasText);
|
|
899
|
+
}
|
|
813
900
|
.toolbar-theme__trigger .toolbar-theme__icon {
|
|
814
901
|
display: none;
|
|
815
902
|
flex: 0 0 auto;
|
|
@@ -917,6 +1004,14 @@ const CODE_BROWSER_STYLES = `
|
|
|
917
1004
|
.documented-files-tree .tree-file-link:hover {
|
|
918
1005
|
opacity: 0.92;
|
|
919
1006
|
}
|
|
1007
|
+
.documented-files-tree .tree-file-link.tree-file-link--current {
|
|
1008
|
+
font-weight: 600;
|
|
1009
|
+
text-decoration-thickness: 2px;
|
|
1010
|
+
border-radius: 3px;
|
|
1011
|
+
padding: 1px 3px;
|
|
1012
|
+
margin: -1px -3px;
|
|
1013
|
+
background: color-mix(in oklab, CanvasText 10%, Canvas);
|
|
1014
|
+
}
|
|
920
1015
|
.toolbar button {
|
|
921
1016
|
font: inherit;
|
|
922
1017
|
font-size: var(--cr-ui-fs);
|
|
@@ -1018,14 +1113,6 @@ const CODE_BROWSER_STYLES = `
|
|
|
1018
1113
|
min-width: 0;
|
|
1019
1114
|
padding-left: var(--cr-pane-inline-pad);
|
|
1020
1115
|
}
|
|
1021
|
-
.shell__pair-lab {
|
|
1022
|
-
flex: 0 0 auto;
|
|
1023
|
-
font-size: var(--cr-label-caps-fs);
|
|
1024
|
-
font-weight: 700;
|
|
1025
|
-
letter-spacing: var(--cr-label-caps-track);
|
|
1026
|
-
text-transform: uppercase;
|
|
1027
|
-
opacity: 0.72;
|
|
1028
|
-
}
|
|
1029
1116
|
.shell__pair-path {
|
|
1030
1117
|
flex: 1 1 auto;
|
|
1031
1118
|
min-width: 0;
|
|
@@ -1044,6 +1131,31 @@ const CODE_BROWSER_STYLES = `
|
|
|
1044
1131
|
--code-line-font-size: 13px;
|
|
1045
1132
|
--code-line-height: 1.5;
|
|
1046
1133
|
}
|
|
1134
|
+
.source-pane {
|
|
1135
|
+
min-width: 0;
|
|
1136
|
+
}
|
|
1137
|
+
.source-pane--rendered-md {
|
|
1138
|
+
font-size: 15px;
|
|
1139
|
+
line-height: 1.45;
|
|
1140
|
+
}
|
|
1141
|
+
.source-pane--rendered-md img {
|
|
1142
|
+
max-width: 100%;
|
|
1143
|
+
height: auto;
|
|
1144
|
+
}
|
|
1145
|
+
.source-pane--rendered-md .commentray-mermaid {
|
|
1146
|
+
overflow-x: auto;
|
|
1147
|
+
max-width: 100%;
|
|
1148
|
+
}
|
|
1149
|
+
.source-pane--rendered-md .commentray-line-anchor--source {
|
|
1150
|
+
display: inline;
|
|
1151
|
+
vertical-align: baseline;
|
|
1152
|
+
}
|
|
1153
|
+
#shell[data-source-pane-mode="rendered-markdown"] .source-pane--code {
|
|
1154
|
+
display: none;
|
|
1155
|
+
}
|
|
1156
|
+
#shell[data-source-pane-mode="source"] .source-pane--rendered-md {
|
|
1157
|
+
display: none;
|
|
1158
|
+
}
|
|
1047
1159
|
.pane--code .code-line-stack { --code-ln-min-ch: 3; }
|
|
1048
1160
|
.pane--code .code-line {
|
|
1049
1161
|
display: grid;
|
|
@@ -1105,7 +1217,12 @@ const CODE_BROWSER_STYLES = `
|
|
|
1105
1217
|
.gutter__rays {
|
|
1106
1218
|
position: absolute; inset: 0; pointer-events: none; z-index: 1;
|
|
1107
1219
|
}
|
|
1108
|
-
.gutter__rays svg {
|
|
1220
|
+
.gutter__rays svg {
|
|
1221
|
+
width: 100%;
|
|
1222
|
+
height: 100%;
|
|
1223
|
+
display: block;
|
|
1224
|
+
overflow: hidden;
|
|
1225
|
+
}
|
|
1109
1226
|
.gutter__rays-path {
|
|
1110
1227
|
fill: none; stroke-linecap: round; vector-effect: non-scaling-stroke;
|
|
1111
1228
|
stroke: color-mix(in oklab, var(--commentray-ray-accent) 72%, CanvasText);
|
|
@@ -1144,11 +1261,95 @@ const CODE_BROWSER_STYLES = `
|
|
|
1144
1261
|
.doc-pane-body {
|
|
1145
1262
|
flex: 1 1 auto; min-height: 0; overflow: auto;
|
|
1146
1263
|
}
|
|
1147
|
-
|
|
1148
|
-
.pane--doc .doc-pane-body :where(
|
|
1264
|
+
/* Inline backtick code chips (GitHub-like): prose context only, never fenced pre/code blocks. */
|
|
1265
|
+
.pane--doc .doc-pane-body :where(p, li, blockquote, td, th, h1, h2, h3, h4, h5, h6) > code,
|
|
1266
|
+
.shell--stretch-rows .stretch-preamble :where(p, li, blockquote, td, th, h1, h2, h3, h4, h5, h6) > code,
|
|
1267
|
+
.block-stretch td.stretch-doc .stretch-doc-inner :where(p, li, blockquote, td, th, h1, h2, h3, h4, h5, h6) > code {
|
|
1268
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace;
|
|
1269
|
+
font-size: 0.92em;
|
|
1270
|
+
padding: 0.12em 0.36em;
|
|
1271
|
+
border-radius: 6px;
|
|
1272
|
+
border: 1px solid color-mix(in oklab, CanvasText 12%, Canvas);
|
|
1273
|
+
background: color-mix(in oklab, CanvasText 8%, Canvas);
|
|
1274
|
+
color: inherit;
|
|
1275
|
+
}
|
|
1276
|
+
@media (prefers-color-scheme: dark) {
|
|
1277
|
+
:root:is(:not([data-commentray-theme]), [data-commentray-theme="system"]) .pane--doc .doc-pane-body :where(p, li, blockquote, td, th, h1, h2, h3, h4, h5, h6) > code,
|
|
1278
|
+
:root:is(:not([data-commentray-theme]), [data-commentray-theme="system"]) .shell--stretch-rows .stretch-preamble :where(p, li, blockquote, td, th, h1, h2, h3, h4, h5, h6) > code,
|
|
1279
|
+
:root:is(:not([data-commentray-theme]), [data-commentray-theme="system"]) .block-stretch td.stretch-doc .stretch-doc-inner :where(p, li, blockquote, td, th, h1, h2, h3, h4, h5, h6) > code {
|
|
1280
|
+
border-color: color-mix(in oklab, CanvasText 26%, Canvas);
|
|
1281
|
+
background: color-mix(in oklab, CanvasText 16%, Canvas);
|
|
1282
|
+
}
|
|
1283
|
+
}
|
|
1284
|
+
:root[data-commentray-theme="dark"] .pane--doc .doc-pane-body :where(p, li, blockquote, td, th, h1, h2, h3, h4, h5, h6) > code,
|
|
1285
|
+
:root[data-commentray-theme="dark"] .shell--stretch-rows .stretch-preamble :where(p, li, blockquote, td, th, h1, h2, h3, h4, h5, h6) > code,
|
|
1286
|
+
:root[data-commentray-theme="dark"] .block-stretch td.stretch-doc .stretch-doc-inner :where(p, li, blockquote, td, th, h1, h2, h3, h4, h5, h6) > code {
|
|
1287
|
+
border-color: color-mix(in oklab, CanvasText 26%, Canvas);
|
|
1288
|
+
background: color-mix(in oklab, CanvasText 16%, Canvas);
|
|
1289
|
+
}
|
|
1290
|
+
/**
|
|
1291
|
+
* GFM tables in rendered Markdown (doc pane, stretch preamble, per-block doc cells).
|
|
1292
|
+
* Intrinsic width so the pane scrolls sideways instead of squeezing columns; borders
|
|
1293
|
+
* and padding match familiar GitHub-style readability.
|
|
1294
|
+
*/
|
|
1295
|
+
.pane--doc .doc-pane-body :where(table),
|
|
1296
|
+
.shell--stretch-rows .stretch-preamble :where(table),
|
|
1297
|
+
.block-stretch td.stretch-doc .stretch-doc-inner :where(table) {
|
|
1149
1298
|
width: max-content;
|
|
1150
1299
|
max-width: none;
|
|
1151
1300
|
border-collapse: collapse;
|
|
1301
|
+
margin: 0.85em 0;
|
|
1302
|
+
font-size: inherit;
|
|
1303
|
+
line-height: inherit;
|
|
1304
|
+
}
|
|
1305
|
+
.pane--doc .doc-pane-body :where(th, td),
|
|
1306
|
+
.shell--stretch-rows .stretch-preamble :where(th, td),
|
|
1307
|
+
.block-stretch td.stretch-doc .stretch-doc-inner :where(th, td) {
|
|
1308
|
+
border: 1px solid color-mix(in oklab, CanvasText 22%, Canvas);
|
|
1309
|
+
padding: 8px 12px;
|
|
1310
|
+
vertical-align: top;
|
|
1311
|
+
}
|
|
1312
|
+
.pane--doc .doc-pane-body :where(thead th),
|
|
1313
|
+
.shell--stretch-rows .stretch-preamble :where(thead th),
|
|
1314
|
+
.block-stretch td.stretch-doc .stretch-doc-inner :where(thead th) {
|
|
1315
|
+
font-weight: 600;
|
|
1316
|
+
background: color-mix(in oklab, CanvasText 7%, Canvas);
|
|
1317
|
+
}
|
|
1318
|
+
.pane--doc .doc-pane-body tbody tr:nth-child(even) :where(td),
|
|
1319
|
+
.shell--stretch-rows .stretch-preamble tbody tr:nth-child(even) :where(td),
|
|
1320
|
+
.block-stretch td.stretch-doc .stretch-doc-inner tbody tr:nth-child(even) :where(td) {
|
|
1321
|
+
background: color-mix(in oklab, CanvasText 3.5%, Canvas);
|
|
1322
|
+
}
|
|
1323
|
+
.pane--doc .doc-pane-body :where(ul.contains-task-list),
|
|
1324
|
+
.shell--stretch-rows .stretch-preamble :where(ul.contains-task-list),
|
|
1325
|
+
.block-stretch td.stretch-doc .stretch-doc-inner :where(ul.contains-task-list) {
|
|
1326
|
+
list-style: none;
|
|
1327
|
+
padding-inline-start: 1.2em;
|
|
1328
|
+
}
|
|
1329
|
+
.pane--doc .doc-pane-body :where(li.task-list-item),
|
|
1330
|
+
.shell--stretch-rows .stretch-preamble :where(li.task-list-item),
|
|
1331
|
+
.block-stretch td.stretch-doc .stretch-doc-inner :where(li.task-list-item) {
|
|
1332
|
+
position: relative;
|
|
1333
|
+
}
|
|
1334
|
+
.pane--doc .doc-pane-body :where(li.task-list-item input[type="checkbox"]),
|
|
1335
|
+
.shell--stretch-rows .stretch-preamble :where(li.task-list-item input[type="checkbox"]),
|
|
1336
|
+
.block-stretch td.stretch-doc .stretch-doc-inner :where(li.task-list-item input[type="checkbox"]) {
|
|
1337
|
+
position: absolute;
|
|
1338
|
+
margin-inline-start: -1.35em;
|
|
1339
|
+
margin-top: 0.2em;
|
|
1340
|
+
}
|
|
1341
|
+
.pane--doc .doc-pane-body :where(del),
|
|
1342
|
+
.shell--stretch-rows .stretch-preamble :where(del),
|
|
1343
|
+
.block-stretch td.stretch-doc .stretch-doc-inner :where(del) {
|
|
1344
|
+
opacity: 0.82;
|
|
1345
|
+
}
|
|
1346
|
+
.pane--doc .doc-pane-body :where(section.footnotes),
|
|
1347
|
+
.shell--stretch-rows .stretch-preamble :where(section.footnotes),
|
|
1348
|
+
.block-stretch td.stretch-doc .stretch-doc-inner :where(section.footnotes) {
|
|
1349
|
+
margin-top: 1.5em;
|
|
1350
|
+
padding-top: 0.75em;
|
|
1351
|
+
border-top: 1px solid color-mix(in oklab, CanvasText 18%, Canvas);
|
|
1352
|
+
font-size: 0.92em;
|
|
1152
1353
|
}
|
|
1153
1354
|
.pane--doc .doc-pane-body .commentray-mermaid {
|
|
1154
1355
|
overflow-x: auto;
|
|
@@ -1166,6 +1367,23 @@ const CODE_BROWSER_STYLES = `
|
|
|
1166
1367
|
overflow-wrap: normal;
|
|
1167
1368
|
word-break: normal;
|
|
1168
1369
|
}
|
|
1370
|
+
#doc-pane-body .commentray-page-break {
|
|
1371
|
+
position: relative;
|
|
1372
|
+
min-height: var(--commentray-page-break-min-height, clamp(260px, 56vh, 620px));
|
|
1373
|
+
margin: 24px 0;
|
|
1374
|
+
display: flex;
|
|
1375
|
+
align-items: center;
|
|
1376
|
+
justify-content: center;
|
|
1377
|
+
pointer-events: none;
|
|
1378
|
+
}
|
|
1379
|
+
#doc-pane-body .commentray-page-break__rule {
|
|
1380
|
+
width: 100%;
|
|
1381
|
+
border-top: 1px dashed var(--border);
|
|
1382
|
+
opacity: 0.38;
|
|
1383
|
+
}
|
|
1384
|
+
#shell[data-page-breaks-enabled="false"] .commentray-page-break {
|
|
1385
|
+
display: none;
|
|
1386
|
+
}
|
|
1169
1387
|
.toolbar-angle-picker {
|
|
1170
1388
|
display: inline-flex;
|
|
1171
1389
|
align-items: center;
|
|
@@ -1385,6 +1603,19 @@ const CODE_BROWSER_STYLES = `
|
|
|
1385
1603
|
0 1px 2px color-mix(in oklab, CanvasText 12%, transparent),
|
|
1386
1604
|
0 4px 14px color-mix(in oklab, CanvasText 18%, transparent);
|
|
1387
1605
|
}
|
|
1606
|
+
.toolbar-icon-btn--source-markdown-scroll-narrow {
|
|
1607
|
+
display: none;
|
|
1608
|
+
}
|
|
1609
|
+
#source-markdown-pane-flip-scroll.toolbar-icon-btn--source-markdown-scroll-narrow.is-visible {
|
|
1610
|
+
display: inline-flex;
|
|
1611
|
+
position: fixed;
|
|
1612
|
+
top: calc(10px + env(safe-area-inset-top, 0px));
|
|
1613
|
+
left: calc(12px + env(safe-area-inset-left, 0px));
|
|
1614
|
+
z-index: 50;
|
|
1615
|
+
box-shadow:
|
|
1616
|
+
0 1px 2px color-mix(in oklab, CanvasText 12%, transparent),
|
|
1617
|
+
0 4px 14px color-mix(in oklab, CanvasText 18%, transparent);
|
|
1618
|
+
}
|
|
1388
1619
|
/** Region connector lines are not needed on the narrow single-pane layout (gutter is hidden). */
|
|
1389
1620
|
.shell:not(.shell--stretch-rows) .gutter .gutter__rays {
|
|
1390
1621
|
opacity: 0 !important;
|
|
@@ -1450,6 +1681,47 @@ const CODE_BROWSER_STYLES = `
|
|
|
1450
1681
|
color: CanvasText;
|
|
1451
1682
|
text-shadow: 0 0 2px Canvas, 0 0 3px Canvas;
|
|
1452
1683
|
}
|
|
1684
|
+
.toolbar-source-render-toggle {
|
|
1685
|
+
min-width: var(--cr-control-h);
|
|
1686
|
+
width: var(--cr-control-h);
|
|
1687
|
+
height: var(--cr-control-h);
|
|
1688
|
+
padding: 0;
|
|
1689
|
+
justify-content: center;
|
|
1690
|
+
gap: 0;
|
|
1691
|
+
}
|
|
1692
|
+
.toolbar-source-render-toggle__caption {
|
|
1693
|
+
position: absolute;
|
|
1694
|
+
width: 1px;
|
|
1695
|
+
height: 1px;
|
|
1696
|
+
padding: 0;
|
|
1697
|
+
margin: -1px;
|
|
1698
|
+
overflow: hidden;
|
|
1699
|
+
clip: rect(0, 0, 0, 0);
|
|
1700
|
+
white-space: nowrap;
|
|
1701
|
+
border: 0;
|
|
1702
|
+
}
|
|
1703
|
+
.toolbar-source-render-toggle__box {
|
|
1704
|
+
display: none;
|
|
1705
|
+
}
|
|
1706
|
+
.toolbar-source-render-toggle__face {
|
|
1707
|
+
display: inline-flex;
|
|
1708
|
+
position: relative;
|
|
1709
|
+
width: 100%;
|
|
1710
|
+
height: 100%;
|
|
1711
|
+
min-height: var(--cr-control-h);
|
|
1712
|
+
min-width: var(--cr-control-h);
|
|
1713
|
+
}
|
|
1714
|
+
.toolbar-source-render-toggle[aria-pressed="true"] .toolbar-source-render-toggle__face::after {
|
|
1715
|
+
content: "✓";
|
|
1716
|
+
position: absolute;
|
|
1717
|
+
right: 1px;
|
|
1718
|
+
bottom: 0;
|
|
1719
|
+
font-size: 11px;
|
|
1720
|
+
line-height: 1;
|
|
1721
|
+
font-weight: 800;
|
|
1722
|
+
color: CanvasText;
|
|
1723
|
+
text-shadow: 0 0 2px Canvas, 0 0 3px Canvas;
|
|
1724
|
+
}
|
|
1453
1725
|
.shell:not(.shell--stretch-rows)[data-dual-mobile-pane="code"] .pane--doc,
|
|
1454
1726
|
.shell:not(.shell--stretch-rows)[data-dual-mobile-pane="code"] .gutter {
|
|
1455
1727
|
display: none !important;
|
|
@@ -1512,11 +1784,6 @@ const CODE_BROWSER_STYLES = `
|
|
|
1512
1784
|
max-width: 100%;
|
|
1513
1785
|
}
|
|
1514
1786
|
.shell--stretch-rows .stretch-preamble img { max-width: 100%; height: auto; }
|
|
1515
|
-
.shell--stretch-rows .stretch-preamble :where(table) {
|
|
1516
|
-
width: max-content;
|
|
1517
|
-
max-width: none;
|
|
1518
|
-
border-collapse: collapse;
|
|
1519
|
-
}
|
|
1520
1787
|
.block-stretch {
|
|
1521
1788
|
width: 100%;
|
|
1522
1789
|
border-collapse: collapse;
|
|
@@ -1541,11 +1808,6 @@ const CODE_BROWSER_STYLES = `
|
|
|
1541
1808
|
overflow-x: auto;
|
|
1542
1809
|
}
|
|
1543
1810
|
.block-stretch td.stretch-doc .stretch-doc-inner img { max-width: 100%; height: auto; }
|
|
1544
|
-
.block-stretch td.stretch-doc .stretch-doc-inner :where(table) {
|
|
1545
|
-
width: max-content;
|
|
1546
|
-
max-width: none;
|
|
1547
|
-
border-collapse: collapse;
|
|
1548
|
-
}
|
|
1549
1811
|
.block-stretch td.stretch-doc .stretch-doc-inner .commentray-mermaid {
|
|
1550
1812
|
overflow-x: auto;
|
|
1551
1813
|
max-width: 100%;
|
|
@@ -1660,16 +1922,20 @@ ${CODE_BROWSER_STYLES}
|
|
|
1660
1922
|
<span class="toolbar-wrap-lines__caption">Wrap lines</span>
|
|
1661
1923
|
</label>
|
|
1662
1924
|
${dualFlipControlHtml}
|
|
1925
|
+
${p.sourceMarkdownToggleHtml}
|
|
1663
1926
|
${p.toolbarDocHubHtml}
|
|
1664
1927
|
${p.relatedNavHtml}
|
|
1665
1928
|
</div>
|
|
1666
1929
|
<div class="toolbar__primary-trail">
|
|
1667
1930
|
${p.toolbarEndHtml}
|
|
1931
|
+
${TOOLBAR_SHARE_LINK_HTML}
|
|
1932
|
+
${TOOLBAR_HELP_TOUR_HTML}
|
|
1668
1933
|
${TOOLBAR_COLOR_THEME_HTML}
|
|
1669
1934
|
</div>
|
|
1670
1935
|
</div>
|
|
1671
1936
|
</header>
|
|
1672
1937
|
${dualFlipScrollAffordanceHtml}
|
|
1938
|
+
${p.sourceMarkdownFlipScrollAffordanceHtml}
|
|
1673
1939
|
<header class="app__chrome" role="region" aria-label="Search">
|
|
1674
1940
|
<div class="chrome__search-row">
|
|
1675
1941
|
<label class="chrome__search-label" for="search-q" aria-label="Search" title="Search"><span class="chrome__search-label__caption nav-rail__search-label">Search</span><span class="chrome__search-label__glyph" aria-hidden="true">${CHROME_ICON_SEARCH_SVG}</span></label>
|
|
@@ -1679,7 +1945,7 @@ ${TOOLBAR_COLOR_THEME_HTML}
|
|
|
1679
1945
|
<div class="search-results" id="search-results" hidden aria-live="polite"></div>
|
|
1680
1946
|
</header>
|
|
1681
1947
|
<main id="main-content" class="app__main" tabindex="-1">
|
|
1682
|
-
<div class="${shellClass}" id="shell" data-layout="${p.layout}"${p.layout === "dual" ? ' data-dual-mobile-pane="doc"' : ""} 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.shellPairDocDataAttr}>
|
|
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}>
|
|
1683
1949
|
${p.shellInner}
|
|
1684
1950
|
</div>
|
|
1685
1951
|
</main>
|
|
@@ -1693,10 +1959,53 @@ ${loadCodeBrowserClientBundle()}
|
|
|
1693
1959
|
</body>
|
|
1694
1960
|
</html>`;
|
|
1695
1961
|
}
|
|
1962
|
+
function firstNonEmpty(values) {
|
|
1963
|
+
return values.find((v) => v.trim().length > 0);
|
|
1964
|
+
}
|
|
1965
|
+
function resolveMultiAngleDefaultSelection(args) {
|
|
1966
|
+
const { multi, defaultId, opts, builtAngles } = args;
|
|
1967
|
+
let defaultMarkdown = opts.commentrayMarkdown;
|
|
1968
|
+
let defaultScrollB64 = "";
|
|
1969
|
+
let defaultPathSearch = (opts.commentrayPathForSearch ?? "").trim();
|
|
1970
|
+
let defaultGh = opts.commentrayOnGithubUrl;
|
|
1971
|
+
let defaultStaticBrowse = (opts.commentrayStaticBrowseUrl ?? "").trim();
|
|
1972
|
+
let defaultPaneHtml = "";
|
|
1973
|
+
for (const b of builtAngles) {
|
|
1974
|
+
if (b.spec.id !== defaultId)
|
|
1975
|
+
continue;
|
|
1976
|
+
defaultMarkdown = b.spec.markdown;
|
|
1977
|
+
defaultScrollB64 = b.scrollB64;
|
|
1978
|
+
defaultPathSearch = b.spec.commentrayPathRel.trim();
|
|
1979
|
+
defaultGh = b.spec.commentrayOnGithubUrl;
|
|
1980
|
+
defaultStaticBrowse = (b.spec.staticBrowseUrl ?? "").trim();
|
|
1981
|
+
defaultPaneHtml = b.commentrayHtml;
|
|
1982
|
+
break;
|
|
1983
|
+
}
|
|
1984
|
+
if (defaultStaticBrowse.length === 0) {
|
|
1985
|
+
defaultStaticBrowse =
|
|
1986
|
+
firstNonEmpty(multi.angles.map((a) => (a.staticBrowseUrl ?? "").trim())) ?? "";
|
|
1987
|
+
}
|
|
1988
|
+
if ((defaultGh ?? "").trim().length === 0) {
|
|
1989
|
+
defaultGh = firstNonEmpty(multi.angles.map((a) => (a.commentrayOnGithubUrl ?? "").trim()));
|
|
1990
|
+
}
|
|
1991
|
+
return {
|
|
1992
|
+
defaultMarkdown,
|
|
1993
|
+
defaultScrollB64,
|
|
1994
|
+
defaultPathSearch,
|
|
1995
|
+
defaultGh,
|
|
1996
|
+
defaultStaticBrowse,
|
|
1997
|
+
defaultPaneHtml,
|
|
1998
|
+
};
|
|
1999
|
+
}
|
|
1696
2000
|
async function multiAngleJsonRowAndDocHtml(opts, spec) {
|
|
1697
2001
|
const rows = spec.blockStretchRows;
|
|
1698
|
-
const
|
|
1699
|
-
|
|
2002
|
+
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
|
+
const links = rows !== undefined && rowsPathOk
|
|
2008
|
+
? buildBlockScrollLinks(rows.index, rows.sourceRelative, angleCrNorm, spec.markdown, opts.code)
|
|
1700
2009
|
: [];
|
|
1701
2010
|
const mdForDoc = injectCommentrayDocAnchors(spec.markdown, links.length > 0 ? links : undefined);
|
|
1702
2011
|
const scrollB64 = links.length > 0 ? Buffer.from(JSON.stringify(links), "utf8").toString("base64") : "";
|
|
@@ -1723,29 +2032,24 @@ async function buildMultiAngleDualPaneShell(opts, multi) {
|
|
|
1723
2032
|
? multi.defaultAngleId
|
|
1724
2033
|
: (multi.angles[0]?.id ?? "main");
|
|
1725
2034
|
const jsonAngles = [];
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
2035
|
+
const builtAngles = [];
|
|
2036
|
+
const sourceMarkdownEnabled = isMarkdownLikeSource(opts);
|
|
2037
|
+
const sourceMdForPane = sourceMarkdownEnabled ? injectSourceMarkdownAnchors(opts.code) : "";
|
|
2038
|
+
const sourcePaneUrls = sourcePaneOutputUrls(opts);
|
|
2039
|
+
const [codeHtml, sourceMarkdownPaneHtml] = await Promise.all([
|
|
2040
|
+
renderHighlightedCodeLineRows(opts.code, opts.language),
|
|
2041
|
+
sourceMarkdownEnabled
|
|
2042
|
+
? renderMarkdownToHtml(sourceMdForPane, {
|
|
2043
|
+
commentrayOutputUrls: sourcePaneUrls,
|
|
2044
|
+
})
|
|
2045
|
+
: Promise.resolve(""),
|
|
2046
|
+
]);
|
|
1733
2047
|
for (const spec of multi.angles) {
|
|
1734
2048
|
const { jsonRow, commentrayHtml, scrollB64 } = await multiAngleJsonRowAndDocHtml(opts, spec);
|
|
1735
|
-
|
|
1736
|
-
defaultMarkdown = spec.markdown;
|
|
1737
|
-
defaultScrollB64 = scrollB64;
|
|
1738
|
-
defaultPathSearch = spec.commentrayPathRel.trim();
|
|
1739
|
-
defaultGh = spec.commentrayOnGithubUrl;
|
|
1740
|
-
{
|
|
1741
|
-
const sb = (spec.staticBrowseUrl ?? "").trim();
|
|
1742
|
-
if (sb.length > 0)
|
|
1743
|
-
defaultStaticBrowse = sb;
|
|
1744
|
-
}
|
|
1745
|
-
defaultPaneHtml = commentrayHtml;
|
|
1746
|
-
}
|
|
2049
|
+
builtAngles.push({ spec, commentrayHtml, scrollB64 });
|
|
1747
2050
|
jsonAngles.push(jsonRow);
|
|
1748
2051
|
}
|
|
2052
|
+
const { defaultMarkdown, defaultScrollB64, defaultPathSearch, defaultGh, defaultStaticBrowse, defaultPaneHtml, } = resolveMultiAngleDefaultSelection({ multi, defaultId, opts, builtAngles });
|
|
1749
2053
|
const selOpts = multi.angles
|
|
1750
2054
|
.map((a) => {
|
|
1751
2055
|
const lab = escapeHtml(a.title?.trim() || a.id);
|
|
@@ -1754,7 +2058,7 @@ async function buildMultiAngleDualPaneShell(opts, multi) {
|
|
|
1754
2058
|
.join("");
|
|
1755
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>`;
|
|
1756
2060
|
const pairHtml = renderShellPairContextHtml(opts.filePath, defaultPathSearch);
|
|
1757
|
-
const shellInner = wrapDualShellInner(pairHtml, dualPanePanesInnerHtml(codeHtml, defaultPaneHtml));
|
|
2061
|
+
const shellInner = wrapDualShellInner(pairHtml, dualPanePanesInnerHtml(codeHtml, defaultPaneHtml, sourceMarkdownPaneHtml));
|
|
1758
2062
|
const payloadObj = { defaultAngleId: defaultId, angles: jsonAngles };
|
|
1759
2063
|
const multiAnglePayloadB64 = Buffer.from(JSON.stringify(payloadObj), "utf8").toString("base64");
|
|
1760
2064
|
return {
|
|
@@ -1768,6 +2072,8 @@ async function buildMultiAngleDualPaneShell(opts, multi) {
|
|
|
1768
2072
|
},
|
|
1769
2073
|
angleSelectHtml,
|
|
1770
2074
|
multiAnglePayloadB64,
|
|
2075
|
+
sourceMarkdownToggleEnabled: sourceMarkdownEnabled,
|
|
2076
|
+
sourcePaneDefaultMode: sourceMarkdownEnabled ? "rendered-markdown" : "source",
|
|
1771
2077
|
};
|
|
1772
2078
|
}
|
|
1773
2079
|
async function buildCodeBrowserShell(opts, layoutPref) {
|
|
@@ -1785,6 +2091,8 @@ async function buildCodeBrowserShell(opts, layoutPref) {
|
|
|
1785
2091
|
scrollBlockLinksB64: ms.scrollBlockLinksB64,
|
|
1786
2092
|
angleSelectHtml: built.angleSelectHtml,
|
|
1787
2093
|
multiAnglePayloadB64: built.multiAnglePayloadB64,
|
|
2094
|
+
sourceMarkdownToggleEnabled: built.sourceMarkdownToggleEnabled,
|
|
2095
|
+
sourcePaneDefaultMode: built.sourcePaneDefaultMode,
|
|
1788
2096
|
multiShell: ms,
|
|
1789
2097
|
};
|
|
1790
2098
|
}
|
|
@@ -1811,14 +2119,31 @@ async function buildCodeBrowserShell(opts, layoutPref) {
|
|
|
1811
2119
|
if (links.length > 0) {
|
|
1812
2120
|
scrollBlockLinksB64 = Buffer.from(JSON.stringify(links), "utf8").toString("base64");
|
|
1813
2121
|
}
|
|
1814
|
-
const
|
|
2122
|
+
const sourceMarkdownEnabled = isMarkdownLikeSource(opts);
|
|
2123
|
+
const sourceMdForPane = sourceMarkdownEnabled ? injectSourceMarkdownAnchors(opts.code) : "";
|
|
2124
|
+
const sourcePaneUrls = sourcePaneOutputUrls(opts);
|
|
2125
|
+
const [codeHtml, commentrayHtml, sourceMarkdownPaneHtml] = await Promise.all([
|
|
1815
2126
|
renderHighlightedCodeLineRows(opts.code, opts.language),
|
|
1816
2127
|
renderMarkdownToHtml(mdForDoc, {
|
|
1817
2128
|
commentrayOutputUrls: opts.commentrayOutputUrls,
|
|
1818
2129
|
}),
|
|
2130
|
+
sourceMarkdownEnabled
|
|
2131
|
+
? renderMarkdownToHtml(sourceMdForPane, {
|
|
2132
|
+
commentrayOutputUrls: sourcePaneUrls,
|
|
2133
|
+
})
|
|
2134
|
+
: Promise.resolve(""),
|
|
1819
2135
|
]);
|
|
1820
2136
|
const pairHtml = renderShellPairContextHtml(opts.filePath, (opts.commentrayPathForSearch ?? "").trim());
|
|
1821
|
-
shellInner = wrapDualShellInner(pairHtml, dualPanePanesInnerHtml(codeHtml, commentrayHtml));
|
|
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
|
+
};
|
|
1822
2147
|
}
|
|
1823
2148
|
return {
|
|
1824
2149
|
layout,
|
|
@@ -1826,6 +2151,8 @@ async function buildCodeBrowserShell(opts, layoutPref) {
|
|
|
1826
2151
|
scrollBlockLinksB64,
|
|
1827
2152
|
angleSelectHtml: "",
|
|
1828
2153
|
multiAnglePayloadB64: "",
|
|
2154
|
+
sourceMarkdownToggleEnabled: false,
|
|
2155
|
+
sourcePaneDefaultMode: "source",
|
|
1829
2156
|
};
|
|
1830
2157
|
}
|
|
1831
2158
|
function searchChromeFromOptions(opts, commentrayPathOverride) {
|
|
@@ -1856,6 +2183,23 @@ function toolbarCommentrayGithubFromShell(shell, opts) {
|
|
|
1856
2183
|
function rawMdB64FromShell(shell, opts) {
|
|
1857
2184
|
return (shell.multiShell?.rawMdB64 ?? Buffer.from(opts.commentrayMarkdown, "utf8").toString("base64"));
|
|
1858
2185
|
}
|
|
2186
|
+
function currentPairCommentrayPathRel(shell, opts) {
|
|
2187
|
+
return (shell.multiShell?.commentrayPathForSearch ??
|
|
2188
|
+
opts.commentrayPathForSearch ??
|
|
2189
|
+
opts.blockStretchRows?.commentrayPathRel ??
|
|
2190
|
+
"").trim();
|
|
2191
|
+
}
|
|
2192
|
+
/**
|
|
2193
|
+
* Repo-relative source + companion Markdown paths for matching the current page to nav pairs
|
|
2194
|
+
* (see `code-browser-client.ts` documented-files tree).
|
|
2195
|
+
*/
|
|
2196
|
+
function shellPairIdentityDataAttrs(shell, opts) {
|
|
2197
|
+
const src = normPosixPath(opts.filePath ?? "");
|
|
2198
|
+
const cr = normPosixPath(currentPairCommentrayPathRel(shell, opts));
|
|
2199
|
+
if (src.length === 0 || cr.length === 0)
|
|
2200
|
+
return "";
|
|
2201
|
+
return ` data-commentray-pair-source-path="${escapeHtml(src)}" data-commentray-pair-commentray-path="${escapeHtml(cr)}"`;
|
|
2202
|
+
}
|
|
1859
2203
|
/** Canonical doc target for static validation: same-site `./browse/…` when present, else GitHub blob. */
|
|
1860
2204
|
function shellPairDocDataAttr(shell, opts) {
|
|
1861
2205
|
if (shell.layout !== "dual")
|
|
@@ -1898,6 +2242,7 @@ export async function renderCodeBrowserHtml(opts) {
|
|
|
1898
2242
|
builtAt,
|
|
1899
2243
|
toolHomeUrl: opts.toolHomeUrl,
|
|
1900
2244
|
commentrayRenderSemver: renderSemver,
|
|
2245
|
+
pagesBuildCommitSha: normalizePagesBuildCommitSha(opts.pagesBuildCommitSha),
|
|
1901
2246
|
});
|
|
1902
2247
|
const { hljsLight, hljsDark } = hljsStylesheetThemes(opts.hljsTheme);
|
|
1903
2248
|
const mermaidScript = mermaidRuntimeScriptHtml(opts.includeMermaidRuntime);
|
|
@@ -1915,11 +2260,15 @@ export async function renderCodeBrowserHtml(opts) {
|
|
|
1915
2260
|
const shellDocumentedPairsAttr = shellDocumentedPairsAttrFromOptions(opts);
|
|
1916
2261
|
const shellSearchAttrs = shellSearchAttrsWithNavJson(shellSearchAttrsBase, opts.documentedNavJsonUrl);
|
|
1917
2262
|
const pairDocDataAttr = shellPairDocDataAttr(shell, opts);
|
|
2263
|
+
const pairIdentityDataAttrs = shellPairIdentityDataAttrs(shell, opts);
|
|
2264
|
+
const sourceMarkdownToggles = sourceMarkdownToggleControlsHtml(shell.sourceMarkdownToggleEnabled);
|
|
2265
|
+
const sourcePaneModeAttr = ` data-source-pane-mode="${shell.sourcePaneDefaultMode}"`;
|
|
1918
2266
|
return buildCodeBrowserPageHtml({
|
|
1919
2267
|
title,
|
|
1920
2268
|
metaDescriptionHtml,
|
|
1921
2269
|
generatorMetaHtml,
|
|
1922
2270
|
toolbarSiteHubHtml,
|
|
2271
|
+
shellPairIdentityDataAttrs: pairIdentityDataAttrs,
|
|
1923
2272
|
shellPairDocDataAttr: pairDocDataAttr,
|
|
1924
2273
|
angleSelectHtml: shell.angleSelectHtml,
|
|
1925
2274
|
toolbarDocHubHtml,
|
|
@@ -1939,6 +2288,9 @@ export async function renderCodeBrowserHtml(opts) {
|
|
|
1939
2288
|
searchPlaceholder,
|
|
1940
2289
|
shellSearchAttrs,
|
|
1941
2290
|
multiAngleScriptBlock: shell.multiAnglePayloadB64,
|
|
2291
|
+
sourceMarkdownToggleHtml: sourceMarkdownToggles.sourceMarkdownToggleHtml,
|
|
2292
|
+
sourceMarkdownFlipScrollAffordanceHtml: sourceMarkdownToggles.sourceMarkdownFlipScrollAffordanceHtml,
|
|
2293
|
+
sourcePaneModeAttr,
|
|
1942
2294
|
});
|
|
1943
2295
|
}
|
|
1944
2296
|
//# sourceMappingURL=code-browser.js.map
|