sourcey 3.5.9 → 3.6.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.
Files changed (48) hide show
  1. package/README.md +28 -117
  2. package/dist/adapters/index.d.ts +11 -0
  3. package/dist/adapters/index.d.ts.map +1 -0
  4. package/dist/adapters/index.js +98 -0
  5. package/dist/adapters/mkdocs.d.ts +5 -0
  6. package/dist/adapters/mkdocs.d.ts.map +1 -0
  7. package/dist/adapters/mkdocs.js +367 -0
  8. package/dist/adapters/shared.d.ts +12 -0
  9. package/dist/adapters/shared.d.ts.map +1 -0
  10. package/dist/adapters/shared.js +134 -0
  11. package/dist/adapters/types.d.ts +68 -0
  12. package/dist/adapters/types.d.ts.map +1 -0
  13. package/dist/adapters/types.js +1 -0
  14. package/dist/client/search.js +77 -8
  15. package/dist/client/sidebar.js +169 -0
  16. package/dist/components/layout/Head.js +16 -3
  17. package/dist/components/layout/Sidebar.d.ts.map +1 -1
  18. package/dist/components/layout/Sidebar.js +1 -1
  19. package/dist/components/layout/TableOfContents.d.ts.map +1 -1
  20. package/dist/components/layout/TableOfContents.js +4 -2
  21. package/dist/config.d.ts +38 -0
  22. package/dist/config.d.ts.map +1 -1
  23. package/dist/config.js +79 -141
  24. package/dist/core/doxygen-loader.d.ts.map +1 -1
  25. package/dist/core/doxygen-loader.js +2 -0
  26. package/dist/core/markdown-loader.d.ts +14 -0
  27. package/dist/core/markdown-loader.d.ts.map +1 -1
  28. package/dist/core/markdown-loader.js +63 -22
  29. package/dist/core/navigation.d.ts.map +1 -1
  30. package/dist/core/navigation.js +8 -7
  31. package/dist/core/search-indexer.d.ts +10 -0
  32. package/dist/core/search-indexer.d.ts.map +1 -1
  33. package/dist/core/search-indexer.js +5 -0
  34. package/dist/dev-server.d.ts.map +1 -1
  35. package/dist/dev-server.js +60 -33
  36. package/dist/index.d.ts +2 -0
  37. package/dist/index.d.ts.map +1 -1
  38. package/dist/index.js +5 -2
  39. package/dist/init.d.ts.map +1 -1
  40. package/dist/init.js +19 -14
  41. package/dist/site-assembly.d.ts.map +1 -1
  42. package/dist/site-assembly.js +107 -25
  43. package/dist/utils/markdown.d.ts.map +1 -1
  44. package/dist/utils/markdown.js +15 -4
  45. package/dist/vite-plugin.d.ts +2 -0
  46. package/dist/vite-plugin.d.ts.map +1 -1
  47. package/dist/vite-plugin.js +71 -1
  48. package/package.json +4 -3
@@ -30,7 +30,12 @@ async function exists(path) {
30
30
  }
31
31
  }
32
32
  function log(msg) {
33
- const t = new Date().toLocaleTimeString([], { hour12: false, hour: "2-digit", minute: "2-digit", second: "2-digit" });
33
+ const t = new Date().toLocaleTimeString([], {
34
+ hour12: false,
35
+ hour: "2-digit",
36
+ minute: "2-digit",
37
+ second: "2-digit",
38
+ });
34
39
  console.log(` \x1b[2m${t}\x1b[0m ${msg}`);
35
40
  }
36
41
  function shortPath(path) {
@@ -44,20 +49,13 @@ export async function startDevServer(options) {
44
49
  : resolve(options.config ?? process.cwd(), "sourcey.config.ts");
45
50
  const watchPaths = [configPath];
46
51
  for (const tab of config.tabs) {
47
- if (tab.openapi)
48
- watchPaths.push(tab.openapi);
49
- if (tab.mcp)
50
- watchPaths.push(tab.mcp);
51
- if (tab.doxygen)
52
- watchPaths.push(tab.doxygen.xml);
53
- if (tab.godoc) {
54
- if (tab.godoc.snapshot)
55
- watchPaths.push(tab.godoc.snapshot);
52
+ watchPaths.push(...(tab.source.watchPaths ?? []));
53
+ if (tab.source.kind === "godoc") {
56
54
  // The Go module directory is large; watching every .go file slows the
57
55
  // dev server. Restart manually after broad source edits.
58
56
  }
59
- if (tab.groups) {
60
- for (const group of tab.groups) {
57
+ if (tab.source.kind === "markdown") {
58
+ for (const group of tab.source.groups) {
61
59
  for (const page of group.pages) {
62
60
  watchPaths.push(page.file);
63
61
  }
@@ -68,22 +66,41 @@ export async function startDevServer(options) {
68
66
  const map = new Map();
69
67
  map.set(configPath, { kind: "config" });
70
68
  for (const tab of cfg.tabs) {
71
- if (tab.openapi) {
72
- map.set(resolve(tab.openapi), { kind: "openapi", tabSlug: tab.slug, specPath: tab.openapi });
69
+ for (const watchPath of tab.source.watchPaths ?? []) {
70
+ map.set(resolve(watchPath), { kind: "config" });
71
+ }
72
+ if (tab.source.kind === "openapi") {
73
+ map.set(resolve(tab.source.spec), {
74
+ kind: "openapi",
75
+ tabSlug: tab.slug,
76
+ specPath: tab.source.spec,
77
+ });
73
78
  }
74
- if (tab.mcp) {
75
- map.set(resolve(tab.mcp), { kind: "mcp", tabSlug: tab.slug, specPath: tab.mcp });
79
+ if (tab.source.kind === "mcp") {
80
+ map.set(resolve(tab.source.spec), {
81
+ kind: "mcp",
82
+ tabSlug: tab.slug,
83
+ specPath: tab.source.spec,
84
+ });
76
85
  }
77
- if (tab.doxygen) {
78
- map.set(resolve(tab.doxygen.xml), { kind: "doxygen", tabSlug: tab.slug, xmlDir: tab.doxygen.xml });
86
+ if (tab.source.kind === "doxygen") {
87
+ map.set(resolve(tab.source.config.xml), {
88
+ kind: "doxygen",
89
+ tabSlug: tab.slug,
90
+ xmlDir: tab.source.config.xml,
91
+ });
79
92
  }
80
- if (tab.godoc?.snapshot) {
81
- map.set(resolve(tab.godoc.snapshot), { kind: "godoc", tabSlug: tab.slug, snapshotPath: tab.godoc.snapshot });
93
+ if (tab.source.kind === "godoc" && tab.source.config.snapshot) {
94
+ map.set(resolve(tab.source.config.snapshot), {
95
+ kind: "godoc",
96
+ tabSlug: tab.slug,
97
+ snapshotPath: tab.source.config.snapshot,
98
+ });
82
99
  }
83
- if (tab.groups) {
84
- for (const group of tab.groups) {
100
+ if (tab.source.kind === "markdown") {
101
+ for (const group of tab.source.groups) {
85
102
  for (const page of group.pages) {
86
- map.set(resolve(page.file), { kind: "markdown", tabSlug: tab.slug, pagePath: page.file, pageSlug: page.slug });
103
+ map.set(resolve(page.file), { kind: "markdown", tabSlug: tab.slug, page });
87
104
  }
88
105
  }
89
106
  }
@@ -143,11 +160,13 @@ export async function startDevServer(options) {
143
160
  const { data } = snapshot;
144
161
  const start = performance.now();
145
162
  if (content.kind === "markdown") {
146
- const slug = slugFromPath(content.pageSlug);
147
- log(`reloading ${shortPath(content.pagePath)}`);
148
- const page = await loadDocsPage(content.pagePath, slug, {
163
+ const slug = slugFromPath(content.page.slug);
164
+ log(`reloading ${shortPath(content.page.file)}`);
165
+ const page = await loadDocsPage(content.page.file, slug, {
149
166
  changelog: config.changelog.enabled,
150
167
  repoUrl: config.repo,
168
+ sourceRoot: content.page.sourceRoot,
169
+ preprocess: content.page.preprocess,
151
170
  });
152
171
  if (cache !== snapshot)
153
172
  return;
@@ -166,10 +185,10 @@ export async function startDevServer(options) {
166
185
  }
167
186
  else if (content.kind === "doxygen") {
168
187
  const tab = config.tabs.find((candidate) => candidate.slug === content.tabSlug);
169
- if (!tab?.doxygen)
188
+ if (!tab || tab.source.kind !== "doxygen")
170
189
  return;
171
190
  log(`rebuilding doxygen tab "${tab.label}"`);
172
- const { pages, navTab } = await loadDoxygenTab(tab.doxygen, tab.slug, tab.label);
191
+ const { pages, navTab } = await loadDoxygenTab(tab.source.config, tab.slug, tab.label);
173
192
  if (cache !== snapshot)
174
193
  return;
175
194
  for (const [key, page] of data.pageMap) {
@@ -194,13 +213,13 @@ export async function startDevServer(options) {
194
213
  }
195
214
  else if (content.kind === "godoc") {
196
215
  const tab = config.tabs.find((candidate) => candidate.slug === content.tabSlug);
197
- if (!tab?.godoc)
216
+ if (!tab || tab.source.kind !== "godoc")
198
217
  return;
199
218
  log(`rebuilding godoc tab "${tab.label}"`);
200
- const { pages, navTab } = await loadGodocTab(tab.godoc, tab.slug, tab.label, {
219
+ const { pages, navTab } = await loadGodocTab(tab.source.config, tab.slug, tab.label, {
201
220
  repo: config.repo,
202
221
  editBranch: config.editBranch,
203
- editBasePath: tab.godoc.sourceBasePath,
222
+ editBasePath: tab.source.config.sourceBasePath,
204
223
  });
205
224
  if (cache !== snapshot)
206
225
  return;
@@ -280,7 +299,7 @@ export async function startDevServer(options) {
280
299
  return resolveConfigFromRaw(configMod.default, dirname(configPath));
281
300
  }
282
301
  async function render(url) {
283
- const { renderPage } = await vite.ssrLoadModule(ssrRendererPath);
302
+ const { renderPage } = (await vite.ssrLoadModule(ssrRendererPath));
284
303
  const { data, siteConfig: site } = await getCached();
285
304
  const navigation = buildSiteNavigation(data.siteTabs);
286
305
  const requestPath = stripBaseUrl(new URL(url, "http://sourcey.local").pathname, config.baseUrl);
@@ -300,7 +319,10 @@ export async function startDevServer(options) {
300
319
  }
301
320
  }
302
321
  let pageData = data.pageMap.get(pagePath);
303
- if (!pageData && config.prettyUrls === "slash" && pagePath.endsWith(".html") && !pagePath.endsWith("/index.html")) {
322
+ if (!pageData &&
323
+ config.prettyUrls === "slash" &&
324
+ pagePath.endsWith(".html") &&
325
+ !pagePath.endsWith("/index.html")) {
304
326
  // Fallback for stale `.html` links when prettyUrls is enabled.
305
327
  const pretty = pagePath.replace(/\.html$/, "/index.html");
306
328
  pageData = data.pageMap.get(pretty);
@@ -324,6 +346,10 @@ export async function startDevServer(options) {
324
346
  const docsPagesByTab = collectDocsPagesByTab(data.pageMap, config.tabs);
325
347
  return buildSearchIndex(data.specsBySlug, docsPagesByTab, navigation, config.baseUrl || "/", config.search.featured);
326
348
  }
349
+ async function loadExtraFileForDev(outputPath) {
350
+ const { data } = await getCached();
351
+ return data.extraFiles.get(outputPath);
352
+ }
327
353
  const viteConfig = {
328
354
  root: process.cwd(),
329
355
  server: {
@@ -343,6 +369,7 @@ export async function startDevServer(options) {
343
369
  baseUrl: () => config.baseUrl,
344
370
  render,
345
371
  searchIndex: buildSearchIndexForDev,
372
+ extraFile: loadExtraFileForDev,
346
373
  }),
347
374
  ],
348
375
  clearScreen: false,
package/dist/index.d.ts CHANGED
@@ -36,6 +36,8 @@ export interface SiteBuildResult {
36
36
  }
37
37
  export declare function buildSiteDocs(options?: SiteBuildOptions): Promise<SiteBuildResult>;
38
38
  export { defineConfig } from "./config.js";
39
+ export { doxygen, godoc, markdown, mcp, mkdocs, openapi } from "./adapters/index.js";
39
40
  export { resolveInternalLinks } from "./site-assembly.js";
40
41
  export type { NormalizedSpec, NormalizedOperation, NormalizedTag, NormalizedSchema, NormalizedParameter, NormalizedRequestBody, NormalizedResponse, } from "./core/types.js";
42
+ export type { DoxygenSourceOptions, GodocSourceOptions, MarkdownSourceOptions, McpSourceOptions, MkDocsSourceOptions, OpenApiSourceOptions, ResolvedTabSource, SourceAdapter, SourceAdapterContext, } from "./adapters/index.js";
41
43
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,mBAAmB,EAA8B,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACvG,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAiBlD,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,cAAc,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,oBAAoB,EAAE,mBAAmB,EAAE,CAAC;CAC7C;AAED;;;GAGG;AACH,wBAAsB,SAAS,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC,CAkB3E;AAMD,MAAM,WAAW,gBAAgB;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,oBAAoB,EAAE,mBAAmB,EAAE,CAAC;IAC5C,gBAAgB,EAAE,OAAO,wBAAwB,EAAE,qBAAqB,EAAE,CAAC;IAC3E,wDAAwD;IACxD,MAAM,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;CACtC;AAED,wBAAsB,aAAa,CAAC,OAAO,GAAE,gBAAqB,GAAG,OAAO,CAAC,eAAe,CAAC,CAoF5F;AA4CD,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAG1D,YAAY,EACV,cAAc,EACd,mBAAmB,EACnB,aAAa,EACb,gBAAgB,EAChB,mBAAmB,EACnB,qBAAqB,EACrB,kBAAkB,GACnB,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,mBAAmB,EAEnB,cAAc,EACf,MAAM,iBAAiB,CAAC;AACzB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAiBlD,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,cAAc,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,oBAAoB,EAAE,mBAAmB,EAAE,CAAC;CAC7C;AAED;;;GAGG;AACH,wBAAsB,SAAS,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC,CAkB3E;AAMD,MAAM,WAAW,gBAAgB;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,oBAAoB,EAAE,mBAAmB,EAAE,CAAC;IAC5C,gBAAgB,EAAE,OAAO,wBAAwB,EAAE,qBAAqB,EAAE,CAAC;IAC3E,wDAAwD;IACxD,MAAM,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;CACtC;AAED,wBAAsB,aAAa,CAAC,OAAO,GAAE,gBAAqB,GAAG,OAAO,CAAC,eAAe,CAAC,CAwF5F;AA8CD,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AACrF,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAG1D,YAAY,EACV,cAAc,EACd,mBAAmB,EACnB,aAAa,EACb,gBAAgB,EAChB,mBAAmB,EACnB,qBAAqB,EACrB,kBAAkB,GACnB,MAAM,iBAAiB,CAAC;AAEzB,YAAY,EACV,oBAAoB,EACpB,kBAAkB,EAClB,qBAAqB,EACrB,gBAAgB,EAChB,mBAAmB,EACnB,oBAAoB,EACpB,iBAAiB,EACjB,aAAa,EACb,oBAAoB,GACrB,MAAM,qBAAqB,CAAC"}
package/dist/index.js CHANGED
@@ -29,7 +29,7 @@ export async function buildDocs(options) {
29
29
  }
30
30
  export async function buildSiteDocs(options = {}) {
31
31
  const outputDir = resolve(options.outputDir ?? "dist");
32
- const config = options.config ?? await loadConfig(options.configDir);
32
+ const config = options.config ?? (await loadConfig(options.configDir));
33
33
  const assembled = await assembleSite(config);
34
34
  const site = await buildSiteConfig(config);
35
35
  const sitePages = Array.from(assembled.pageMap.values());
@@ -65,7 +65,9 @@ export async function buildSiteDocs(options = {}) {
65
65
  }
66
66
  else {
67
67
  const staticOg = config.ogImage;
68
- if (staticOg.startsWith("http://") || staticOg.startsWith("https://") || staticOg.startsWith("data:")) {
68
+ if (staticOg.startsWith("http://") ||
69
+ staticOg.startsWith("https://") ||
70
+ staticOg.startsWith("data:")) {
69
71
  for (const page of sitePages) {
70
72
  page.ogImagePath = staticOg;
71
73
  }
@@ -131,4 +133,5 @@ function summarizeVersion(version) {
131
133
  return summary || undefined;
132
134
  }
133
135
  export { defineConfig } from "./config.js";
136
+ export { doxygen, godoc, markdown, mcp, mkdocs, openapi } from "./adapters/index.js";
134
137
  export { resolveInternalLinks } from "./site-assembly.js";
@@ -1 +1 @@
1
- {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../src/init.ts"],"names":[],"mappings":"AA4DA,eAAO,MAAM,IAAI,qDAyPf,CAAC"}
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../src/init.ts"],"names":[],"mappings":"AA4DA,eAAO,MAAM,IAAI,qDAoQf,CAAC"}
package/dist/init.js CHANGED
@@ -79,7 +79,9 @@ export const init = defineCommand({
79
79
  }
80
80
  }
81
81
  if (existsSync(resolve(targetDir, "sourcey.config.ts"))) {
82
- consola.error("sourcey.config.ts already exists in " + (targetDir === cwd ? "this directory" : relative(cwd, targetDir)) + ".");
82
+ consola.error("sourcey.config.ts already exists in " +
83
+ (targetDir === cwd ? "this directory" : relative(cwd, targetDir)) +
84
+ ".");
83
85
  process.exit(1);
84
86
  }
85
87
  // -- Auto-detect sources --
@@ -155,42 +157,45 @@ export const init = defineCommand({
155
157
  process.exit(0);
156
158
  }
157
159
  // -- Generate files --
158
- const pages = withExample
159
- ? `["introduction", "quickstart"]`
160
- : `["introduction"]`;
160
+ const pages = withExample ? `["introduction", "quickstart"]` : `["introduction"]`;
161
161
  // Build tabs array — paths relative from targetDir to cwd
162
162
  const relPath = (file) => {
163
163
  const abs = resolve(cwd, file);
164
164
  const rel = relative(targetDir, abs);
165
165
  return rel.startsWith(".") ? rel : "./" + rel;
166
166
  };
167
+ const imports = new Set(["defineConfig", "markdown"]);
167
168
  let tabs = ` {
168
169
  tab: "Documentation",
169
170
  slug: "",
170
- groups: [
171
- {
172
- group: "Getting Started",
173
- pages: ${pages},
174
- },
175
- ],
171
+ source: markdown({
172
+ groups: [
173
+ {
174
+ group: "Getting Started",
175
+ pages: ${pages},
176
+ },
177
+ ],
178
+ }),
176
179
  },`;
177
180
  if (addOpenAPI) {
181
+ imports.add("openapi");
178
182
  tabs += `
179
183
  {
180
184
  tab: "API Reference",
181
185
  slug: "api",
182
- openapi: "${relPath(addOpenAPI)}",
186
+ source: openapi("${relPath(addOpenAPI)}"),
183
187
  },`;
184
188
  }
185
189
  if (addDoxygen) {
190
+ imports.add("doxygen");
186
191
  tabs += `
187
192
  {
188
193
  tab: "API Reference",
189
194
  slug: "api",
190
- doxygen: { xml: "${relPath(addDoxygen.xmlDir)}" },
195
+ source: doxygen({ xml: "${relPath(addDoxygen.xmlDir)}" }),
191
196
  },`;
192
197
  }
193
- const config = `import { defineConfig } from "sourcey";
198
+ const config = `import { ${[...imports].join(", ")} } from "sourcey";
194
199
 
195
200
  export default defineConfig({
196
201
  name: "${name}",
@@ -247,7 +252,7 @@ import { myFunction } from "my-package";
247
252
  build: "sourcey build",
248
253
  },
249
254
  dependencies: {
250
- sourcey: "^3.4.3",
255
+ sourcey: "^3.6.0",
251
256
  },
252
257
  }, null, 2);
253
258
  writeFileSync(resolve(targetDir, "package.json"), pkg + "\n");
@@ -1 +1 @@
1
- {"version":3,"file":"site-assembly.d.ts","sourceRoot":"","sources":["../src/site-assembly.ts"],"names":[],"mappings":"AASA,OAAO,EAAgB,KAAK,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAIlF,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC3E,OAAO,KAAK,EAAiB,QAAQ,EAAgB,MAAM,2BAA2B,CAAC;AACvF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,KAAK,EAAE,mBAAmB,EAA8B,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACvG,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAGxD,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,WAAW,EAAE,cAAc,CAAC;IAC5B,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IACzC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC/B,oBAAoB,EAAE,mBAAmB,EAAE,CAAC;IAC5C,gBAAgB,EAAE,qBAAqB,EAAE,CAAC;IAC1C,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;CAC1C;AAED,wBAAsB,YAAY,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,YAAY,CAAC,CA2HhF;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,qBAAqB,GAAG,MAAM,CAKzE;AAED,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,EAC9B,IAAI,EAAE,WAAW,EAAE,GAClB,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,CAAC,CAgBzB;AAED,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,EAC9B,QAAQ,EAAE,OAAO,EAAE,EACnB,IAAI,EAAE,WAAW,EAAE,EACnB,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,UAAU,GACrB,IAAI,CAsBN;AAaD,wBAAgB,2BAA2B,CACzC,WAAW,EAAE,mBAAmB,EAAE,EAClC,eAAe,UAAQ,GACtB,IAAI,CAYN;AAED,wBAAgB,yBAAyB,CAAC,UAAU,EAAE,mBAAmB,GAAG,MAAM,CAIjF;AAED,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,mBAAmB,GAAG,MAAM,CAI9E;AAED,wBAAgB,0BAA0B,CAAC,WAAW,EAAE,mBAAmB,EAAE,GAAG,MAAM,EAAE,CAEvF;AAED,wBAAsB,eAAe,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,UAAU,CAAC,CA4BjF;AAED,wBAAgB,iBAAiB,IAAI,cAAc,CAUlD;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE,MAAM,EAAE,cAAc,GAAG,IAAI,CAuEpF"}
1
+ {"version":3,"file":"site-assembly.d.ts","sourceRoot":"","sources":["../src/site-assembly.ts"],"names":[],"mappings":"AASA,OAAO,EAAgB,KAAK,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAIlF,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC3E,OAAO,KAAK,EAAiB,QAAQ,EAAgB,MAAM,2BAA2B,CAAC;AAEvF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,KAAK,EACV,mBAAmB,EAEnB,cAAc,EACf,MAAM,iBAAiB,CAAC;AACzB,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAGxD,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,WAAW,EAAE,cAAc,CAAC;IAC5B,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IACzC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC/B,oBAAoB,EAAE,mBAAmB,EAAE,CAAC;IAC5C,gBAAgB,EAAE,qBAAqB,EAAE,CAAC;IAC1C,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;CAC1C;AAED,wBAAsB,YAAY,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,YAAY,CAAC,CAmIhF;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,qBAAqB,GAAG,MAAM,CAKzE;AAED,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,EAC9B,IAAI,EAAE,WAAW,EAAE,GAClB,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,CAAC,CAoBzB;AAED,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,EAC9B,QAAQ,EAAE,OAAO,EAAE,EACnB,IAAI,EAAE,WAAW,EAAE,EACnB,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,UAAU,GACrB,IAAI,CAsBN;AAaD,wBAAgB,2BAA2B,CACzC,WAAW,EAAE,mBAAmB,EAAE,EAClC,eAAe,UAAQ,GACtB,IAAI,CAYN;AAED,wBAAgB,yBAAyB,CAAC,UAAU,EAAE,mBAAmB,GAAG,MAAM,CAIjF;AAED,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,mBAAmB,GAAG,MAAM,CAI9E;AAED,wBAAgB,0BAA0B,CAAC,WAAW,EAAE,mBAAmB,EAAE,GAAG,MAAM,EAAE,CAEvF;AAED,wBAAsB,eAAe,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,UAAU,CAAC,CA4BjF;AAED,wBAAgB,iBAAiB,IAAI,cAAc,CAUlD;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE,MAAM,EAAE,cAAc,GAAG,IAAI,CA6FpF"}
@@ -1,5 +1,5 @@
1
1
  import { readFile } from "node:fs/promises";
2
- import { extname, posix, resolve } from "node:path";
2
+ import { extname, posix, relative, resolve } from "node:path";
3
3
  import { loadSpec } from "./core/loader.js";
4
4
  import { convertToOpenApi3 } from "./core/converter.js";
5
5
  import { parseSpec } from "./core/parser.js";
@@ -20,7 +20,7 @@ export async function assembleSite(config) {
20
20
  const changelogDiagnostics = [];
21
21
  const godocDiagnostics = [];
22
22
  for (const tab of config.tabs) {
23
- if (tab.openapi || tab.mcp) {
23
+ if (tab.source.kind === "openapi" || tab.source.kind === "mcp") {
24
24
  const spec = specsBySlug.get(tab.slug);
25
25
  const navTab = buildNavFromSpec(spec, tab.slug, config.prettyUrls);
26
26
  navTab.label = tab.label;
@@ -35,8 +35,8 @@ export async function assembleSite(config) {
35
35
  });
36
36
  continue;
37
37
  }
38
- if (tab.doxygen) {
39
- const { pages, navTab } = await loadDoxygenTab(tab.doxygen, tab.slug, tab.label);
38
+ if (tab.source.kind === "doxygen") {
39
+ const { pages, navTab } = await loadDoxygenTab(tab.source.config, tab.slug, tab.label);
40
40
  for (const [slug, page] of pages) {
41
41
  const outputPath = pageOutputPath(tab.slug, slug, config.prettyUrls);
42
42
  pageMap.set(outputPath, {
@@ -50,11 +50,11 @@ export async function assembleSite(config) {
50
50
  siteTabs.push(navTab);
51
51
  continue;
52
52
  }
53
- if (tab.godoc) {
54
- const { pages, navTab, diagnostics } = await loadGodocTab(tab.godoc, tab.slug, tab.label, {
53
+ if (tab.source.kind === "godoc") {
54
+ const { pages, navTab, diagnostics } = await loadGodocTab(tab.source.config, tab.slug, tab.label, {
55
55
  repo: config.repo,
56
56
  editBranch: config.editBranch,
57
- editBasePath: tab.godoc.sourceBasePath,
57
+ editBasePath: tab.source.config.sourceBasePath,
58
58
  });
59
59
  godocDiagnostics.push(...diagnostics);
60
60
  for (const [slug, page] of pages) {
@@ -70,15 +70,17 @@ export async function assembleSite(config) {
70
70
  siteTabs.push(navTab);
71
71
  continue;
72
72
  }
73
- if (!tab.groups)
73
+ if (tab.source.kind !== "markdown")
74
74
  continue;
75
75
  const pagesByPath = new Map();
76
- for (const group of tab.groups) {
76
+ for (const group of tab.source.groups) {
77
77
  for (const rp of group.pages) {
78
78
  const slug = slugFromPath(rp.slug);
79
79
  const page = await loadDocsPage(rp.file, slug, {
80
80
  changelog: config.changelog.enabled,
81
81
  repoUrl: config.repo,
82
+ sourceRoot: rp.sourceRoot,
83
+ preprocess: rp.preprocess,
82
84
  });
83
85
  pagesByPath.set(rp.slug, page);
84
86
  const outputPath = pageOutputPath(tab.slug, slug, config.prettyUrls);
@@ -111,6 +113,7 @@ export async function assembleSite(config) {
111
113
  const sitePages = Array.from(pageMap.values());
112
114
  resolveInternalLinks(sitePages, config);
113
115
  const extraFiles = attachChangelogFeeds(sitePages, config);
116
+ await attachSourceAssets(extraFiles, config.tabs);
114
117
  return {
115
118
  siteTabs,
116
119
  primarySpec,
@@ -130,13 +133,15 @@ export function formatGodocDiagnostic(diag) {
130
133
  export function collectDocsPagesByTab(pageMap, tabs) {
131
134
  const docsPagesByTab = new Map();
132
135
  for (const tab of tabs) {
133
- if (!tab.groups && !tab.doxygen && !tab.godoc)
136
+ if (!isDocsSource(tab.source.kind))
134
137
  continue;
135
138
  const tabPages = [];
136
139
  for (const [, page] of pageMap) {
137
140
  if (page.tabSlug !== tab.slug || !isSearchableDocsSitePage(page))
138
141
  continue;
139
- tabPages.push(page.currentPage.kind === "markdown" ? page.currentPage.markdown : page.currentPage.changelog);
142
+ tabPages.push(page.currentPage.kind === "markdown"
143
+ ? page.currentPage.markdown
144
+ : page.currentPage.changelog);
140
145
  }
141
146
  docsPagesByTab.set(tab.slug, tabPages);
142
147
  }
@@ -144,10 +149,10 @@ export function collectDocsPagesByTab(pageMap, tabs) {
144
149
  }
145
150
  export function rebuildMarkdownTabNavigation(pageMap, siteTabs, tabs, tabSlug, prettyUrls) {
146
151
  const tab = tabs.find((candidate) => candidate.slug === tabSlug);
147
- if (!tab?.groups)
152
+ if (!tab || tab.source.kind !== "markdown")
148
153
  return;
149
154
  const pagesByPath = new Map();
150
- for (const group of tab.groups) {
155
+ for (const group of tab.source.groups) {
151
156
  for (const rp of group.pages) {
152
157
  const slug = slugFromPath(rp.slug);
153
158
  const entry = pageMap.get(pageOutputPath(tab.slug, slug, prettyUrls));
@@ -241,6 +246,7 @@ export function createMinimalSpec() {
241
246
  }
242
247
  export function resolveInternalLinks(pages, config) {
243
248
  const pathMap = new Map();
249
+ addSourceAssetAliases(pathMap, config.tabs ?? []);
244
250
  for (const page of pages) {
245
251
  const out = page.outputPath;
246
252
  const clean = out.replace(/\/index\.html$/, "").replace(/\.html$/, "");
@@ -253,6 +259,10 @@ export function resolveInternalLinks(pages, config) {
253
259
  .replace(/^\/+/, "")
254
260
  .replace(/\.(md|mdx)$/, "");
255
261
  pathMap.set(sourceClean, out);
262
+ const sourceRelativeClean = getSourceRootRelativePath(page);
263
+ if (sourceRelativeClean) {
264
+ pathMap.set(sourceRelativeClean, out);
265
+ }
256
266
  }
257
267
  const repoBase = config.repo?.replace(/\/$/, "");
258
268
  const branch = config.editBranch;
@@ -263,6 +273,7 @@ export function resolveInternalLinks(pages, config) {
263
273
  if (!docsSourcePath)
264
274
  continue;
265
275
  if (page.currentPage.kind === "markdown") {
276
+ page.currentPage.markdown.description = rewriteMarkdownLinks(page.currentPage.markdown.description, page.outputPath, docsSourcePath, pathMap, sourceBase, prettyUrls);
266
277
  page.currentPage.markdown.html = rewriteHtmlLinks(page.currentPage.markdown.html, page.outputPath, docsSourcePath, pathMap, sourceBase, prettyUrls);
267
278
  continue;
268
279
  }
@@ -338,6 +349,15 @@ function attachChangelogFeeds(pages, config) {
338
349
  }
339
350
  return extraFiles;
340
351
  }
352
+ async function attachSourceAssets(extraFiles, tabs) {
353
+ for (const tab of tabs) {
354
+ if (tab.source.kind !== "markdown")
355
+ continue;
356
+ for (const asset of tab.source.assets ?? []) {
357
+ extraFiles.set(tabPath(tab.slug, asset.outputPath), await readFile(asset.file));
358
+ }
359
+ }
360
+ }
341
361
  function addPermalinkPages(pageMap, prettyUrls) {
342
362
  const changelogPages = Array.from(pageMap.values()).filter(isMainChangelogSitePage);
343
363
  for (const page of changelogPages) {
@@ -364,15 +384,15 @@ function addPermalinkPages(pageMap, prettyUrls) {
364
384
  async function loadSpecs(tabs) {
365
385
  const specsBySlug = new Map();
366
386
  for (const tab of tabs) {
367
- if (tab.openapi) {
368
- const loaded = await loadSpec(tab.openapi);
387
+ if (tab.source.kind === "openapi") {
388
+ const loaded = await loadSpec(tab.source.spec);
369
389
  const parsed = await parseSpec(loaded);
370
390
  const openapi3 = await convertToOpenApi3(parsed);
371
391
  specsBySlug.set(tab.slug, normalizeSpec(openapi3));
372
392
  }
373
- else if (tab.mcp) {
393
+ else if (tab.source.kind === "mcp") {
374
394
  const { parse } = await import("mcp-parser");
375
- const mcpSpec = await parse(tab.mcp);
395
+ const mcpSpec = await parse(tab.source.spec);
376
396
  specsBySlug.set(tab.slug, normalizeMcpSpec(mcpSpec));
377
397
  }
378
398
  }
@@ -395,7 +415,10 @@ const MIME_TYPES = {
395
415
  ".ico": "image/x-icon",
396
416
  };
397
417
  async function resolveAssetUrl(pathOrUrl) {
398
- if (!pathOrUrl || pathOrUrl.startsWith("data:") || pathOrUrl.startsWith("http://") || pathOrUrl.startsWith("https://")) {
418
+ if (!pathOrUrl ||
419
+ pathOrUrl.startsWith("data:") ||
420
+ pathOrUrl.startsWith("http://") ||
421
+ pathOrUrl.startsWith("https://")) {
399
422
  return pathOrUrl;
400
423
  }
401
424
  const abs = resolve(pathOrUrl);
@@ -409,6 +432,9 @@ function isMainChangelogSitePage(page) {
409
432
  function isSearchableDocsSitePage(page) {
410
433
  return page.currentPage.kind === "markdown" || isMainChangelogSitePage(page);
411
434
  }
435
+ function isDocsSource(kind) {
436
+ return kind === "markdown" || kind === "doxygen" || kind === "godoc";
437
+ }
412
438
  function createFeedLinks(atomPath, rssPath, title) {
413
439
  return [
414
440
  { href: atomPath, type: "application/atom+xml", title: `${title} Atom Feed` },
@@ -429,26 +455,74 @@ function getDocsSourcePath(page) {
429
455
  return page.currentPage.changelog.sourcePath;
430
456
  return undefined;
431
457
  }
458
+ function getSourceRootRelativePath(page) {
459
+ if (page.currentPage.kind !== "markdown")
460
+ return undefined;
461
+ const markdown = page.currentPage.markdown;
462
+ if (!markdown.sourceRoot)
463
+ return undefined;
464
+ const sourceRoot = normalizeSourcePath(markdown.sourceRoot);
465
+ const sourcePath = normalizeSourcePath(markdown.sourcePath);
466
+ if (!sourcePath.startsWith(`${sourceRoot}/`))
467
+ return undefined;
468
+ return stripMarkdownExtension(sourcePath.slice(sourceRoot.length + 1));
469
+ }
470
+ function addSourceAssetAliases(pathMap, tabs) {
471
+ for (const tab of tabs) {
472
+ if (tab.source.kind !== "markdown")
473
+ continue;
474
+ for (const asset of tab.source.assets ?? []) {
475
+ const outputPath = tabPath(tab.slug, asset.outputPath);
476
+ pathMap.set(normalizeSourcePath(asset.outputPath), outputPath);
477
+ for (const sourceRoot of sourceRootsForMarkdownSource(tab.source)) {
478
+ const sourceRootPath = normalizeSourcePath(relative(process.cwd(), sourceRoot));
479
+ pathMap.set(posix.join(sourceRootPath, normalizeSourcePath(asset.outputPath)), outputPath);
480
+ }
481
+ }
482
+ }
483
+ }
484
+ function sourceRootsForMarkdownSource(source) {
485
+ const roots = new Set();
486
+ for (const group of source.groups) {
487
+ for (const page of group.pages) {
488
+ if (page.sourceRoot)
489
+ roots.add(page.sourceRoot);
490
+ }
491
+ }
492
+ return [...roots];
493
+ }
494
+ function normalizeSourcePath(value) {
495
+ return value.replace(/\\/g, "/").replace(/^\/+/, "");
496
+ }
497
+ function stripMarkdownExtension(value) {
498
+ return value.replace(/\.(md|mdx)$/, "");
499
+ }
432
500
  function rewriteHtmlLinks(html, outputPath, docsSourcePath, pathMap, sourceBase, prettyUrls) {
433
- return html.replace(/href="([^"]+)"/g, (match, href) => {
501
+ return html.replace(/\b(href|src)="([^"]+)"/g, (match, attr, href) => {
434
502
  const resolved = resolveInternalHref(href, outputPath, docsSourcePath, pathMap, sourceBase, prettyUrls);
435
- return resolved ? `href="${resolved}"` : match;
503
+ return resolved ? `${attr}="${resolved}"` : match;
436
504
  });
437
505
  }
438
506
  function rewriteMarkdownLinks(markdown, outputPath, docsSourcePath, pathMap, sourceBase, prettyUrls) {
439
- return markdown.replace(/\[([^\]]+)\]\(([^)]+)\)/g, (match, label, href) => {
507
+ return markdown.replace(/\[((?:`[^`]*`|[^\]])+)\]\(([^)]+)\)/g, (match, label, href) => {
440
508
  const resolved = resolveInternalHref(href, outputPath, docsSourcePath, pathMap, sourceBase, prettyUrls);
441
509
  return resolved ? `[${label}](${resolved})` : match;
442
510
  });
443
511
  }
444
512
  function resolveInternalHref(href, outputPath, docsSourcePath, pathMap, sourceBase, prettyUrls) {
445
- if (href.startsWith("http://") || href.startsWith("https://") || href.startsWith("#") || href.startsWith("mailto:")) {
513
+ if (href.startsWith("http://") ||
514
+ href.startsWith("https://") ||
515
+ href.startsWith("#") ||
516
+ href.startsWith("mailto:")) {
446
517
  return null;
447
518
  }
448
519
  const [path, hash] = href.split("#", 2);
449
520
  const hashSuffix = hash ? `#${hash}` : "";
450
- const sourcePath = path.replace(/\\/g, "/");
451
- const clean = sourcePath.replace(/^\/+/, "").replace(/\/+$/, "").replace(/\.(md|mdx|html)$/, "");
521
+ const sourcePath = decodeHrefPath(path).replace(/\\/g, "/");
522
+ const clean = sourcePath
523
+ .replace(/^\/+/, "")
524
+ .replace(/\/+$/, "")
525
+ .replace(/\.(md|mdx|html)$/, "");
452
526
  const pageDir = outputPath.includes("/")
453
527
  ? outputPath.substring(0, outputPath.lastIndexOf("/"))
454
528
  : "";
@@ -490,6 +564,14 @@ function resolveInternalHref(href, outputPath, docsSourcePath, pathMap, sourceBa
490
564
  }
491
565
  return null;
492
566
  }
567
+ function decodeHrefPath(path) {
568
+ try {
569
+ return decodeURIComponent(path);
570
+ }
571
+ catch {
572
+ return path;
573
+ }
574
+ }
493
575
  /**
494
576
  * Rewrite an on-disk output path into the relative href that a user visits.
495
577
  * - `"slash"`: trims trailing `index.html`, leaves a directory-style `foo/`.
@@ -506,7 +588,7 @@ function toPrettyLink(target, prettyUrls) {
506
588
  return prettyUrls === "strip" ? withSlash.slice(0, -1) : withSlash;
507
589
  }
508
590
  if (prettyUrls === "strip" && target.endsWith(".html")) {
509
- return target.slice(0, -(".html".length));
591
+ return target.slice(0, -".html".length);
510
592
  }
511
593
  return target;
512
594
  }
@@ -1 +1 @@
1
- {"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/utils/markdown.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,KAAK,KAAK,EAAe,MAAM,QAAQ,CAAC;AAKzD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CASnE;AAED,4CAA4C;AAC5C,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,CAAC,GAAG,CAAC,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;CACZ;AAgJD;;;GAGG;AACH,wBAAgB,WAAW,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,KAAK,EAAE,CAGnD;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,EAAE,CAe5D;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAY5D;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAGzD;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAGrD;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAG3D"}
1
+ {"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/utils/markdown.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,KAAK,KAAK,EAAe,MAAM,QAAQ,CAAC;AAOzD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CASnE;AAED,4CAA4C;AAC5C,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,CAAC,GAAG,CAAC,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;CACZ;AA2JD;;;GAGG;AACH,wBAAgB,WAAW,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,KAAK,EAAE,CAGnD;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,EAAE,CAe5D;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAY5D;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAGzD;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAGrD;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAG3D"}
@@ -2,6 +2,7 @@ import { Marked } from "marked";
2
2
  import { highlightCode } from "./highlighter.js";
3
3
  import { COPY_ICON_SVG } from "./copy-svg.js";
4
4
  import { htmlId } from "./html-id.js";
5
+ const MARKDOWN_LINK_RE = /\[((?:`[^`]*`|[^\]])+)\]\(([^)]+)\)/g;
5
6
  /**
6
7
  * Shared code block renderer used by all markdown rendering.
7
8
  * Outputs the prose-code-block wrapper with copy button and Shiki highlighting.
@@ -98,7 +99,13 @@ const iframeExtension = {
98
99
  return undefined;
99
100
  const attrs = parseDirectiveAttrs(match[2] ?? "");
100
101
  const height = parseInt(attrs.height ?? "", 10);
101
- return { type: "iframe", raw: match[0], url: match[1], title: attrs.title ?? "", height: Number.isFinite(height) ? height : 400 };
102
+ return {
103
+ type: "iframe",
104
+ raw: match[0],
105
+ url: match[1],
106
+ title: attrs.title ?? "",
107
+ height: Number.isFinite(height) ? height : 400,
108
+ };
102
109
  },
103
110
  renderer(token) {
104
111
  const { url, title, height } = token;
@@ -124,8 +131,12 @@ const marked = new Marked(videoExtension, iframeExtension, {
124
131
  return `<h${depth} id="${id}">${this.parser.parseInline(tokens)}</h${depth}>\n`;
125
132
  },
126
133
  table(token) {
127
- const header = token.header.map((cell) => `<th>${this.parser.parseInline(cell.tokens)}</th>`).join("");
128
- const body = token.rows.map((row) => `<tr>${row.map((cell) => `<td>${this.parser.parseInline(cell.tokens)}</td>`).join("")}</tr>`).join("\n");
134
+ const header = token.header
135
+ .map((cell) => `<th>${this.parser.parseInline(cell.tokens)}</th>`)
136
+ .join("");
137
+ const body = token.rows
138
+ .map((row) => `<tr>${row.map((cell) => `<td>${this.parser.parseInline(cell.tokens)}</td>`).join("")}</tr>`)
139
+ .join("\n");
129
140
  return `<div class="table-wrap"><table><thead><tr>${header}</tr></thead><tbody>${body}</tbody></table></div>`;
130
141
  },
131
142
  link({ href, title, tokens }) {
@@ -193,7 +204,7 @@ export function extractFirstParagraph(input) {
193
204
  export function stripMarkdownLinks(input) {
194
205
  if (!input)
195
206
  return "";
196
- return input.replace(/\[([^\]]+)\]\(([^)]+)\)/g, "$1");
207
+ return input.replace(MARKDOWN_LINK_RE, "$1");
197
208
  }
198
209
  /**
199
210
  * Render Markdown to HTML.