sourcey 3.6.0 → 3.6.2

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 (86) hide show
  1. package/README.md +5 -2
  2. package/dist/adapters/index.d.ts +3 -2
  3. package/dist/adapters/index.d.ts.map +1 -1
  4. package/dist/adapters/index.js +35 -3
  5. package/dist/adapters/types.d.ts +8 -2
  6. package/dist/adapters/types.d.ts.map +1 -1
  7. package/dist/cli.js +28 -34
  8. package/dist/client/search.js +181 -119
  9. package/dist/client/tabs.js +23 -0
  10. package/dist/components/layout/Head.d.ts.map +1 -1
  11. package/dist/components/layout/Head.js +7 -6
  12. package/dist/components/openapi/Introduction.d.ts.map +1 -1
  13. package/dist/components/openapi/Introduction.js +16 -1
  14. package/dist/components/openapi/Security.d.ts.map +1 -1
  15. package/dist/components/openapi/Security.js +18 -2
  16. package/dist/config.d.ts +70 -0
  17. package/dist/config.d.ts.map +1 -1
  18. package/dist/config.js +23 -7
  19. package/dist/core/api-rendering.d.ts +47 -0
  20. package/dist/core/api-rendering.d.ts.map +1 -0
  21. package/dist/core/api-rendering.js +76 -0
  22. package/dist/core/doxygen-loader.d.ts +1 -1
  23. package/dist/core/doxygen-loader.d.ts.map +1 -1
  24. package/dist/core/doxygen-loader.js +37 -19
  25. package/dist/core/godoc-loader.d.ts.map +1 -1
  26. package/dist/core/godoc-loader.js +17 -6
  27. package/dist/core/markdown-loader.d.ts.map +1 -1
  28. package/dist/core/markdown-loader.js +8 -5
  29. package/dist/core/mcp-normalizer.d.ts.map +1 -1
  30. package/dist/core/mcp-normalizer.js +48 -34
  31. package/dist/core/parser.d.ts.map +1 -1
  32. package/dist/core/parser.js +75 -4
  33. package/dist/core/rustdoc-introspector.d.ts +29 -0
  34. package/dist/core/rustdoc-introspector.d.ts.map +1 -0
  35. package/dist/core/rustdoc-introspector.js +236 -0
  36. package/dist/core/rustdoc-loader.d.ts +25 -0
  37. package/dist/core/rustdoc-loader.d.ts.map +1 -0
  38. package/dist/core/rustdoc-loader.js +472 -0
  39. package/dist/core/rustdoc-render.d.ts +82 -0
  40. package/dist/core/rustdoc-render.d.ts.map +1 -0
  41. package/dist/core/rustdoc-render.js +808 -0
  42. package/dist/core/rustdoc-types.d.ts +314 -0
  43. package/dist/core/rustdoc-types.d.ts.map +1 -0
  44. package/dist/core/rustdoc-types.js +18 -0
  45. package/dist/core/search-indexer.js +1 -1
  46. package/dist/core/sourcey-rustdoc/Cargo.lock +705 -0
  47. package/dist/core/sourcey-rustdoc/Cargo.toml +38 -0
  48. package/dist/core/sourcey-rustdoc/README.md +59 -0
  49. package/dist/core/sourcey-rustdoc/src/diagnostics.rs +42 -0
  50. package/dist/core/sourcey-rustdoc/src/doctest.rs +268 -0
  51. package/dist/core/sourcey-rustdoc/src/extract.rs +492 -0
  52. package/dist/core/sourcey-rustdoc/src/lib.rs +58 -0
  53. package/dist/core/sourcey-rustdoc/src/links.rs +126 -0
  54. package/dist/core/sourcey-rustdoc/src/main.rs +256 -0
  55. package/dist/core/sourcey-rustdoc/src/signature.rs +415 -0
  56. package/dist/core/sourcey-rustdoc/src/spec.rs +390 -0
  57. package/dist/core/sourcey-rustdoc/tests/format_version.rs +45 -0
  58. package/dist/dev-server.d.ts.map +1 -1
  59. package/dist/dev-server.js +50 -1
  60. package/dist/index.d.ts +4 -2
  61. package/dist/index.d.ts.map +1 -1
  62. package/dist/index.js +22 -13
  63. package/dist/init.js +2 -2
  64. package/dist/renderer/changelog-feed.d.ts.map +1 -1
  65. package/dist/renderer/changelog-feed.js +27 -19
  66. package/dist/renderer/context.d.ts +1 -0
  67. package/dist/renderer/context.d.ts.map +1 -1
  68. package/dist/renderer/html-builder.d.ts.map +1 -1
  69. package/dist/renderer/html-builder.js +4 -3
  70. package/dist/renderer/llms.js +57 -2
  71. package/dist/site-assembly.d.ts +5 -0
  72. package/dist/site-assembly.d.ts.map +1 -1
  73. package/dist/site-assembly.js +57 -2
  74. package/dist/themes/default/sourcey.css +300 -0
  75. package/dist/utils/code-samples.d.ts +1 -0
  76. package/dist/utils/code-samples.d.ts.map +1 -1
  77. package/dist/utils/code-samples.js +30 -22
  78. package/dist/utils/html.d.ts +10 -0
  79. package/dist/utils/html.d.ts.map +1 -0
  80. package/dist/utils/html.js +152 -0
  81. package/dist/utils/http.d.ts +0 -2
  82. package/dist/utils/http.d.ts.map +1 -1
  83. package/dist/utils/http.js +19 -34
  84. package/dist/utils/markdown.d.ts.map +1 -1
  85. package/dist/utils/markdown.js +102 -37
  86. package/package.json +10 -5
@@ -1,12 +1,15 @@
1
+ import { renderMarkdownInline } from "../utils/markdown.js";
1
2
  export function generateChangelogFeeds(page, options) {
2
3
  const buildDate = options.buildDate ?? new Date();
3
- const updated = page.changelog.versions
4
- .map((version) => version.date ? new Date(`${version.date}T00:00:00Z`) : null)
5
- .find(Boolean) ?? buildDate;
4
+ const datedVersions = page.changelog.versions
5
+ .map((version) => (version.date ? new Date(`${version.date}T00:00:00Z`).getTime() : NaN))
6
+ .filter(Number.isFinite);
7
+ const updated = datedVersions.length ? new Date(Math.max(...datedVersions)) : buildDate;
6
8
  const title = options.title ?? [options.siteName, page.title].filter(Boolean).join(" ").trim();
7
9
  const description = options.description ?? page.description ?? `${page.title} feed`;
8
10
  const feedId = toFeedId(options.atomPath);
9
- const atomEntries = page.changelog.versions.map((version) => {
11
+ const atomEntries = page.changelog.versions
12
+ .map((version) => {
10
13
  const href = options.versionHref(version);
11
14
  const content = renderVersionHtml(version);
12
15
  const updatedAt = version.date ? new Date(`${version.date}T00:00:00Z`) : updated;
@@ -20,25 +23,28 @@ export function generateChangelogFeeds(page, options) {
20
23
  ` <content type="html">${escapeXml(content)}</content>`,
21
24
  " </entry>",
22
25
  ].join("\n");
23
- }).join("\n");
26
+ })
27
+ .join("\n");
24
28
  const atom = [
25
29
  `<?xml version="1.0" encoding="UTF-8"?>`,
26
30
  `<feed xmlns="http://www.w3.org/2005/Atom">`,
27
31
  ` <title>${escapeXml(title)}</title>`,
28
32
  ` <id>${escapeXml(feedId)}</id>`,
29
33
  ` <updated>${updated.toISOString()}</updated>`,
34
+ ` <author><name>${escapeXml(options.siteName || title)}</name></author>`,
30
35
  ` <subtitle>${escapeXml(description)}</subtitle>`,
31
36
  ` <link rel="self" href="${escapeXml(options.atomPath)}" />`,
32
37
  ` <link href="${escapeXml(options.pagePath)}" />`,
33
38
  page.changelog.versions.length ? atomEntries : "",
34
39
  `</feed>`,
35
- ].filter(Boolean).join("\n");
36
- const rssItems = page.changelog.versions.map((version) => {
40
+ ]
41
+ .filter(Boolean)
42
+ .join("\n");
43
+ const rssItems = page.changelog.versions
44
+ .map((version) => {
37
45
  const href = options.versionHref(version);
38
46
  const label = version.version ?? "Unreleased";
39
- const pubDate = version.date
40
- ? new Date(`${version.date}T00:00:00Z`)
41
- : updated;
47
+ const pubDate = version.date ? new Date(`${version.date}T00:00:00Z`) : updated;
42
48
  return [
43
49
  " <item>",
44
50
  ` <title>${escapeXml(label)}</title>`,
@@ -48,7 +54,8 @@ export function generateChangelogFeeds(page, options) {
48
54
  ` <description>${escapeXml(renderVersionHtml(version))}</description>`,
49
55
  " </item>",
50
56
  ].join("\n");
51
- }).join("\n");
57
+ })
58
+ .join("\n");
52
59
  const rss = [
53
60
  `<?xml version="1.0" encoding="UTF-8"?>`,
54
61
  `<rss version="2.0">`,
@@ -59,15 +66,19 @@ export function generateChangelogFeeds(page, options) {
59
66
  page.changelog.versions.length ? rssItems : "",
60
67
  ` </channel>`,
61
68
  `</rss>`,
62
- ].filter(Boolean).join("\n");
69
+ ]
70
+ .filter(Boolean)
71
+ .join("\n");
63
72
  return { atom, rss };
64
73
  }
65
74
  function renderVersionHtml(version) {
66
- const summary = version.summary ? `<p>${escapeHtml(version.summary)}</p>` : "";
67
- const sections = version.sections.map((section) => {
75
+ const summary = version.summary ? `<p>${renderMarkdownInline(version.summary)}</p>` : "";
76
+ const sections = version.sections
77
+ .map((section) => {
68
78
  const items = section.entries.map((entry) => `<li>${entry.html}</li>`).join("");
69
79
  return `<section><h3>${escapeHtml(section.label)}</h3><ul>${items}</ul></section>`;
70
- }).join("");
80
+ })
81
+ .join("");
71
82
  return `<article><h2>${escapeHtml(version.version ?? "Unreleased")}</h2>${summary}${sections}</article>`;
72
83
  }
73
84
  function escapeXml(value) {
@@ -79,10 +90,7 @@ function escapeXml(value) {
79
90
  .replace(/'/g, "&apos;");
80
91
  }
81
92
  function escapeHtml(value) {
82
- return value
83
- .replace(/&/g, "&amp;")
84
- .replace(/</g, "&lt;")
85
- .replace(/>/g, "&gt;");
93
+ return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
86
94
  }
87
95
  function toFeedId(value) {
88
96
  if (value.startsWith("http://") || value.startsWith("https://"))
@@ -63,6 +63,7 @@ export declare const PageContext: import("preact").Context<CurrentPage>;
63
63
  */
64
64
  export interface SiteConfig {
65
65
  name: string;
66
+ titleSeparator: string;
66
67
  siteUrl?: string;
67
68
  baseUrl: string;
68
69
  prettyUrls: PrettyUrls;
@@ -1 +1 @@
1
- {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/renderer/context.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC9E,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,uBAAuB,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAEnG,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,mEAAmE;IACnE,UAAU,EAAE,OAAO,CAAC;IACpB,oCAAoC;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,oEAAoE;IACpE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iDAAiD;IACjD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,wDAAwD;IACxD,cAAc,CAAC,EAAE,aAAa,EAAE,CAAC;CAClC;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,cAAc,CAAC;IACrB,OAAO,EAAE,aAAa,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,MAAM,WAAW,GACnB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,cAAc,CAAA;CAAE,GACtC;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,EAAE,YAAY,CAAA;CAAE,GAC5C;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,SAAS,EAAE,aAAa,CAAA;CAAE,CAAC;AAEpD;;GAEG;AACH,eAAO,MAAM,WAAW,0CAA+C,CAAC;AAExE;;GAEG;AACH,eAAO,MAAM,cAAc,yCAGzB,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,iBAAiB,0CAA+C,CAAC;AAE9E;;GAEG;AACH,eAAO,MAAM,WAAW,uCAA4C,CAAC;AAErE;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,UAAU,CAAC;IACvB,KAAK,EAAE,aAAa,CAAC;IACrB,IAAI,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACxD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,MAAM,EAAE;QAAE,KAAK,EAAE,UAAU,EAAE,CAAC;QAAC,OAAO,CAAC,EAAE;YAAE,IAAI,EAAE,QAAQ,CAAC;YAAC,KAAK,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAC;IAC3F,MAAM,EAAE;QAAE,KAAK,EAAE,UAAU,EAAE,CAAA;KAAE,CAAC;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,uBAAuB,CAAC;CACpC;AAED,eAAO,MAAM,WAAW,sCAA2C,CAAC"}
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/renderer/context.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC9E,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,uBAAuB,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAEnG,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,mEAAmE;IACnE,UAAU,EAAE,OAAO,CAAC;IACpB,oCAAoC;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,oEAAoE;IACpE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iDAAiD;IACjD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,wDAAwD;IACxD,cAAc,CAAC,EAAE,aAAa,EAAE,CAAC;CAClC;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,cAAc,CAAC;IACrB,OAAO,EAAE,aAAa,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,MAAM,WAAW,GACnB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,cAAc,CAAA;CAAE,GACtC;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,EAAE,YAAY,CAAA;CAAE,GAC5C;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,SAAS,EAAE,aAAa,CAAA;CAAE,CAAC;AAEpD;;GAEG;AACH,eAAO,MAAM,WAAW,0CAA+C,CAAC;AAExE;;GAEG;AACH,eAAO,MAAM,cAAc,yCAGzB,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,iBAAiB,0CAA+C,CAAC;AAE9E;;GAEG;AACH,eAAO,MAAM,WAAW,uCAA4C,CAAC;AAErE;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,UAAU,CAAC;IACvB,KAAK,EAAE,aAAa,CAAC;IACrB,IAAI,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACxD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,MAAM,EAAE;QAAE,KAAK,EAAE,UAAU,EAAE,CAAC;QAAC,OAAO,CAAC,EAAE;YAAE,IAAI,EAAE,QAAQ,CAAC;YAAC,KAAK,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAC;IAC3F,MAAM,EAAE;QAAE,KAAK,EAAE,UAAU,EAAE,CAAA;KAAE,CAAC;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,uBAAuB,CAAC;CACpC;AAED,eAAO,MAAM,WAAW,sCAA2C,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"html-builder.d.ts","sourceRoot":"","sources":["../../src/renderer/html-builder.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1F,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AA2B5D,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,QAAQ;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,WAAW,CAAC;IACzB,IAAI,EAAE,cAAc,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,iEAAiE;IACjE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,aAAa,EAAE,CAAC;CAClC;AAED,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,QAAQ,EACd,IAAI,EAAE,UAAU,EAChB,OAAO,CAAC,EAAE;IACR,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GACA,aAAa,CAcf;AAED;;GAEG;AACH,wBAAsB,SAAS,CAC7B,KAAK,EAAE,QAAQ,EAAE,EACjB,UAAU,EAAE,cAAc,EAC1B,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,UAAU,EAChB,OAAO,CAAC,EAAE;IACR,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,UAAU,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;CAC3C,GACA,OAAO,CAAC,WAAW,CAAC,CA8EtB"}
1
+ {"version":3,"file":"html-builder.d.ts","sourceRoot":"","sources":["../../src/renderer/html-builder.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1F,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAiC5D,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,QAAQ;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,WAAW,CAAC;IACzB,IAAI,EAAE,cAAc,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,iEAAiE;IACjE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,aAAa,EAAE,CAAC;CAClC;AAED,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,QAAQ,EACd,IAAI,EAAE,UAAU,EAChB,OAAO,CAAC,EAAE;IACR,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GACA,aAAa,CAcf;AAED;;GAEG;AACH,wBAAsB,SAAS,CAC7B,KAAK,EAAE,QAAQ,EAAE,EACjB,UAAU,EAAE,cAAc,EAC1B,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,UAAU,EAChB,OAAO,CAAC,EAAE;IACR,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,UAAU,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;CAC3C,GACA,OAAO,CAAC,WAAW,CAAC,CA8EtB"}
@@ -7,6 +7,7 @@ import preact from "@preact/preset-vite";
7
7
  import { renderPage } from "./static-renderer.js";
8
8
  import { withActivePage } from "../core/navigation.js";
9
9
  import { isAbsoluteHttpUrl, toAbsoluteUrl, toPublicPath } from "../site-url.js";
10
+ import { escapeHtml as escapeXml } from "../utils/html.js";
10
11
  const __dirname = dirname(fileURLToPath(import.meta.url));
11
12
  const projectRoot = resolve(__dirname, "../..");
12
13
  async function exists(path) {
@@ -27,8 +28,8 @@ async function resolveAssetPaths() {
27
28
  const distClient = resolve(projectRoot, "dist/client/index.js");
28
29
  const srcCss = resolve(projectRoot, "src/themes/default/sourcey.css");
29
30
  const distCss = resolve(projectRoot, "dist/themes/default/sourcey.css");
30
- const clientEntry = await exists(srcClient) ? srcClient : distClient;
31
- const sourceyCssPath = await exists(srcCss) ? srcCss : distCss;
31
+ const clientEntry = (await exists(srcClient)) ? srcClient : distClient;
32
+ const sourceyCssPath = (await exists(srcCss)) ? srcCss : distCss;
32
33
  return { clientEntry, sourceyCssPath };
33
34
  }
34
35
  export function createRenderOptions(page, site, options) {
@@ -88,7 +89,7 @@ export async function buildSite(pages, navigation, outputDir, site, options) {
88
89
  const urls = pages.map((page) => {
89
90
  const publicPath = toPublicPath(page.outputPath, site.baseUrl, site.prettyUrls);
90
91
  const loc = site.siteUrl ? toAbsoluteUrl(publicPath, site.siteUrl) : publicPath;
91
- return ` <url><loc>${loc}</loc></url>`;
92
+ return ` <url><loc>${escapeXml(loc)}</loc></url>`;
92
93
  });
93
94
  const sitemap = [
94
95
  `<?xml version="1.0" encoding="UTF-8"?>`,
@@ -41,7 +41,7 @@ export function generateLlmsTxt(pages, navigation, site) {
41
41
  if (op.hidden)
42
42
  continue;
43
43
  const opLabel = op.summary ?? operationDisplayName(op);
44
- const opSummary = [operationKind(op), firstLine(op.description)].filter(Boolean).join(" ");
44
+ const opSummary = [operationKind(op), firstLine(op.description)].filter(Boolean).join(" - ");
45
45
  lines.push(`- [${opLabel}](${href(page)}#${operationAnchor(op)})${opSummary ? `: ${opSummary}` : ""}`);
46
46
  }
47
47
  }
@@ -92,6 +92,15 @@ function appendMarkdownPage(lines, page, site) {
92
92
  lines.push(doc.description);
93
93
  lines.push("");
94
94
  }
95
+ const isRustdoc = doc.sourcePath?.startsWith("rustdoc/");
96
+ if (isRustdoc) {
97
+ const body = stripHtmlPreservingRustDoctests(doc.html);
98
+ if (body) {
99
+ lines.push(body);
100
+ lines.push("");
101
+ }
102
+ return;
103
+ }
95
104
  const body = stripHtml(doc.html);
96
105
  if (body) {
97
106
  lines.push(body);
@@ -207,7 +216,7 @@ function appendOperation(lines, op) {
207
216
  const type = param.schema
208
217
  ? formatSchemaType(param.schema)
209
218
  : firstContentSchemaType(param.content);
210
- const desc = param.description ? ` ${firstLine(param.description)}` : "";
219
+ const desc = param.description ? ` - ${firstLine(param.description)}` : "";
211
220
  lines.push(`- \`${param.name}\` (${param.in}, ${type}, ${req})${desc}`);
212
221
  }
213
222
  lines.push("");
@@ -337,6 +346,52 @@ function stripHtml(html) {
337
346
  .replace(/\s+/g, " ")
338
347
  .trim();
339
348
  }
349
+ /**
350
+ * Like stripHtml but preserves rustdoc doctest <pre><code> blocks as
351
+ * fenced ```rust ... ``` so they remain useful as runnable examples in
352
+ * llms-full.txt. Section headings and item names are also kept.
353
+ */
354
+ function stripHtmlPreservingRustDoctests(html) {
355
+ const tokens = [];
356
+ const sectionRe = /<section class="rust-item rust-([a-z_]+) api-item"[^>]*>([\s\S]*?)<\/section>/g;
357
+ let lastIndex = 0;
358
+ let prose = "";
359
+ for (const match of html.matchAll(sectionRe)) {
360
+ prose += html.slice(lastIndex, match.index ?? 0);
361
+ lastIndex = (match.index ?? 0) + match[0].length;
362
+ tokens.push(formatRustItemForLlms(match[2], match[1]));
363
+ }
364
+ prose += html.slice(lastIndex);
365
+ const proseText = stripHtml(prose);
366
+ const parts = [];
367
+ if (proseText)
368
+ parts.push(proseText);
369
+ if (tokens.length > 0)
370
+ parts.push(tokens.join("\n\n"));
371
+ return parts.join("\n\n").trim();
372
+ }
373
+ function formatRustItemForLlms(inner, kind) {
374
+ const titleMatch = inner.match(/<h4[^>]*class="[^"]*code-header[^"]*"[^>]*>([\s\S]*?)<\/h4>/);
375
+ const title = titleMatch ? stripHtml(titleMatch[1]) : "";
376
+ const docMatch = inner.match(/<div class="docblock[^"]*"[^>]*>([\s\S]*?)<\/div>/);
377
+ const docText = docMatch ? stripHtml(docMatch[1]) : "";
378
+ // The visible doctest renders through the shared Shiki code block. Match the
379
+ // `rust-doctest-code` wrapper (exact class, so the hidden `-full` variant is
380
+ // skipped), pull the inner Shiki <code>, then strip span tags while keeping
381
+ // line breaks so the extracted code stays readable.
382
+ const doctests = Array.from(inner.matchAll(/<div class="rust-doctest-code" id="[^"]*">[\s\S]*?<pre class="shiki[^"]*"[^>]*><code[^>]*>([\s\S]*?)<\/code><\/pre>/g)).map((m) => decodeEntities(m[1].replace(/<[^>]+>/g, "")).replace(/\n{3,}/g, "\n\n").trimEnd());
383
+ const out = [];
384
+ if (title)
385
+ out.push(`#### ${kind}: ${title}`);
386
+ if (docText)
387
+ out.push(docText);
388
+ for (const code of doctests) {
389
+ out.push("```rust");
390
+ out.push(code);
391
+ out.push("```");
392
+ }
393
+ return out.join("\n");
394
+ }
340
395
  function decodeEntities(text) {
341
396
  return text
342
397
  .replace(/&nbsp;/g, " ")
@@ -1,4 +1,5 @@
1
1
  import { type GodocLoaderDiagnostic } from "./core/godoc-loader.js";
2
+ import { type RustdocLoaderDiagnostic } from "./core/rustdoc-loader.js";
2
3
  import type { PrettyUrls, ResolvedConfig, ResolvedTab } from "./config.js";
3
4
  import type { DocsPage } from "./core/markdown-loader.js";
4
5
  import type { SiteTab } from "./core/navigation.js";
@@ -12,10 +13,14 @@ export interface SiteAssembly {
12
13
  pageMap: Map<string, SitePage>;
13
14
  changelogDiagnostics: ChangelogDiagnostic[];
14
15
  godocDiagnostics: GodocLoaderDiagnostic[];
16
+ rustdocDiagnostics: RustdocLoaderDiagnostic[];
15
17
  extraFiles: Map<string, string | Buffer>;
16
18
  }
17
19
  export declare function assembleSite(config: ResolvedConfig): Promise<SiteAssembly>;
18
20
  export declare function formatGodocDiagnostic(diag: GodocLoaderDiagnostic): string;
21
+ export declare function enforceGodocDiagnostics(diagnostics: GodocLoaderDiagnostic[]): void;
22
+ export declare function enforceRustdocDiagnostics(diagnostics: RustdocLoaderDiagnostic[]): void;
23
+ export declare function formatRustdocDiagnostic(diagnostic: RustdocLoaderDiagnostic): string;
19
24
  export declare function collectDocsPagesByTab(pageMap: Map<string, SitePage>, tabs: ResolvedTab[]): Map<string, DocsPage[]>;
20
25
  export declare function rebuildMarkdownTabNavigation(pageMap: Map<string, SitePage>, siteTabs: SiteTab[], tabs: ResolvedTab[], tabSlug: string, prettyUrls: PrettyUrls): void;
21
26
  export declare function enforceChangelogDiagnostics(diagnostics: ChangelogDiagnostic[], strictChangelog?: boolean): void;
@@ -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;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
+ {"version":3,"file":"site-assembly.d.ts","sourceRoot":"","sources":["../src/site-assembly.ts"],"names":[],"mappings":"AASA,OAAO,EAAgB,KAAK,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAClF,OAAO,EAAkB,KAAK,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AAIxF,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,kBAAkB,EAAE,uBAAuB,EAAE,CAAC;IAC9C,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;CAC1C;AAED,wBAAsB,YAAY,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,YAAY,CAAC,CAiKhF;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,qBAAqB,GAAG,MAAM,CAKzE;AAED,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,qBAAqB,EAAE,GAAG,IAAI,CAGlF;AAED,wBAAgB,yBAAyB,CAAC,WAAW,EAAE,uBAAuB,EAAE,GAAG,IAAI,CAGtF;AAUD,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,uBAAuB,GAAG,MAAM,CAMnF;AAUD,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,CA6BjF;AAED,wBAAgB,iBAAiB,IAAI,cAAc,CAUlD;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE,MAAM,EAAE,cAAc,GAAG,IAAI,CA6FpF"}
@@ -8,6 +8,7 @@ import { normalizeMcpSpec } from "./core/mcp-normalizer.js";
8
8
  import { loadDocsPage, slugFromPath } from "./core/markdown-loader.js";
9
9
  import { loadDoxygenTab } from "./core/doxygen-loader.js";
10
10
  import { loadGodocTab } from "./core/godoc-loader.js";
11
+ import { loadRustdocTab } from "./core/rustdoc-loader.js";
11
12
  import { buildNavFromSpec, buildNavFromPages } from "./core/navigation.js";
12
13
  import { generateChangelogFeeds } from "./renderer/changelog-feed.js";
13
14
  import { pageOutputPath, tabIndexOutputPath, tabPath } from "./config.js";
@@ -19,6 +20,7 @@ export async function assembleSite(config) {
19
20
  const siteTabs = [];
20
21
  const changelogDiagnostics = [];
21
22
  const godocDiagnostics = [];
23
+ const rustdocDiagnostics = [];
22
24
  for (const tab of config.tabs) {
23
25
  if (tab.source.kind === "openapi" || tab.source.kind === "mcp") {
24
26
  const spec = specsBySlug.get(tab.slug);
@@ -36,7 +38,7 @@ export async function assembleSite(config) {
36
38
  continue;
37
39
  }
38
40
  if (tab.source.kind === "doxygen") {
39
- const { pages, navTab } = await loadDoxygenTab(tab.source.config, tab.slug, tab.label);
41
+ const { pages, navTab } = await loadDoxygenTab(tab.source.config, tab.slug, tab.label, config.titleSeparator);
40
42
  for (const [slug, page] of pages) {
41
43
  const outputPath = pageOutputPath(tab.slug, slug, config.prettyUrls);
42
44
  pageMap.set(outputPath, {
@@ -70,6 +72,26 @@ export async function assembleSite(config) {
70
72
  siteTabs.push(navTab);
71
73
  continue;
72
74
  }
75
+ if (tab.source.kind === "rustdoc") {
76
+ const { pages, navTab, diagnostics } = await loadRustdocTab(tab.source.config, tab.slug, tab.label, {
77
+ repo: config.repo,
78
+ editBranch: config.editBranch,
79
+ editBasePath: tab.source.config.sourceBasePath,
80
+ });
81
+ rustdocDiagnostics.push(...diagnostics);
82
+ for (const [slug, page] of pages) {
83
+ const outputPath = pageOutputPath(tab.slug, slug, config.prettyUrls);
84
+ pageMap.set(outputPath, {
85
+ outputPath,
86
+ currentPage: { kind: "markdown", markdown: page },
87
+ spec: primarySpec,
88
+ tabSlug: tab.slug,
89
+ pageSlug: slug,
90
+ });
91
+ }
92
+ siteTabs.push(navTab);
93
+ continue;
94
+ }
73
95
  if (tab.source.kind !== "markdown")
74
96
  continue;
75
97
  const pagesByPath = new Map();
@@ -121,6 +143,7 @@ export async function assembleSite(config) {
121
143
  pageMap,
122
144
  changelogDiagnostics,
123
145
  godocDiagnostics,
146
+ rustdocDiagnostics,
124
147
  extraFiles,
125
148
  };
126
149
  }
@@ -130,6 +153,37 @@ export function formatGodocDiagnostic(diag) {
130
153
  const loc = diag.file ? ` ${diag.file}${diag.line ? `:${diag.line}` : ""}` : "";
131
154
  return `[${sev}] ${diag.code}${where}${loc} ${diag.message}`;
132
155
  }
156
+ export function enforceGodocDiagnostics(diagnostics) {
157
+ const error = diagnostics.find((diagnostic) => diagnostic.severity === "error");
158
+ if (error)
159
+ throw new Error(formatGodocFailure(error));
160
+ }
161
+ export function enforceRustdocDiagnostics(diagnostics) {
162
+ const error = diagnostics.find((diagnostic) => diagnostic.severity === "error");
163
+ if (error)
164
+ throw new Error(formatRustdocFailure(error));
165
+ }
166
+ function formatGodocFailure(diagnostic) {
167
+ const where = diagnostic.package ? ` (${diagnostic.package})` : "";
168
+ const loc = diagnostic.file
169
+ ? ` ${diagnostic.file}${diagnostic.line ? `:${diagnostic.line}` : ""}`
170
+ : "";
171
+ return `[${diagnostic.code}]${where}${loc}: ${diagnostic.message}`;
172
+ }
173
+ export function formatRustdocDiagnostic(diagnostic) {
174
+ const location = diagnostic.file
175
+ ? ` ${diagnostic.file}${diagnostic.line ? `:${diagnostic.line}` : ""}`
176
+ : "";
177
+ const cratePrefix = diagnostic.crate ? ` [${diagnostic.crate}]` : "";
178
+ return `[${diagnostic.severity.toUpperCase()}] ${diagnostic.code}${cratePrefix}${location} ${diagnostic.message}`;
179
+ }
180
+ function formatRustdocFailure(diagnostic) {
181
+ const location = diagnostic.file
182
+ ? ` ${diagnostic.file}${diagnostic.line ? `:${diagnostic.line}` : ""}`
183
+ : "";
184
+ const cratePrefix = diagnostic.crate ? ` (${diagnostic.crate})` : "";
185
+ return `[${diagnostic.code}]${cratePrefix}${location}: ${diagnostic.message}`;
186
+ }
133
187
  export function collectDocsPagesByTab(pageMap, tabs) {
134
188
  const docsPagesByTab = new Map();
135
189
  for (const tab of tabs) {
@@ -217,6 +271,7 @@ export async function buildSiteConfig(config) {
217
271
  const customCSS = await loadCustomCSS(config.theme.css);
218
272
  return {
219
273
  name: config.name,
274
+ titleSeparator: config.titleSeparator,
220
275
  siteUrl: config.siteUrl,
221
276
  baseUrl: config.baseUrl,
222
277
  prettyUrls: config.prettyUrls,
@@ -433,7 +488,7 @@ function isSearchableDocsSitePage(page) {
433
488
  return page.currentPage.kind === "markdown" || isMainChangelogSitePage(page);
434
489
  }
435
490
  function isDocsSource(kind) {
436
- return kind === "markdown" || kind === "doxygen" || kind === "godoc";
491
+ return kind === "markdown" || kind === "doxygen" || kind === "godoc" || kind === "rustdoc";
437
492
  }
438
493
  function createFeedLinks(atomPath, rssPath, title) {
439
494
  return [