@commentray/render 0.0.1 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/dist/block-stretch-layout.d.ts +30 -0
  2. package/dist/block-stretch-layout.d.ts.map +1 -0
  3. package/dist/block-stretch-layout.js +116 -0
  4. package/dist/block-stretch-layout.js.map +1 -0
  5. package/dist/build-commentray-nav-search.d.ts +52 -0
  6. package/dist/build-commentray-nav-search.d.ts.map +1 -0
  7. package/dist/build-commentray-nav-search.js +79 -0
  8. package/dist/build-commentray-nav-search.js.map +1 -0
  9. package/dist/code-browser-client.bundle.js +7 -5
  10. package/dist/code-browser-client.js +428 -69
  11. package/dist/code-browser-client.js.map +1 -1
  12. package/dist/code-browser-embedded-payload.d.ts +10 -0
  13. package/dist/code-browser-embedded-payload.d.ts.map +1 -0
  14. package/dist/code-browser-embedded-payload.js +18 -0
  15. package/dist/code-browser-embedded-payload.js.map +1 -0
  16. package/dist/code-browser-encoding.d.ts +9 -0
  17. package/dist/code-browser-encoding.d.ts.map +1 -0
  18. package/dist/code-browser-encoding.js +24 -0
  19. package/dist/code-browser-encoding.js.map +1 -0
  20. package/dist/code-browser-scroll-sync.d.ts +13 -0
  21. package/dist/code-browser-scroll-sync.d.ts.map +1 -0
  22. package/dist/code-browser-scroll-sync.js +15 -0
  23. package/dist/code-browser-scroll-sync.js.map +1 -0
  24. package/dist/code-browser-web-storage.d.ts +7 -0
  25. package/dist/code-browser-web-storage.d.ts.map +1 -0
  26. package/dist/code-browser-web-storage.js +21 -0
  27. package/dist/code-browser-web-storage.js.map +1 -0
  28. package/dist/code-browser.d.ts +76 -0
  29. package/dist/code-browser.d.ts.map +1 -1
  30. package/dist/code-browser.js +400 -39
  31. package/dist/code-browser.js.map +1 -1
  32. package/dist/index.d.ts +4 -0
  33. package/dist/index.d.ts.map +1 -1
  34. package/dist/index.js +2 -0
  35. package/dist/index.js.map +1 -1
  36. package/dist/markdown-pipeline.d.ts +23 -1
  37. package/dist/markdown-pipeline.d.ts.map +1 -1
  38. package/dist/markdown-pipeline.js +142 -2
  39. package/dist/markdown-pipeline.js.map +1 -1
  40. package/dist/mermaid-runtime-html.d.ts +7 -0
  41. package/dist/mermaid-runtime-html.d.ts.map +1 -0
  42. package/dist/mermaid-runtime-html.js +26 -0
  43. package/dist/mermaid-runtime-html.js.map +1 -0
  44. package/dist/package-version.d.ts +5 -0
  45. package/dist/package-version.d.ts.map +1 -0
  46. package/dist/package-version.js +14 -0
  47. package/dist/package-version.js.map +1 -0
  48. package/dist/side-by-side.d.ts +5 -0
  49. package/dist/side-by-side.d.ts.map +1 -1
  50. package/dist/side-by-side.js +11 -9
  51. package/dist/side-by-side.js.map +1 -1
  52. package/package.json +6 -4
@@ -1,4 +1,6 @@
1
+ import path from "node:path";
1
2
  import rehypeHighlight from "rehype-highlight";
3
+ import rehypeRaw from "rehype-raw";
2
4
  import rehypeSanitize, { defaultSchema } from "rehype-sanitize";
3
5
  import rehypeStringify from "rehype-stringify";
4
6
  import remarkGfm from "remark-gfm";
@@ -7,6 +9,117 @@ import remarkRehype from "remark-rehype";
7
9
  import { unified } from "unified";
8
10
  import { visit } from "unist-util-visit";
9
11
  import { escapeHtml } from "./html-utils.js";
12
+ function escapeRegExp(s) {
13
+ return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
14
+ }
15
+ function stripUrlQueryAndHash(s) {
16
+ let end = s.length;
17
+ const q = s.indexOf("?");
18
+ const h = s.indexOf("#");
19
+ if (q >= 0)
20
+ end = Math.min(end, q);
21
+ if (h >= 0)
22
+ end = Math.min(end, h);
23
+ return s.slice(0, end);
24
+ }
25
+ function tryExtractRepoFilePathFromGithubUrl(url, owner, repo) {
26
+ const re = new RegExp(`^https://github\\.com/${escapeRegExp(owner)}/${escapeRegExp(repo)}/(?:blob|tree)/[^/]+/(.+)$`, "i");
27
+ const m = re.exec(url.trim());
28
+ if (!m)
29
+ return null;
30
+ let tail = m[1];
31
+ try {
32
+ tail = decodeURIComponent(tail);
33
+ }
34
+ catch {
35
+ // keep encoded path
36
+ }
37
+ return stripUrlQueryAndHash(tail);
38
+ }
39
+ function remarkGithubBlobToRepoPaths(opts) {
40
+ const { owner, repo } = opts;
41
+ return (tree) => {
42
+ const rewrite = (url) => {
43
+ const next = tryExtractRepoFilePathFromGithubUrl(url, owner, repo);
44
+ if (!next)
45
+ return null;
46
+ const posix = next.replace(/\\/g, "/").replace(/^\/+/, "");
47
+ return posix ? `/${posix}` : null;
48
+ };
49
+ visit(tree, "link", (node) => {
50
+ const next = rewrite(node.url);
51
+ if (next)
52
+ node.url = next;
53
+ });
54
+ visit(tree, "image", (node) => {
55
+ const next = rewrite(node.url);
56
+ if (next)
57
+ node.url = next;
58
+ });
59
+ visit(tree, "definition", (node) => {
60
+ const next = rewrite(node.url);
61
+ if (next)
62
+ node.url = next;
63
+ });
64
+ };
65
+ }
66
+ function posixHref(fsPath) {
67
+ return fsPath.split(path.sep).join("/");
68
+ }
69
+ function decodeUrlPath(s) {
70
+ try {
71
+ return decodeURIComponent(s);
72
+ }
73
+ catch {
74
+ return s;
75
+ }
76
+ }
77
+ function rehypeCommentrayOutputUrls(ctx) {
78
+ const repoRoot = path.resolve(ctx.repoRootAbs);
79
+ const htmlDir = path.dirname(path.resolve(ctx.htmlOutputFileAbs));
80
+ const baseDir = path.resolve(ctx.markdownUrlBaseDirAbs);
81
+ function resolveTargetAbs(raw) {
82
+ const t = raw.trim();
83
+ if (!t || t.startsWith("#"))
84
+ return null;
85
+ if (/^[a-zA-Z][a-zA-Z0-9+.-]*:/i.test(t))
86
+ return null;
87
+ if (t.startsWith("//"))
88
+ return null;
89
+ let resolved;
90
+ if (t.startsWith("/")) {
91
+ const rest = decodeUrlPath(t.replace(/^\/+/, ""));
92
+ const segments = rest.split("/").filter((s) => s && s !== "." && s !== "..");
93
+ resolved = path.normalize(path.join(repoRoot, ...segments));
94
+ }
95
+ else {
96
+ const decoded = decodeUrlPath(t);
97
+ resolved = path.normalize(path.resolve(baseDir, decoded));
98
+ }
99
+ const relToRepo = path.relative(repoRoot, resolved);
100
+ if (relToRepo.startsWith("..") || path.isAbsolute(relToRepo))
101
+ return null;
102
+ const out = path.relative(htmlDir, resolved);
103
+ if (path.isAbsolute(out))
104
+ return null;
105
+ return posixHref(out);
106
+ }
107
+ return (tree) => {
108
+ visit(tree, "element", (node) => {
109
+ if (node.tagName !== "a" && node.tagName !== "img")
110
+ return;
111
+ const key = node.tagName === "a" ? "href" : "src";
112
+ const raw = node.properties?.[key];
113
+ if (typeof raw !== "string")
114
+ return;
115
+ const next = resolveTargetAbs(raw);
116
+ if (next == null)
117
+ return;
118
+ node.properties ??= {};
119
+ node.properties[key] = next;
120
+ });
121
+ };
122
+ }
10
123
  function remarkMermaidPlaceholders() {
11
124
  return (tree) => {
12
125
  visit(tree, "code", (node, index, parent) => {
@@ -22,20 +135,47 @@ function remarkMermaidPlaceholders() {
22
135
  };
23
136
  }
24
137
  const sanitizeSchema = structuredClone(defaultSchema);
138
+ /** Companion Markdown is repo-controlled; keep `id` unprefixed so `commentray-block-*` anchors are stable. */
139
+ sanitizeSchema.clobber = ["ariaDescribedBy", "ariaLabelledBy", "name"];
25
140
  sanitizeSchema.attributes = {
26
141
  ...sanitizeSchema.attributes,
27
142
  code: [...(sanitizeSchema.attributes?.code ?? []), "className"],
28
143
  pre: [...(sanitizeSchema.attributes?.pre ?? []), "className"],
29
144
  span: [...(sanitizeSchema.attributes?.span ?? []), "className"],
30
- div: ["className"],
145
+ div: [
146
+ ...(sanitizeSchema.attributes?.div ?? []),
147
+ "className",
148
+ "id",
149
+ "ariaHidden",
150
+ /** Block scroll sync markers from `injectCommentrayBlockAnchors` (hast property names). */
151
+ "dataSourceStart",
152
+ "dataCommentrayLine",
153
+ ],
31
154
  };
32
- export async function renderMarkdownToHtml(markdown) {
155
+ export async function renderMarkdownToHtml(markdown, options) {
156
+ const outUrls = options?.commentrayOutputUrls;
33
157
  const file = await unified()
34
158
  .use(remarkParse)
35
159
  .use(remarkGfm)
160
+ .use(function remarkGithubBlobMaybe() {
161
+ return (tree) => {
162
+ const gh = outUrls?.githubBlobRepo;
163
+ if (!gh)
164
+ return;
165
+ remarkGithubBlobToRepoPaths({ owner: gh.owner, repo: gh.repo })(tree);
166
+ };
167
+ })
36
168
  .use(remarkMermaidPlaceholders)
37
169
  .use(remarkRehype, { allowDangerousHtml: true })
170
+ .use(rehypeRaw)
38
171
  .use(rehypeSanitize, sanitizeSchema)
172
+ .use(function rehypeOutputUrlsMaybe() {
173
+ return (tree) => {
174
+ if (!outUrls)
175
+ return;
176
+ rehypeCommentrayOutputUrls(outUrls)(tree);
177
+ };
178
+ })
39
179
  .use(rehypeHighlight)
40
180
  .use(rehypeStringify)
41
181
  .process(markdown);
@@ -1 +1 @@
1
- {"version":3,"file":"markdown-pipeline.js","sourceRoot":"","sources":["../src/markdown-pipeline.ts"],"names":[],"mappings":"AACA,OAAO,eAAe,MAAM,kBAAkB,CAAC;AAC/C,OAAO,cAAc,EAAE,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChE,OAAO,eAAe,MAAM,kBAAkB,CAAC;AAC/C,OAAO,SAAS,MAAM,YAAY,CAAC;AACnC,OAAO,WAAW,MAAM,cAAc,CAAC;AACvC,OAAO,YAAY,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAEzC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,SAAS,yBAAyB;IAChC,OAAO,CAAC,IAAU,EAAE,EAAE;QACpB,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,IAAU,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;YAChD,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,MAAM,KAAK,SAAS,IAAI,KAAK,KAAK,SAAS;gBAAE,OAAO;YACnF,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;YACzB,MAAM,IAAI,GAAS;gBACjB,IAAI,EAAE,MAAM;gBACZ,KAAK,EAAE,8DAA8D,UAAU,CAC7E,KAAK,CACN,qBAAqB;aACvB,CAAC;YACF,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC;QAChC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,cAAc,GAAG,eAAe,CAAC,aAAa,CAAC,CAAC;AAEtD,cAAc,CAAC,UAAU,GAAG;IAC1B,GAAG,cAAc,CAAC,UAAU;IAC5B,IAAI,EAAE,CAAC,GAAG,CAAC,cAAc,CAAC,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,EAAE,WAAW,CAAC;IAC/D,GAAG,EAAE,CAAC,GAAG,CAAC,cAAc,CAAC,UAAU,EAAE,GAAG,IAAI,EAAE,CAAC,EAAE,WAAW,CAAC;IAC7D,IAAI,EAAE,CAAC,GAAG,CAAC,cAAc,CAAC,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,EAAE,WAAW,CAAC;IAC/D,GAAG,EAAE,CAAC,WAAW,CAAC;CACnB,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,QAAgB;IACzD,MAAM,IAAI,GAAG,MAAM,OAAO,EAAE;SACzB,GAAG,CAAC,WAAW,CAAC;SAChB,GAAG,CAAC,SAAS,CAAC;SACd,GAAG,CAAC,yBAAyB,CAAC;SAC9B,GAAG,CAAC,YAAY,EAAE,EAAE,kBAAkB,EAAE,IAAI,EAAE,CAAC;SAC/C,GAAG,CAAC,cAAc,EAAE,cAAc,CAAC;SACnC,GAAG,CAAC,eAAe,CAAC;SACpB,GAAG,CAAC,eAAe,CAAC;SACpB,OAAO,CAAC,QAAQ,CAAC,CAAC;IACrB,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC;AACtB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,aAAqB;IAC1D,OAAO,oBAAoB,CAAC,aAAa,CAAC,CAAC;AAC7C,CAAC"}
1
+ {"version":3,"file":"markdown-pipeline.js","sourceRoot":"","sources":["../src/markdown-pipeline.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAI7B,OAAO,eAAe,MAAM,kBAAkB,CAAC;AAC/C,OAAO,SAAS,MAAM,YAAY,CAAC;AACnC,OAAO,cAAc,EAAE,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChE,OAAO,eAAe,MAAM,kBAAkB,CAAC;AAC/C,OAAO,SAAS,MAAM,YAAY,CAAC;AACnC,OAAO,WAAW,MAAM,cAAc,CAAC;AACvC,OAAO,YAAY,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAEzC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAuB7C,SAAS,YAAY,CAAC,CAAS;IAC7B,OAAO,CAAC,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;AAClD,CAAC;AAED,SAAS,oBAAoB,CAAC,CAAS;IACrC,IAAI,GAAG,GAAG,CAAC,CAAC,MAAM,CAAC;IACnB,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACzB,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACzB,IAAI,CAAC,IAAI,CAAC;QAAE,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;IACnC,IAAI,CAAC,IAAI,CAAC;QAAE,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;IACnC,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AACzB,CAAC;AAED,SAAS,mCAAmC,CAC1C,GAAW,EACX,KAAa,EACb,IAAY;IAEZ,MAAM,EAAE,GAAG,IAAI,MAAM,CACnB,yBAAyB,YAAY,CAAC,KAAK,CAAC,IAAI,YAAY,CAAC,IAAI,CAAC,4BAA4B,EAC9F,GAAG,CACJ,CAAC;IACF,MAAM,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;IAC9B,IAAI,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IACpB,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAChB,IAAI,CAAC;QACH,IAAI,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC;IAClC,CAAC;IAAC,MAAM,CAAC;QACP,oBAAoB;IACtB,CAAC;IACD,OAAO,oBAAoB,CAAC,IAAI,CAAC,CAAC;AACpC,CAAC;AAED,SAAS,2BAA2B,CAAC,IAAqC;IACxE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC;IAC7B,OAAO,CAAC,IAAe,EAAE,EAAE;QACzB,MAAM,OAAO,GAAG,CAAC,GAAW,EAAiB,EAAE;YAC7C,MAAM,IAAI,GAAG,mCAAmC,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;YACnE,IAAI,CAAC,IAAI;gBAAE,OAAO,IAAI,CAAC;YACvB,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;YAC3D,OAAO,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;QACpC,CAAC,CAAC;QACF,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,IAAU,EAAE,EAAE;YACjC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAC/B,IAAI,IAAI;gBAAE,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC;QAC5B,CAAC,CAAC,CAAC;QACH,KAAK,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC,IAAW,EAAE,EAAE;YACnC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAC/B,IAAI,IAAI;gBAAE,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC;QAC5B,CAAC,CAAC,CAAC;QACH,KAAK,CAAC,IAAI,EAAE,YAAY,EAAE,CAAC,IAAgB,EAAE,EAAE;YAC7C,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAC/B,IAAI,IAAI;gBAAE,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC;QAC5B,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC;AAED,SAAS,SAAS,CAAC,MAAc;IAC/B,OAAO,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC1C,CAAC;AAED,SAAS,aAAa,CAAC,CAAS;IAC9B,IAAI,CAAC;QACH,OAAO,kBAAkB,CAAC,CAAC,CAAC,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,CAAC;IACX,CAAC;AACH,CAAC;AAED,SAAS,0BAA0B,CAAC,GAA+B;IACjE,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IAC/C,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC;IAClE,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC;IAExD,SAAS,gBAAgB,CAAC,GAAW;QACnC,MAAM,CAAC,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;QACrB,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,OAAO,IAAI,CAAC;QACzC,IAAI,4BAA4B,CAAC,IAAI,CAAC,CAAC,CAAC;YAAE,OAAO,IAAI,CAAC;QACtD,IAAI,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC;QAEpC,IAAI,QAAgB,CAAC;QACrB,IAAI,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YACtB,MAAM,IAAI,GAAG,aAAa,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC;YAClD,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC;YAC7E,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC;QAC9D,CAAC;aAAM,CAAC;YACN,MAAM,OAAO,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC;YACjC,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;QAC5D,CAAC;QAED,MAAM,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QACpD,IAAI,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC;YAAE,OAAO,IAAI,CAAC;QAE1E,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QAC7C,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,OAAO,IAAI,CAAC;QAEtC,OAAO,SAAS,CAAC,GAAG,CAAC,CAAC;IACxB,CAAC;IAED,OAAO,CAAC,IAAc,EAAE,EAAE;QACxB,KAAK,CAAC,IAAI,EAAE,SAAS,EAAE,CAAC,IAAa,EAAE,EAAE;YACvC,IAAI,IAAI,CAAC,OAAO,KAAK,GAAG,IAAI,IAAI,CAAC,OAAO,KAAK,KAAK;gBAAE,OAAO;YAC3D,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,KAAK,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC;YAClD,MAAM,GAAG,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC,GAAG,CAAC,CAAC;YACnC,IAAI,OAAO,GAAG,KAAK,QAAQ;gBAAE,OAAO;YACpC,MAAM,IAAI,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC;YACnC,IAAI,IAAI,IAAI,IAAI;gBAAE,OAAO;YACzB,IAAI,CAAC,UAAU,KAAK,EAAE,CAAC;YACvB,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;QAC9B,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC;AAED,SAAS,yBAAyB;IAChC,OAAO,CAAC,IAAe,EAAE,EAAE;QACzB,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,IAAU,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;YAChD,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,MAAM,KAAK,SAAS,IAAI,KAAK,KAAK,SAAS;gBAAE,OAAO;YACnF,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;YACzB,MAAM,IAAI,GAAS;gBACjB,IAAI,EAAE,MAAM;gBACZ,KAAK,EAAE,8DAA8D,UAAU,CAC7E,KAAK,CACN,qBAAqB;aACvB,CAAC;YACF,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC;QAChC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,cAAc,GAAG,eAAe,CAAC,aAAa,CAAC,CAAC;AAEtD,8GAA8G;AAC9G,cAAc,CAAC,OAAO,GAAG,CAAC,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,CAAC,CAAC;AAEvE,cAAc,CAAC,UAAU,GAAG;IAC1B,GAAG,cAAc,CAAC,UAAU;IAC5B,IAAI,EAAE,CAAC,GAAG,CAAC,cAAc,CAAC,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,EAAE,WAAW,CAAC;IAC/D,GAAG,EAAE,CAAC,GAAG,CAAC,cAAc,CAAC,UAAU,EAAE,GAAG,IAAI,EAAE,CAAC,EAAE,WAAW,CAAC;IAC7D,IAAI,EAAE,CAAC,GAAG,CAAC,cAAc,CAAC,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,EAAE,WAAW,CAAC;IAC/D,GAAG,EAAE;QACH,GAAG,CAAC,cAAc,CAAC,UAAU,EAAE,GAAG,IAAI,EAAE,CAAC;QACzC,WAAW;QACX,IAAI;QACJ,YAAY;QACZ,2FAA2F;QAC3F,iBAAiB;QACjB,oBAAoB;KACrB;CACF,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,QAAgB,EAChB,OAAiC;IAEjC,MAAM,OAAO,GAAG,OAAO,EAAE,oBAAoB,CAAC;IAC9C,MAAM,IAAI,GAAG,MAAM,OAAO,EAAE;SACzB,GAAG,CAAC,WAAW,CAAC;SAChB,GAAG,CAAC,SAAS,CAAC;SACd,GAAG,CAAC,SAAS,qBAAqB;QACjC,OAAO,CAAC,IAAe,EAAE,EAAE;YACzB,MAAM,EAAE,GAAG,OAAO,EAAE,cAAc,CAAC;YACnC,IAAI,CAAC,EAAE;gBAAE,OAAO;YAChB,2BAA2B,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;QACxE,CAAC,CAAC;IACJ,CAAC,CAAC;SACD,GAAG,CAAC,yBAAyB,CAAC;SAC9B,GAAG,CAAC,YAAY,EAAE,EAAE,kBAAkB,EAAE,IAAI,EAAE,CAAC;SAC/C,GAAG,CAAC,SAAS,CAAC;SACd,GAAG,CAAC,cAAc,EAAE,cAAc,CAAC;SACnC,GAAG,CAAC,SAAS,qBAAqB;QACjC,OAAO,CAAC,IAAc,EAAE,EAAE;YACxB,IAAI,CAAC,OAAO;gBAAE,OAAO;YACrB,0BAA0B,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC;QAC5C,CAAC,CAAC;IACJ,CAAC,CAAC;SACD,GAAG,CAAC,eAAe,CAAC;SACpB,GAAG,CAAC,eAAe,CAAC;SACpB,OAAO,CAAC,QAAQ,CAAC,CAAC;IACrB,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC;AACtB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,aAAqB;IAC1D,OAAO,oBAAoB,CAAC,aAAa,CAAC,CAAC;AAC7C,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Injects Mermaid only when the page is not served from `file:`.
3
+ * Cross-origin `import()` from an opaque `file://` origin is browser-dependent and often
4
+ * breaks or spams the console; the code browser should stay usable when opened locally.
5
+ */
6
+ export declare function mermaidRuntimeScriptHtml(include: boolean | undefined): string;
7
+ //# sourceMappingURL=mermaid-runtime-html.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mermaid-runtime-html.d.ts","sourceRoot":"","sources":["../src/mermaid-runtime-html.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,CAoB7E"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Injects Mermaid only when the page is not served from `file:`.
3
+ * Cross-origin `import()` from an opaque `file://` origin is browser-dependent and often
4
+ * breaks or spams the console; the code browser should stay usable when opened locally.
5
+ */
6
+ export function mermaidRuntimeScriptHtml(include) {
7
+ if (!include)
8
+ return "";
9
+ const cdn = "https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs";
10
+ const moduleSource = [
11
+ `import mermaid from "${cdn}";`,
12
+ `mermaid.initialize({ startOnLoad: true, securityLevel: "strict" });`,
13
+ `mermaid.run({ querySelector: ".mermaid" });`,
14
+ ].join("");
15
+ const asTextContent = JSON.stringify(moduleSource);
16
+ return (`<script>` +
17
+ `(function(){` +
18
+ `if(typeof location!=="undefined"&&location.protocol==="file:")return;` +
19
+ `var s=document.createElement("script");` +
20
+ `s.type="module";` +
21
+ `s.textContent=${asTextContent};` +
22
+ `document.body.appendChild(s);` +
23
+ `})();` +
24
+ `</script>`);
25
+ }
26
+ //# sourceMappingURL=mermaid-runtime-html.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mermaid-runtime-html.js","sourceRoot":"","sources":["../src/mermaid-runtime-html.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,UAAU,wBAAwB,CAAC,OAA4B;IACnE,IAAI,CAAC,OAAO;QAAE,OAAO,EAAE,CAAC;IACxB,MAAM,GAAG,GAAG,kEAAkE,CAAC;IAC/E,MAAM,YAAY,GAAG;QACnB,wBAAwB,GAAG,IAAI;QAC/B,qEAAqE;QACrE,6CAA6C;KAC9C,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACX,MAAM,aAAa,GAAG,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;IACnD,OAAO,CACL,UAAU;QACV,cAAc;QACd,uEAAuE;QACvE,yCAAyC;QACzC,kBAAkB;QAClB,iBAAiB,aAAa,GAAG;QACjC,+BAA+B;QAC/B,OAAO;QACP,WAAW,CACZ,CAAC;AACJ,CAAC"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Reads `version` from this package’s `package.json` (works for both `src/` and `dist/` layouts).
3
+ */
4
+ export declare function commentrayRenderVersion(): string;
5
+ //# sourceMappingURL=package-version.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"package-version.d.ts","sourceRoot":"","sources":["../src/package-version.ts"],"names":[],"mappings":"AAIA;;GAEG;AACH,wBAAgB,uBAAuB,IAAI,MAAM,CAMhD"}
@@ -0,0 +1,14 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { dirname, join } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ /**
5
+ * Reads `version` from this package’s `package.json` (works for both `src/` and `dist/` layouts).
6
+ */
7
+ export function commentrayRenderVersion() {
8
+ const here = dirname(fileURLToPath(import.meta.url));
9
+ const packageDir = join(here, "..");
10
+ const raw = readFileSync(join(packageDir, "package.json"), "utf8");
11
+ const j = JSON.parse(raw);
12
+ return j.version ?? "0.0.0";
13
+ }
14
+ //# sourceMappingURL=package-version.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"package-version.js","sourceRoot":"","sources":["../src/package-version.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC;;GAEG;AACH,MAAM,UAAU,uBAAuB;IACrC,MAAM,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IACrD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACpC,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,CAAC,UAAU,EAAE,cAAc,CAAC,EAAE,MAAM,CAAC,CAAC;IACnE,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAyB,CAAC;IAClD,OAAO,CAAC,CAAC,OAAO,IAAI,OAAO,CAAC;AAC9B,CAAC"}
@@ -1,3 +1,4 @@
1
+ import { type CommentrayOutputUrlOptions } from "./markdown-pipeline.js";
1
2
  export type SideBySideOptions = {
2
3
  title?: string;
3
4
  /** Source code text (not yet fenced). */
@@ -6,8 +7,12 @@ export type SideBySideOptions = {
6
7
  language: string;
7
8
  /** Commentray markdown body. */
8
9
  commentrayMarkdown: string;
10
+ /** Highlight.js theme base name (e.g. `github`, `github-dark`); matches static code browser. */
11
+ hljsTheme?: string;
9
12
  /** When true, include Mermaid runtime from CDN in the footer. */
10
13
  includeMermaidRuntime?: boolean;
14
+ /** Optional static URL rewriting for the commentray pane (images, local links, GitHub blob). */
15
+ commentrayOutputUrls?: CommentrayOutputUrlOptions;
11
16
  };
12
17
  export declare function renderSideBySideHtml(opts: SideBySideOptions): Promise<string>;
13
18
  //# sourceMappingURL=side-by-side.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"side-by-side.d.ts","sourceRoot":"","sources":["../src/side-by-side.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,iBAAiB,GAAG;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yCAAyC;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,2DAA2D;IAC3D,QAAQ,EAAE,MAAM,CAAC;IACjB,gCAAgC;IAChC,kBAAkB,EAAE,MAAM,CAAC;IAC3B,iEAAiE;IACjE,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACjC,CAAC;AAEF,wBAAsB,oBAAoB,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,CAiDnF"}
1
+ {"version":3,"file":"side-by-side.d.ts","sourceRoot":"","sources":["../src/side-by-side.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,0BAA0B,EAGhC,MAAM,wBAAwB,CAAC;AAGhC,MAAM,MAAM,iBAAiB,GAAG;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yCAAyC;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,2DAA2D;IAC3D,QAAQ,EAAE,MAAM,CAAC;IACjB,gCAAgC;IAChC,kBAAkB,EAAE,MAAM,CAAC;IAC3B,gGAAgG;IAChG,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iEAAiE;IACjE,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,gGAAgG;IAChG,oBAAoB,CAAC,EAAE,0BAA0B,CAAC;CACnD,CAAC;AAEF,wBAAsB,oBAAoB,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,CAkDnF"}
@@ -1,25 +1,27 @@
1
1
  import { escapeHtml } from "./html-utils.js";
2
- import { renderFencedCode, renderMarkdownToHtml } from "./markdown-pipeline.js";
2
+ import { renderFencedCode, renderMarkdownToHtml, } from "./markdown-pipeline.js";
3
+ import { mermaidRuntimeScriptHtml } from "./mermaid-runtime-html.js";
3
4
  export async function renderSideBySideHtml(opts) {
4
5
  const fence = "```" + opts.language + "\n" + opts.code + "\n```\n";
5
6
  const [codeHtml, commentrayHtml] = await Promise.all([
6
7
  renderFencedCode(fence),
7
- renderMarkdownToHtml(opts.commentrayMarkdown),
8
+ renderMarkdownToHtml(opts.commentrayMarkdown, {
9
+ commentrayOutputUrls: opts.commentrayOutputUrls,
10
+ }),
8
11
  ]);
9
- const mermaidScript = opts.includeMermaidRuntime
10
- ? `<script type="module">
11
- import mermaid from "https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs";
12
- mermaid.initialize({ startOnLoad: true, securityLevel: "strict" });
13
- mermaid.run({ querySelector: ".mermaid" });
14
- </script>`
15
- : "";
12
+ const mermaidScript = mermaidRuntimeScriptHtml(opts.includeMermaidRuntime);
16
13
  const title = opts.title ?? "Commentray";
14
+ const hljs = opts.hljsTheme ?? "github";
15
+ const hljsDark = opts.hljsTheme?.includes("dark") ? opts.hljsTheme : "github-dark";
16
+ const hljsCdnBase = "https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.11.1/build/styles";
17
17
  return `<!doctype html>
18
18
  <html lang="en">
19
19
  <head>
20
20
  <meta charset="utf-8" />
21
21
  <meta name="viewport" content="width=device-width, initial-scale=1" />
22
22
  <title>${escapeHtml(title)}</title>
23
+ <link rel="stylesheet" href="${hljsCdnBase}/${escapeHtml(hljs)}.min.css" media="(prefers-color-scheme: light)" />
24
+ <link rel="stylesheet" href="${hljsCdnBase}/${escapeHtml(hljsDark)}.min.css" media="(prefers-color-scheme: dark)" />
23
25
  <style>
24
26
  :root { color-scheme: light dark; }
25
27
  body { margin: 0; font-family: system-ui, -apple-system, Segoe UI, Roboto, sans-serif; }
@@ -1 +1 @@
1
- {"version":3,"file":"side-by-side.js","sourceRoot":"","sources":["../src/side-by-side.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAchF,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,IAAuB;IAChE,MAAM,KAAK,GAAG,KAAK,GAAG,IAAI,CAAC,QAAQ,GAAG,IAAI,GAAG,IAAI,CAAC,IAAI,GAAG,SAAS,CAAC;IACnE,MAAM,CAAC,QAAQ,EAAE,cAAc,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QACnD,gBAAgB,CAAC,KAAK,CAAC;QACvB,oBAAoB,CAAC,IAAI,CAAC,kBAAkB,CAAC;KAC9C,CAAC,CAAC;IAEH,MAAM,aAAa,GAAG,IAAI,CAAC,qBAAqB;QAC9C,CAAC,CAAC;;;;UAII;QACN,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,YAAY,CAAC;IAEzC,OAAO;;;;;aAKI,UAAU,CAAC,KAAK,CAAC;;;;;;;;;;;;;;;;;UAiBpB,QAAQ;;;;UAIR,cAAc;;;MAGlB,aAAa;;QAEX,CAAC;AACT,CAAC"}
1
+ {"version":3,"file":"side-by-side.js","sourceRoot":"","sources":["../src/side-by-side.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAEL,gBAAgB,EAChB,oBAAoB,GACrB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AAkBrE,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,IAAuB;IAChE,MAAM,KAAK,GAAG,KAAK,GAAG,IAAI,CAAC,QAAQ,GAAG,IAAI,GAAG,IAAI,CAAC,IAAI,GAAG,SAAS,CAAC;IACnE,MAAM,CAAC,QAAQ,EAAE,cAAc,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QACnD,gBAAgB,CAAC,KAAK,CAAC;QACvB,oBAAoB,CAAC,IAAI,CAAC,kBAAkB,EAAE;YAC5C,oBAAoB,EAAE,IAAI,CAAC,oBAAoB;SAChD,CAAC;KACH,CAAC,CAAC;IAEH,MAAM,aAAa,GAAG,wBAAwB,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;IAE3E,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,YAAY,CAAC;IACzC,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,IAAI,QAAQ,CAAC;IACxC,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,aAAa,CAAC;IACnF,MAAM,WAAW,GAAG,0EAA0E,CAAC;IAE/F,OAAO;;;;;aAKI,UAAU,CAAC,KAAK,CAAC;mCACK,WAAW,IAAI,UAAU,CAAC,IAAI,CAAC;mCAC/B,WAAW,IAAI,UAAU,CAAC,QAAQ,CAAC;;;;;;;;;;;;;;;;;UAiB5D,QAAQ;;;;UAIR,cAAc;;;MAGlB,aAAa;;QAEX,CAAC;AACT,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@commentray/render",
3
- "version": "0.0.1",
3
+ "version": "0.0.4",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -25,19 +25,21 @@
25
25
  "clean": "rm -rf dist"
26
26
  },
27
27
  "dependencies": {
28
+ "@commentray/core": "0.0.4",
28
29
  "@m31coding/fuzzy-search": "^2.0.0",
29
30
  "rehype-highlight": "^7.0.2",
31
+ "rehype-raw": "^7.0.0",
30
32
  "rehype-sanitize": "^6.0.0",
31
33
  "rehype-stringify": "^10.0.1",
32
34
  "remark-gfm": "^4.0.1",
33
35
  "remark-parse": "^11.0.0",
34
36
  "remark-rehype": "^11.1.2",
35
37
  "unified": "^11.0.5",
36
- "unist-util-visit": "^5.0.0"
38
+ "unist-util-visit": "^5.1.0"
37
39
  },
38
40
  "devDependencies": {
39
41
  "@types/mdast": "^4.0.4",
40
- "@types/node": "^22.14.1",
41
- "esbuild": "^0.25.12"
42
+ "@types/node": "^25.6.0",
43
+ "esbuild": "^0.28.0"
42
44
  }
43
45
  }