sourcey 3.6.5 → 3.6.6

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 (49) hide show
  1. package/README.md +4 -4
  2. package/dist/adapters/shared.js +1 -1
  3. package/dist/astro/index.d.ts.map +1 -1
  4. package/dist/astro/index.js +8 -6
  5. package/dist/client/reader-controls.js +81 -0
  6. package/dist/client/reader.d.ts +5 -0
  7. package/dist/client/reader.d.ts.map +1 -0
  8. package/dist/client/reader.js +5 -0
  9. package/dist/components/App.d.ts.map +1 -1
  10. package/dist/components/App.js +1 -1
  11. package/dist/components/layout/Head.d.ts.map +1 -1
  12. package/dist/components/layout/Head.js +6 -4
  13. package/dist/components/layout/Page.d.ts.map +1 -1
  14. package/dist/components/layout/Page.js +20 -14
  15. package/dist/components/layout/Reader.d.ts +5 -0
  16. package/dist/components/layout/Reader.d.ts.map +1 -0
  17. package/dist/components/layout/Reader.js +64 -0
  18. package/dist/components/layout/SearchDialog.d.ts +2 -0
  19. package/dist/components/layout/SearchDialog.d.ts.map +1 -0
  20. package/dist/components/layout/SearchDialog.js +4 -0
  21. package/dist/components/openapi/Operation.d.ts.map +1 -1
  22. package/dist/components/openapi/Operation.js +2 -2
  23. package/dist/config.d.ts +56 -4
  24. package/dist/config.d.ts.map +1 -1
  25. package/dist/config.js +18 -10
  26. package/dist/core/doxygen-loader.js +1 -1
  27. package/dist/core/loader.js +2 -2
  28. package/dist/core/markdown-loader.d.ts +2 -0
  29. package/dist/core/markdown-loader.d.ts.map +1 -1
  30. package/dist/core/markdown-loader.js +1 -0
  31. package/dist/core/navigation.js +1 -1
  32. package/dist/core/parser.js +1 -1
  33. package/dist/dev-server.d.ts.map +1 -1
  34. package/dist/dev-server.js +3 -4
  35. package/dist/index.d.ts +1 -1
  36. package/dist/index.d.ts.map +1 -1
  37. package/dist/init.js +4 -4
  38. package/dist/renderer/html-builder.d.ts.map +1 -1
  39. package/dist/renderer/html-builder.js +6 -27
  40. package/dist/renderer/static-files.d.ts.map +1 -1
  41. package/dist/renderer/static-files.js +3 -1
  42. package/dist/themes/assets.d.ts +8 -0
  43. package/dist/themes/assets.d.ts.map +1 -0
  44. package/dist/themes/assets.js +16 -0
  45. package/dist/themes/reader/sourcey.css +1024 -0
  46. package/dist/themes/registry.d.ts +20 -0
  47. package/dist/themes/registry.d.ts.map +1 -0
  48. package/dist/themes/registry.js +8 -0
  49. package/package.json +3 -2
package/README.md CHANGED
@@ -32,7 +32,7 @@ npx sourcey init
32
32
  - **Rust and rustdoc**: native API documentation from nightly rustdoc JSON, with doctests as a first-class extracted view. URL-encoded parametric impl anchors for deep-link parity with doc.rust-lang.org. Snapshot mode lets CI build on stable Rust toolchains. Aggregated doctests index across the workspace
33
33
  - **Context exports**: auto-generate llms.txt and llms-full.txt alongside your HTML as alternate views of the same documentation graph
34
34
  - **TypeScript config**: `sourcey.config.ts` with `defineConfig()` autocomplete; theme, navbar, CTA buttons, footer
35
- - **Theme presets**: default (sidebar + TOC), minimal (single column), api-first (Stripe-style three column); colors, fonts, layout dimensions, and custom CSS on top
35
+ - **Themes**: default (sidebar + TOC), minimal (single column), api-first (three column), and reader (editorial specification); colors, fonts, layout dimensions, and custom CSS on top
36
36
  - **Vite dev server**: SSR hot reload on every component and CSS change; spec and markdown changes trigger instant refresh
37
37
  - **Dark mode**: semantic design tokens, light/dark logo variants, localStorage persistence
38
38
  - **Client-side search**: instant fuzzy search across all pages and API operations; Cmd+K
@@ -177,11 +177,11 @@ Guides support rich components in standard markdown:
177
177
 
178
178
  ### Theme
179
179
 
180
- All visual configuration lives under `theme`. Colors, fonts, layout dimensions, and a preset that controls page structure:
180
+ All visual configuration lives under `theme`. `theme.name` selects the complete renderer; colors, fonts, layout dimensions, and custom CSS apply on top:
181
181
 
182
182
  ```typescript
183
183
  theme: {
184
- preset: "api-first",
184
+ name: "api-first",
185
185
  colors: { primary: "#f59e0b", light: "#fbbf24", dark: "#d97706" },
186
186
  fonts: { sans: "'Lexend', sans-serif", mono: "'Fira Code', monospace" },
187
187
  layout: { sidebar: "16rem", content: "48rem" },
@@ -189,7 +189,7 @@ theme: {
189
189
  }
190
190
  ```
191
191
 
192
- Presets control layout structure: `"default"` (sidebar + TOC), `"minimal"` (single centered column), `"api-first"` (three-column with persistent code panels). Everything else applies on top.
192
+ Themes control the complete layout structure: `"default"` (sidebar + TOC), `"minimal"` (single centered column), `"api-first"` (three-column with persistent code panels), and `"reader"` (editorial specification reader). Shared brand settings apply on top. Theme-specific options are only interpreted by the selected theme.
193
193
 
194
194
  ## CLI
195
195
 
@@ -97,7 +97,7 @@ async function expandGlob(pattern, configDir) {
97
97
  }
98
98
  catch (err) {
99
99
  if (err.code === "ENOENT") {
100
- throw new Error(`Glob directory not found: ${dir}`);
100
+ throw new Error(`Glob directory not found: ${dir}`, { cause: err });
101
101
  }
102
102
  throw err;
103
103
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/astro/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/astro/index.ts"],"names":[],"mappings":"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"}
@@ -59,6 +59,7 @@ export default function sourceyAstro(options = {}) {
59
59
  outputRoot: fileURLToPath(dir),
60
60
  outputDir,
61
61
  routeBase: preparedSourcey.routeBase,
62
+ publicBase: preparedSourcey.config.baseUrl,
62
63
  });
63
64
  logger.info(`Sourcey: wrote ${sourceySite.pageCount} page${sourceySite.pageCount === 1 ? "" : "s"}`);
64
65
  },
@@ -149,15 +150,16 @@ function sourceyAstroDevPlugin(options) {
149
150
  const err = error instanceof Error ? error : new Error(String(error));
150
151
  server.ssrFixStacktrace(err);
151
152
  logger.error(`Sourcey: ${err.message}`);
152
- server.ws.send({ type: "error", err: { message: err.message, stack: err.stack ?? "" } });
153
+ server.ws.send({
154
+ type: "error",
155
+ err: { message: err.message, stack: err.stack ?? "" },
156
+ });
153
157
  });
154
158
  });
155
159
  server.middlewares.use(async (req, res, next) => {
156
160
  const url = req.url ?? "/";
157
161
  const pathname = url.split("?", 1)[0] ?? "/";
158
- if (url.startsWith("/@") ||
159
- url.startsWith("/__vite") ||
160
- url.startsWith("/node_modules/")) {
162
+ if (url.startsWith("/@") || url.startsWith("/__vite") || url.startsWith("/node_modules/")) {
161
163
  return next();
162
164
  }
163
165
  if (!requestPathMatchesBase(pathname, prepared.config.baseUrl)) {
@@ -244,7 +246,7 @@ async function writeAstroRouteAlias(options) {
244
246
  const aliasPath = resolve(options.outputRoot, `${route}.html`);
245
247
  const html = await readFile(indexPath, "utf-8");
246
248
  await mkdir(dirname(aliasPath), { recursive: true });
247
- await writeFile(aliasPath, renderAstroRouteAlias(html, options.routeBase));
249
+ await writeFile(aliasPath, renderAstroRouteAlias(html, options.publicBase));
248
250
  }
249
251
  function renderAstroRouteAlias(html, routeBase) {
250
252
  const basePath = routeBase.endsWith("/") ? routeBase : `${routeBase}/`;
@@ -272,7 +274,7 @@ function phaseEnabled(phase, defaultEnabled) {
272
274
  return phase?.enabled ?? defaultEnabled;
273
275
  }
274
276
  function phaseGenerateOgImages(phase, defaultEnabled) {
275
- return typeof phase === "object" ? phase.generateOgImages ?? defaultEnabled : defaultEnabled;
277
+ return typeof phase === "object" ? (phase.generateOgImages ?? defaultEnabled) : defaultEnabled;
276
278
  }
277
279
  function shouldRebuildForChange(file, watchPaths) {
278
280
  if (watchPaths.includes(file))
@@ -0,0 +1,81 @@
1
+ (function () {
2
+ var root = document.querySelector(".sourcey-reader");
3
+ if (!root) return;
4
+ root.querySelectorAll("[data-reader-enhancement]").forEach(function (el) {
5
+ el.hidden = false;
6
+ });
7
+ root.querySelectorAll("[data-reader-fallback]").forEach(function (el) {
8
+ el.hidden = true;
9
+ });
10
+ var toggle = root.querySelector(".menu-toggle");
11
+ var menu = root.querySelector("#reader-mobile-nav");
12
+ function closeMenu() {
13
+ menu.hidden = true;
14
+ toggle.setAttribute("aria-expanded", "false");
15
+ toggle.setAttribute("aria-label", "Open navigation");
16
+ }
17
+ toggle.addEventListener("click", function () {
18
+ var open = toggle.getAttribute("aria-expanded") !== "true";
19
+ menu.hidden = !open;
20
+ toggle.setAttribute("aria-expanded", String(open));
21
+ toggle.setAttribute("aria-label", open ? "Close navigation" : "Open navigation");
22
+ });
23
+ window.matchMedia("(min-width: 901px)").addEventListener("change", function (event) {
24
+ if (event.matches) closeMenu();
25
+ });
26
+ document.addEventListener("keydown", function (event) {
27
+ if (event.key === "Escape" && !menu.hidden) {
28
+ closeMenu();
29
+ toggle.focus();
30
+ }
31
+ var search = root.querySelector("a.search-link");
32
+ if (
33
+ search &&
34
+ event.key === "/" &&
35
+ !event.metaKey &&
36
+ !event.ctrlKey &&
37
+ !event.altKey &&
38
+ !event.target.closest("input, textarea, select, [contenteditable]")
39
+ ) {
40
+ event.preventDefault();
41
+ window.location.href = search.href;
42
+ }
43
+ });
44
+ var select = root.querySelector("#chapter-select");
45
+ select.addEventListener("change", function () {
46
+ window.location.href = select.value;
47
+ });
48
+ var copy = root.querySelector("[data-copy-page]");
49
+ if (copy)
50
+ copy.addEventListener("click", async function () {
51
+ var label = copy.querySelector("span");
52
+ try {
53
+ await navigator.clipboard.writeText(window.location.href);
54
+ label.textContent = "Copied";
55
+ } catch {
56
+ label.textContent = "Copy the address bar URL";
57
+ }
58
+ setTimeout(function () {
59
+ label.textContent = "Copy link";
60
+ }, 2500);
61
+ });
62
+ var links = Array.from(root.querySelectorAll(".docs-toc nav a"));
63
+ if ("IntersectionObserver" in window) {
64
+ var observer = new window.IntersectionObserver(
65
+ function (entries) {
66
+ var active = entries.find(function (entry) {
67
+ return entry.isIntersecting;
68
+ });
69
+ if (!active) return;
70
+ links.forEach(function (link) {
71
+ if (link.hash === "#" + active.target.id) link.setAttribute("aria-current", "location");
72
+ else link.removeAttribute("aria-current");
73
+ });
74
+ },
75
+ { rootMargin: "-100px 0px -65% 0px" },
76
+ );
77
+ root.querySelectorAll(".reader-prose h2, .reader-prose h3").forEach(function (heading) {
78
+ observer.observe(heading);
79
+ });
80
+ }
81
+ })();
@@ -0,0 +1,5 @@
1
+ import "../themes/default/main.css";
2
+ import "./tabs.js";
3
+ import "./search.js";
4
+ import "./reader-controls.js";
5
+ //# sourceMappingURL=reader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reader.d.ts","sourceRoot":"","sources":["../../src/client/reader.ts"],"names":[],"mappings":"AACA,OAAO,4BAA4B,CAAC;AACpC,OAAO,WAAW,CAAC;AACnB,OAAO,aAAa,CAAC;AACrB,OAAO,sBAAsB,CAAC"}
@@ -0,0 +1,5 @@
1
+ // Shared content primitives, with the reader's own progressive enhancements.
2
+ import "../themes/default/main.css";
3
+ import "./tabs.js";
4
+ import "./search.js";
5
+ import "./reader-controls.js";
@@ -1 +1 @@
1
- {"version":3,"file":"App.d.ts","sourceRoot":"","sources":["../../src/components/App.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAQ5D,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAIrF,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,cAAc,CAAC;IACrB,OAAO,EAAE,aAAa,CAAC;IACvB,UAAU,EAAE,cAAc,CAAC;IAC3B,WAAW,EAAE,WAAW,CAAC;IACzB,IAAI,EAAE,UAAU,CAAC;CAClB;AAED;;;GAGG;AACH,wBAAgB,GAAG,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,IAAI,EAAE,EAAE,QAAQ,gCA0B7E"}
1
+ {"version":3,"file":"App.d.ts","sourceRoot":"","sources":["../../src/components/App.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAQ5D,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAIrF,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,cAAc,CAAC;IACrB,OAAO,EAAE,aAAa,CAAC;IACvB,UAAU,EAAE,cAAc,CAAC;IAC3B,WAAW,EAAE,WAAW,CAAC;IACzB,IAAI,EAAE,UAAU,CAAC;CAClB;AAED;;;GAGG;AACH,wBAAgB,GAAG,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,IAAI,EAAE,EAAE,QAAQ,gCAwB7E"}
@@ -7,6 +7,6 @@ import { Page } from "./layout/Page.js";
7
7
  * When embeddable, renders just the page content without html/body wrapper.
8
8
  */
9
9
  export function App({ spec, options, navigation, currentPage, site }) {
10
- const content = options.embeddable ? (_jsx(Page, {})) : (_jsxs("html", { lang: "en", children: [_jsx(Head, {}), _jsxs("body", { id: "sourcey", children: [_jsx(Page, {}), _jsx("script", { src: `${options.assetBase}sourcey.js`, defer: true })] })] }));
10
+ const content = options.embeddable ? (_jsx(Page, {})) : (_jsxs("html", { lang: "en", children: [_jsx(Head, {}), _jsxs("body", { id: "sourcey", "data-sourcey-theme": site.theme.name, children: [_jsx(Page, {}), _jsx("script", { src: `${options.assetBase}sourcey.js`, defer: true })] })] }));
11
11
  return (_jsx(SiteContext.Provider, { value: site, children: _jsx(SpecContext.Provider, { value: spec, children: _jsx(OptionsContext.Provider, { value: options, children: _jsx(NavigationContext.Provider, { value: navigation, children: _jsx(PageContext.Provider, { value: currentPage, children: content }) }) }) }) }));
12
12
  }
@@ -1 +1 @@
1
- {"version":3,"file":"Head.d.ts","sourceRoot":"","sources":["../../../src/components/layout/Head.tsx"],"names":[],"mappings":"AAKA,wBAAgB,IAAI,iCA+FnB"}
1
+ {"version":3,"file":"Head.d.ts","sourceRoot":"","sources":["../../../src/components/layout/Head.tsx"],"names":[],"mappings":"AAWA,wBAAgB,IAAI,iCA4HnB"}
@@ -1,6 +1,6 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "preact/jsx-runtime";
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "preact/jsx-runtime";
2
2
  import { useContext } from "preact/hooks";
3
- import { SpecContext, OptionsContext, PageContext, SiteContext, NavigationContext } from "../../renderer/context.js";
3
+ import { SpecContext, OptionsContext, PageContext, SiteContext, NavigationContext, } from "../../renderer/context.js";
4
4
  import { langIconCSS } from "../../utils/lang-icons.js";
5
5
  import pkg from "../../../package.json" with { type: "json" };
6
6
  export function Head() {
@@ -27,7 +27,7 @@ export function Head() {
27
27
  ? page.markdown.description || pageTitle
28
28
  : page.kind === "changelog"
29
29
  ? changelogVersion?.summary || page.changelog.description || pageTitle
30
- : spec.info.summary ?? spec.info.description ?? `${siteName} API Documentation`;
30
+ : (spec.info.summary ?? spec.info.description ?? `${siteName} API Documentation`);
31
31
  const nav = useContext(NavigationContext);
32
32
  const { colors, fonts, layout } = site.theme;
33
33
  // Desktop: h-16 row + h-12 tabs (when multi-tab) = 7rem, or h-16 alone = 4rem.
@@ -57,7 +57,9 @@ export function Head() {
57
57
  body { margin: 0; background: rgb(var(--color-background-light)); }
58
58
  .dark body { background: rgb(var(--color-background-dark)); }
59
59
  `;
60
- return (_jsxs("head", { children: [_jsx("meta", { charset: "utf-8" }), _jsx("meta", { name: "viewport", content: "width=device-width, initial-scale=1" }), _jsx("title", { children: pageTitle }), _jsx("meta", { name: "description", content: pageDescription }), _jsx("meta", { name: "generator", content: `Sourcey ${pkg.version}` }), options.pageUrl && _jsx("link", { rel: "canonical", href: options.pageUrl }), _jsx("meta", { property: "og:title", content: pageTitle }), _jsx("meta", { property: "og:description", content: pageDescription }), _jsx("meta", { property: "og:type", content: "website" }), siteName && _jsx("meta", { property: "og:site_name", content: siteName }), options.pageUrl && _jsx("meta", { property: "og:url", content: options.pageUrl }), options.ogImageUrl && _jsx("meta", { property: "og:image", content: options.ogImageUrl }), options.ogImageUrl && _jsx("meta", { property: "og:image:width", content: "1200" }), options.ogImageUrl && _jsx("meta", { property: "og:image:height", content: "630" }), options.ogImageUrl && _jsx("meta", { property: "og:image:type", content: "image/png" }), _jsx("meta", { name: "twitter:card", content: options.ogImageUrl ? "summary_large_image" : "summary" }), _jsx("meta", { name: "twitter:title", content: pageTitle }), _jsx("meta", { name: "twitter:description", content: pageDescription }), options.ogImageUrl && _jsx("meta", { name: "twitter:image", content: options.ogImageUrl }), _jsx("meta", { name: "sourcey-search", content: `${options.assetBase}search-index.json` }), options.alternateLinks?.map((link) => (_jsx("link", { rel: "alternate", type: link.type, href: link.href, title: link.title }, `${link.type}-${link.href}`))), _jsx("link", { rel: "preconnect", href: "https://fonts.googleapis.com" }), _jsx("link", { rel: "preconnect", href: "https://fonts.gstatic.com", crossorigin: "anonymous" }), _jsx("link", { rel: "stylesheet", href: `https://fonts.googleapis.com/css2?family=${encodeURIComponent(fonts.googleFont)}:wght@100..900&display=swap` }), _jsx("style", { dangerouslySetInnerHTML: { __html: themeCSS } }), showLangIconCSS && _jsx("style", { dangerouslySetInnerHTML: { __html: langIconCSS() } }), site.customCSS && _jsx("style", { dangerouslySetInnerHTML: { __html: site.customCSS } }), _jsx("script", { dangerouslySetInnerHTML: { __html: `(function(){var t=localStorage.getItem('sourcey-theme');if(t==='dark')document.documentElement.classList.add('dark')})()` } }), _jsx("link", { rel: "stylesheet", href: `${options.assetBase}sourcey.css` }), site.favicon && _jsx("link", { rel: "icon", href: site.favicon })] }));
60
+ return (_jsxs("head", { children: [_jsx("meta", { charset: "utf-8" }), _jsx("meta", { name: "viewport", content: "width=device-width, initial-scale=1" }), _jsx("title", { children: pageTitle }), _jsx("meta", { name: "description", content: pageDescription }), _jsx("meta", { name: "generator", content: `Sourcey ${pkg.version}` }), options.pageUrl && _jsx("link", { rel: "canonical", href: options.pageUrl }), _jsx("meta", { property: "og:title", content: pageTitle }), _jsx("meta", { property: "og:description", content: pageDescription }), _jsx("meta", { property: "og:type", content: "website" }), siteName && _jsx("meta", { property: "og:site_name", content: siteName }), options.pageUrl && _jsx("meta", { property: "og:url", content: options.pageUrl }), options.ogImageUrl && _jsx("meta", { property: "og:image", content: options.ogImageUrl }), options.ogImageUrl && _jsx("meta", { property: "og:image:width", content: "1200" }), options.ogImageUrl && _jsx("meta", { property: "og:image:height", content: "630" }), options.ogImageUrl && _jsx("meta", { property: "og:image:type", content: "image/png" }), _jsx("meta", { name: "twitter:card", content: options.ogImageUrl ? "summary_large_image" : "summary" }), _jsx("meta", { name: "twitter:title", content: pageTitle }), _jsx("meta", { name: "twitter:description", content: pageDescription }), options.ogImageUrl && _jsx("meta", { name: "twitter:image", content: options.ogImageUrl }), _jsx("meta", { name: "sourcey-search", content: `${options.assetBase}search-index.json` }), options.alternateLinks?.map((link) => (_jsx("link", { rel: "alternate", type: link.type, href: link.href, title: link.title }, `${link.type}-${link.href}`))), fonts.googleFont && (_jsxs(_Fragment, { children: [_jsx("link", { rel: "preconnect", href: "https://fonts.googleapis.com" }), _jsx("link", { rel: "preconnect", href: "https://fonts.gstatic.com", crossorigin: "anonymous" }), _jsx("link", { rel: "stylesheet", href: `https://fonts.googleapis.com/css2?family=${encodeURIComponent(fonts.googleFont)}:wght@100..900&display=swap` })] })), _jsx("style", { dangerouslySetInnerHTML: { __html: themeCSS } }), showLangIconCSS && _jsx("style", { dangerouslySetInnerHTML: { __html: langIconCSS() } }), site.theme.name !== "reader" && site.customCSS && (_jsx("style", { dangerouslySetInnerHTML: { __html: site.customCSS } })), site.theme.name !== "reader" && (_jsx("script", { dangerouslySetInnerHTML: {
61
+ __html: `(function(){var t=localStorage.getItem('sourcey-theme');if(t==='dark')document.documentElement.classList.add('dark')})()`,
62
+ } })), _jsx("link", { rel: "stylesheet", href: `${options.assetBase}sourcey.css` }), site.theme.name === "reader" && site.customCSS && (_jsx("style", { dangerouslySetInnerHTML: { __html: site.customCSS } })), site.favicon && _jsx("link", { rel: "icon", href: site.favicon })] }));
61
63
  }
62
64
  function composePageTitle(title, siteName, separator) {
63
65
  if (!siteName)
@@ -1 +1 @@
1
- {"version":3,"file":"Page.d.ts","sourceRoot":"","sources":["../../../src/components/layout/Page.tsx"],"names":[],"mappings":"AAuRA,wBAAgB,IAAI,iCAqCnB"}
1
+ {"version":3,"file":"Page.d.ts","sourceRoot":"","sources":["../../../src/components/layout/Page.tsx"],"names":[],"mappings":"AAuXA,wBAAgB,IAAI,iCA+BnB"}
@@ -1,6 +1,8 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "preact/jsx-runtime";
2
+ import { ReaderPage } from "./Reader.js";
3
+ import { SearchDialog } from "./SearchDialog.js";
2
4
  import { useContext } from "preact/hooks";
3
- import { SpecContext, PageContext, NavigationContext, OptionsContext, SiteContext } from "../../renderer/context.js";
5
+ import { SpecContext, PageContext, NavigationContext, OptionsContext, SiteContext, } from "../../renderer/context.js";
4
6
  import { Markdown } from "../ui/Markdown.js";
5
7
  import { Header } from "./Header.js";
6
8
  import { Sidebar } from "./Sidebar.js";
@@ -23,7 +25,7 @@ function MarkdownPageContent({ page, className = "" }) {
23
25
  const eyebrow = activeGroup?.label;
24
26
  return (_jsxs("div", { class: `relative grow box-border flex-col w-full mx-auto px-1 min-w-0 ${className}`, id: "content-area", children: [_jsxs("header", { class: "relative leading-none", children: [_jsxs("div", { class: "mt-0.5 space-y-2.5", children: [eyebrow && (_jsx("div", { class: "h-5 text-[rgb(var(--color-primary-ink))] dark:text-[rgb(var(--color-primary-light))] text-sm font-semibold", children: eyebrow })), _jsx("div", { class: "flex flex-col sm:flex-row items-start sm:items-center relative gap-2 min-w-0", children: _jsx("h1", { class: "text-2xl sm:text-3xl text-[rgb(var(--color-gray-900))] tracking-tight dark:text-[rgb(var(--color-gray-200))] font-bold", style: "overflow-wrap: anywhere", children: page.title }) })] }), page.description && (_jsx("div", { class: "page-description mt-2 text-lg prose prose-gray dark:prose-invert", style: "overflow-wrap: anywhere", children: _jsx(Markdown, { content: page.description, inline: true }) }))] }), _jsx("div", { class: "prose prose-gray dark:prose-invert relative mt-8 mb-14 max-w-none", dangerouslySetInnerHTML: { __html: page.html } }), _jsx(PageNavigation, {}), _jsx(ContentFooter, {})] }));
25
27
  }
26
- function ChangelogPageContent({ page, className = "" }) {
28
+ function ChangelogPageContent({ page, className = "", }) {
27
29
  return (_jsxs("div", { class: `relative grow box-border flex-col w-full mx-auto px-1 min-w-0 ${className}`, id: "content-area", children: [_jsx(ChangelogPage, { page: page }), _jsx(PageNavigation, {}), _jsx(ContentFooter, {})] }));
28
30
  }
29
31
  /**
@@ -53,7 +55,7 @@ function PageNavigation() {
53
55
  const labelClass = "text-xs text-[rgb(var(--color-gray-500))] dark:text-[rgb(var(--color-gray-400))]";
54
56
  const titleClass = "text-sm font-medium text-[rgb(var(--color-gray-700))] dark:text-[rgb(var(--color-gray-300))] group-hover:text-[rgb(var(--color-primary-ink))] dark:group-hover:text-[rgb(var(--color-primary-light))] transition-colors";
55
57
  const base = options.assetBase;
56
- return (_jsxs("nav", { class: "mt-12 flex items-stretch justify-between gap-4", children: [prev ? (_jsxs("a", { href: `${base}${prev.href}`, class: linkClass, children: [_jsx("span", { class: labelClass, children: "\u2190 Previous" }), _jsx("span", { class: titleClass, children: prev.label })] })) : _jsx("span", {}), next ? (_jsxs("a", { href: `${base}${next.href}`, class: `${linkClass} text-right ml-auto`, children: [_jsx("span", { class: labelClass, children: "Next \u2192" }), _jsx("span", { class: titleClass, children: next.label })] })) : null] }));
58
+ return (_jsxs("nav", { class: "mt-12 flex items-stretch justify-between gap-4", children: [prev ? (_jsxs("a", { href: `${base}${prev.href}`, class: linkClass, children: [_jsx("span", { class: labelClass, children: "\u2190 Previous" }), _jsx("span", { class: titleClass, children: prev.label })] })) : (_jsx("span", {})), next ? (_jsxs("a", { href: `${base}${next.href}`, class: `${linkClass} text-right ml-auto`, children: [_jsx("span", { class: labelClass, children: "Next \u2192" }), _jsx("span", { class: titleClass, children: next.label })] })) : null] }));
57
59
  }
58
60
  function ContentFooter() {
59
61
  const site = useContext(SiteContext);
@@ -62,9 +64,13 @@ function ContentFooter() {
62
64
  // Build "Edit this page" URL when repo + editBranch are configured
63
65
  let editUrl;
64
66
  const editPath = page.kind === "markdown"
65
- ? (page.markdown.editPath === undefined ? page.markdown.sourcePath : page.markdown.editPath)
67
+ ? page.markdown.editPath === undefined
68
+ ? page.markdown.sourcePath
69
+ : page.markdown.editPath
66
70
  : page.kind === "changelog"
67
- ? (page.changelog.editPath === undefined ? page.changelog.sourcePath : page.changelog.editPath)
71
+ ? page.changelog.editPath === undefined
72
+ ? page.changelog.sourcePath
73
+ : page.changelog.editPath
68
74
  : undefined;
69
75
  if (site.repo && site.editBranch && editPath) {
70
76
  const repoBase = site.repo.replace(/\/$/, "");
@@ -75,12 +81,10 @@ function ContentFooter() {
75
81
  editUrl = `${repoBase}/edit/${site.editBranch}/${basePath}${editPath}`;
76
82
  }
77
83
  const linkStyle = "hover:text-[rgb(var(--color-gray-600))] dark:hover:text-[rgb(var(--color-gray-300))] transition-colors";
78
- return (_jsxs("div", { class: "mt-16 mb-8 flex items-center justify-between border-t border-[rgb(var(--color-gray-200)/0.7)] dark:border-[rgb(var(--color-gray-800)/0.5)] pt-6 text-xs text-[rgb(var(--color-gray-500))] dark:text-[rgb(var(--color-gray-400))]", children: [_jsxs("a", { href: "https://sourcey.com", target: "_blank", rel: "noopener noreferrer", class: `flex items-center gap-1.5 ${linkStyle}`, children: ["Built with", _jsx("img", { src: "https://sourcey.com/sourcey-logo.png", alt: "Sourcey", class: "h-4 w-4" })] }), _jsxs("div", { class: "flex items-center gap-4", children: [editUrl && (_jsxs("a", { href: editUrl, target: "_blank", rel: "noopener noreferrer", class: `${linkStyle} flex items-center gap-1`, children: [_jsx("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", "stroke-width": "1.5", stroke: "currentColor", class: "w-3 h-3 mr-0.5", children: _jsx("path", { "stroke-linecap": "round", "stroke-linejoin": "round", d: "m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" }) }), "Edit this page"] })), links.map((link) => (_jsx("a", { href: link.href, target: "_blank", rel: "noopener noreferrer", "aria-label": link.label ?? socialLabels[link.type] ?? link.href, class: linkStyle, children: link.type === "link"
79
- ? (link.label ?? link.href)
80
- : (_jsxs(_Fragment, { children: [_jsx(SocialIcon, { type: link.type }), link.label && _jsx("span", { class: "ml-1", children: link.label })] })) }, link.href)))] })] }));
84
+ return (_jsxs("div", { class: "mt-16 mb-8 flex items-center justify-between border-t border-[rgb(var(--color-gray-200)/0.7)] dark:border-[rgb(var(--color-gray-800)/0.5)] pt-6 text-xs text-[rgb(var(--color-gray-500))] dark:text-[rgb(var(--color-gray-400))]", children: [_jsxs("span", { children: ["Docs by", " ", _jsx("a", { href: "https://sourcey.com", target: "_blank", rel: "noopener noreferrer", class: linkStyle, children: "Sourcey" })] }), _jsxs("div", { class: "flex items-center gap-4", children: [editUrl && (_jsxs("a", { href: editUrl, target: "_blank", rel: "noopener noreferrer", class: `${linkStyle} flex items-center gap-1`, children: [_jsx("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", "stroke-width": "1.5", stroke: "currentColor", class: "w-3 h-3 mr-0.5", children: _jsx("path", { "stroke-linecap": "round", "stroke-linejoin": "round", d: "m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" }) }), "Edit this page"] })), links.map((link) => (_jsx("a", { href: link.href, target: "_blank", rel: "noopener noreferrer", "aria-label": link.label ?? socialLabels[link.type] ?? link.href, class: linkStyle, children: link.type === "link" ? ((link.label ?? link.href)) : (_jsxs(_Fragment, { children: [_jsx(SocialIcon, { type: link.type }), link.label && _jsx("span", { class: "ml-1", children: link.label })] })) }, link.href)))] })] }));
81
85
  }
82
86
  // ---------------------------------------------------------------------------
83
- // Layout presets
87
+ // Built-in theme layouts
84
88
  // ---------------------------------------------------------------------------
85
89
  function DefaultLayout() {
86
90
  const page = useContext(PageContext);
@@ -99,9 +103,11 @@ function ApiFirstLayout() {
99
103
  // ---------------------------------------------------------------------------
100
104
  export function Page() {
101
105
  const site = useContext(SiteContext);
102
- const preset = site.theme.preset;
103
- const Layout = preset === "minimal" ? MinimalLayout
104
- : preset === "api-first" ? ApiFirstLayout
105
- : DefaultLayout;
106
- return (_jsxs("div", { id: "page", class: "relative antialiased text-[rgb(var(--color-gray-500))] dark:text-[rgb(var(--color-gray-400))]", children: [_jsx(Header, {}), _jsx("span", { class: "fixed inset-0 bg-[rgb(var(--color-background-light))] dark:bg-[rgb(var(--color-background-dark))] -z-10 pointer-events-none" }), _jsx(Layout, {}), _jsx("div", { id: "search-dialog", role: "dialog", "aria-label": "Search", children: _jsxs("div", { class: "search-dialog-inner", children: [_jsxs("div", { class: "search-input-row", children: [_jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 20 20", fill: "currentColor", class: "search-input-icon", children: _jsx("path", { "fill-rule": "evenodd", d: "M9 3.5a5.5 5.5 0 1 0 0 11 5.5 5.5 0 0 0 0-11ZM2 9a7 7 0 1 1 12.452 4.391l3.328 3.329a.75.75 0 1 1-1.06 1.06l-3.329-3.328A7 7 0 0 1 2 9Z", "clip-rule": "evenodd" }) }), _jsx("input", { id: "search-input", type: "text", placeholder: "Search docs...", autocomplete: "off", spellcheck: false })] }), _jsx("div", { id: "search-results" }), _jsxs("div", { class: "search-footer", children: [_jsxs("span", { class: "search-footer-hint", children: [_jsx("kbd", { children: "\u2191\u2193" }), " navigate"] }), _jsxs("span", { class: "search-footer-hint", children: [_jsx("kbd", { children: "\u21B5" }), " select"] }), _jsxs("span", { class: "search-footer-hint", children: [_jsx("kbd", { children: "esc" }), " close"] })] })] }) })] }));
106
+ const theme = site.theme.name;
107
+ const page = useContext(PageContext);
108
+ if (theme === "reader") {
109
+ return (_jsx(ReaderPage, { children: page.kind === "spec" ? (_jsx(SpecPageContent, {})) : page.kind === "changelog" ? (_jsx(ChangelogPageContent, { page: page.changelog })) : null }));
110
+ }
111
+ const Layout = theme === "minimal" ? MinimalLayout : theme === "api-first" ? ApiFirstLayout : DefaultLayout;
112
+ return (_jsxs("div", { id: "page", class: "relative antialiased text-[rgb(var(--color-gray-500))] dark:text-[rgb(var(--color-gray-400))]", children: [_jsx(Header, {}), _jsx("span", { class: "fixed inset-0 bg-[rgb(var(--color-background-light))] dark:bg-[rgb(var(--color-background-dark))] -z-10 pointer-events-none" }), _jsx(Layout, {}), _jsx(SearchDialog, {})] }));
107
113
  }
@@ -0,0 +1,5 @@
1
+ import type { ComponentChildren } from "preact";
2
+ export declare function ReaderPage({ children }: {
3
+ children?: ComponentChildren;
4
+ }): import("preact").JSX.Element;
5
+ //# sourceMappingURL=Reader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Reader.d.ts","sourceRoot":"","sources":["../../../src/components/layout/Reader.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,QAAQ,CAAC;AA0DhD,wBAAgB,UAAU,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,CAAC,EAAE,iBAAiB,CAAA;CAAE,gCAiUxE"}
@@ -0,0 +1,64 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "preact/jsx-runtime";
2
+ import { useContext } from "preact/hooks";
3
+ import { NavigationContext, OptionsContext, PageContext, SiteContext, } from "../../renderer/context.js";
4
+ import { SearchDialog } from "./SearchDialog.js";
5
+ import { safeUrl } from "../../utils/html.js";
6
+ function Icon({ name = "arrow", size = 20 }) {
7
+ const paths = {
8
+ arrow: ["M4 12h15m-6-6 6 6-6 6"],
9
+ chevron: ["m9 5 7 7-7 7"],
10
+ northeast: ["M6 18 18 6M6 6h12v12"],
11
+ menu: ["M4 7h16M4 12h16M4 17h16"],
12
+ search: ["m21 21-5-5", "M18 10a8 8 0 1 1-16 0 8 8 0 0 1 16 0"],
13
+ layers: ["m12 3 10 6-10 6L2 9l10-6Zm-10 10 10 6 10-6m-20 4 10 6 10-6"],
14
+ copy: ["M9 9h12v12H9zM15 5V2H2v13h3"],
15
+ code: ["m8 6-6 6 6 6m8-12 6 6-6 6m-3-15-2 18"],
16
+ };
17
+ return (_jsx("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "1.5", "stroke-linecap": "round", "stroke-linejoin": "round", "aria-hidden": "true", children: (paths[name] ?? paths.arrow).map((path) => (_jsx("path", { d: path }))) }));
18
+ }
19
+ function Link({ link, children, className, }) {
20
+ return (_jsx("a", { href: safeUrl(link.href) ?? undefined, class: className, children: children ?? link.label }));
21
+ }
22
+ export function ReaderPage({ children }) {
23
+ const site = useContext(SiteContext);
24
+ const nav = useContext(NavigationContext);
25
+ const page = useContext(PageContext);
26
+ const { assetBase: base } = useContext(OptionsContext);
27
+ const settings = site.theme.reader ?? {};
28
+ const document = settings.document;
29
+ const tab = nav.tabs.find((item) => item.slug === nav.activeTabSlug);
30
+ const items = tab?.groups.flatMap((group) => group.items) ?? [];
31
+ const index = items.findIndex((item) => item.id === nav.activePageSlug);
32
+ const previous = items[index - 1];
33
+ const next = items[index + 1];
34
+ const label = document?.label ?? tab?.label ?? site.name;
35
+ const edition = [label, document?.version].filter(Boolean).join(" ");
36
+ const href = (path) => `${base}${path}` || "./";
37
+ const activeHref = href(items[index]?.href ?? tab?.href ?? "");
38
+ const home = safeUrl(site.logo?.href ?? href(nav.tabs[0]?.href ?? "")) ?? "/";
39
+ const searchHref = settings.searchHref ? safeUrl(settings.searchHref) : null;
40
+ const before = previous
41
+ ? { label: previous.label, href: href(previous.href), description: "← Previous" }
42
+ : settings.pagination?.before;
43
+ const after = next
44
+ ? { label: next.label, href: href(next.href), description: "Next →" }
45
+ : settings.pagination?.after;
46
+ const isCurrent = (target) => {
47
+ if (target.startsWith("/") && site.baseUrl)
48
+ return site.baseUrl.startsWith(target);
49
+ return target === activeHref;
50
+ };
51
+ const navigationLinks = site.navbar.links.map((link) => ({
52
+ ...link,
53
+ label: link.label ?? link.type,
54
+ }));
55
+ const docPage = page.kind === "markdown" ? page.markdown : null;
56
+ const headings = docPage?.headings ?? (page.kind === "changelog" ? page.changelog.headings : []);
57
+ return (_jsxs("div", { class: "sourcey-reader", id: "page", children: [_jsx("a", { class: "skip-link", href: "#main", children: "Skip to content" }), _jsxs("header", { class: "site-header", children: [_jsxs("div", { class: "header-inner", children: [_jsx("a", { class: "home-link", href: home, "aria-label": `${site.name} home`, children: _jsxs("span", { class: "brand", children: [site.logo?.light && (_jsx("img", { class: settings.logoMark ? "brand-mark" : "brand-logo", src: site.logo.light, alt: settings.logoMark ? "" : site.name })), (!site.logo?.light || settings.logoMark) && _jsx("span", { children: site.name })] }) }), _jsx("nav", { class: "desktop-nav", "aria-label": "Main navigation", children: navigationLinks.map((link) => (_jsx("a", { href: safeUrl(link.href) ?? undefined, "aria-current": isCurrent(link.href) ? "page" : undefined, children: link.label }, link.href))) }), _jsxs("div", { class: "header-actions", children: [searchHref ? (_jsxs("a", { class: "search-link", href: searchHref, "aria-label": "Search documentation", children: [_jsx(Icon, { name: "search", size: 17 }), _jsx("span", { children: "Search" }), _jsx("kbd", { children: "/" })] })) : (_jsxs("button", { class: "search-link", id: "search-open", "aria-label": "Search documentation", "data-reader-enhancement": true, hidden: true, children: [_jsx(Icon, { name: "search", size: 17 }), _jsx("span", { children: "Search" }), _jsx("kbd", { children: "/" })] })), site.navbar.primary && (_jsxs("a", { class: "header-cta", href: safeUrl(site.navbar.primary.href) ?? undefined, children: [site.navbar.primary.label, _jsx(Icon, { size: 15 })] })), _jsx("button", { class: "menu-toggle", "aria-label": "Open navigation", "aria-controls": "reader-mobile-nav", "aria-expanded": "false", "data-reader-enhancement": true, hidden: true, children: _jsx(Icon, { name: "menu" }) })] })] }), _jsxs("nav", { id: "reader-mobile-nav", "aria-label": "Mobile navigation", hidden: true, children: [navigationLinks.map((link) => (_jsxs(Link, { link: link, children: [link.label, _jsx(Icon, {})] }, link.href))), searchHref && (_jsxs("a", { href: searchHref, children: ["Search documentation", _jsx(Icon, { name: "search" })] }))] }), _jsx("nav", { class: "reader-mobile-fallback", "aria-label": "Site links", "data-reader-fallback": true, children: navigationLinks.map((link) => (_jsx(Link, { link: link }, link.href))) })] }), _jsxs("div", { class: "docs-shell", children: [_jsxs("aside", { class: "docs-sidebar", "aria-label": `${tab?.label ?? "Documentation"} navigation`, children: [_jsxs("div", { class: "docs-project", children: [_jsxs("a", { class: `docs-map${document ? "" : " docs-project-title"}`, href: href(tab?.href ?? ""), children: [_jsx("strong", { class: "docs-map-label", children: label }), document?.title && _jsx("span", { class: "docs-map-title", children: document.title })] }), (document?.version || document?.status) && (_jsxs("span", { class: "docs-version", children: [_jsx("span", { class: "small-dot" }), [document.version, document.status?.toLowerCase()].filter(Boolean).join(" ")] }))] }), nav.tabs.length > 1 && (_jsx("nav", { class: "reader-tabs", "aria-label": "Documentation sections", children: nav.tabs.map((item) => (_jsx("a", { href: href(item.href), "aria-current": item.slug === nav.activeTabSlug ? "page" : undefined, children: item.label }))) })), _jsx("nav", { "aria-label": "Chapters", children: tab?.groups.map((group) => (_jsxs(_Fragment, { children: [group.href ? (_jsx("a", { class: "nav-section", href: href(group.href), children: group.label })) : (_jsx("span", { class: "nav-section", children: group.label })), group.items.map((item) => (_jsxs("a", { href: href(item.href), "aria-current": item.id === nav.activePageSlug ? "page" : undefined, children: [_jsx("span", { children: item.label }), item.id === nav.activePageSlug && _jsx("span", { class: "active-nav-dot" })] })))] }))) }), (settings.sidebar?.links?.length || settings.sidebar?.note) && (_jsxs("div", { class: "docs-sidebar-bottom", children: [settings.sidebar.links?.map((link) => (_jsxs(Link, { link: link, children: [link.icon && _jsx(Icon, { name: link.icon, size: 16 }), link.label, _jsx(Icon, { name: "northeast", size: 13 })] }, link.href))), settings.sidebar.note && _jsx("p", { children: settings.sidebar.note })] }))] }), _jsxs("div", { class: "mobile-doc-nav", children: [_jsx("label", { for: "chapter-select", children: edition }), _jsx("select", { id: "chapter-select", "aria-label": `${tab?.label ?? "Documentation"} chapter`, "data-reader-enhancement": true, hidden: true, children: nav.tabs.map((section) => (_jsx("optgroup", { label: section.label, children: section.groups
58
+ .flatMap((group) => group.items)
59
+ .map((item) => (_jsx("option", { value: href(item.href), selected: section.slug === nav.activeTabSlug && item.id === nav.activePageSlug, children: item.label }))) }))) }), _jsxs("details", { class: "reader-chapter-fallback", "data-reader-fallback": true, children: [_jsx("summary", { children: "Chapters" }), _jsx("nav", { children: nav.tabs.map((section) => (_jsxs(_Fragment, { children: [nav.tabs.length > 1 && _jsx("strong", { children: section.label }), section.groups
60
+ .flatMap((group) => group.items)
61
+ .map((item) => (_jsx("a", { href: href(item.href), children: item.label })))] }))) })] })] }), _jsx("main", { id: "main", class: "docs-main", children: docPage ? (_jsxs(_Fragment, { children: [_jsxs("div", { class: "doc-breadcrumb", children: [_jsx("span", { children: tab?.label }), _jsx(Icon, { name: "chevron", size: 12 }), _jsx("span", { children: edition }), document?.status && (_jsx("span", { class: "pill soft", children: document.badge ?? document.status }))] }), _jsxs("header", { class: "doc-title", children: [_jsx("h1", { children: docPage.title }), docPage.description && _jsx("p", { children: docPage.description })] }), _jsxs("div", { class: "doc-metadata", children: [document?.status && _jsx("span", { children: document.status }), document?.updated && _jsx("span", { children: document.updated }), _jsxs("button", { "data-copy-page": true, "data-reader-enhancement": true, hidden: true, children: [_jsx(Icon, { name: "copy", size: 12 }), _jsx("span", { "aria-live": "polite", children: "Copy link" })] })] }), _jsx("article", { class: "reader-prose", dangerouslySetInnerHTML: { __html: docPage.html } }), (before || after) && (_jsxs("nav", { class: "doc-pagination", "aria-label": "Previous and next chapter", children: [before ? (_jsxs(Link, { link: before, children: [_jsx("span", { children: before.description }), _jsx("strong", { children: before.label })] })) : (_jsx("span", {})), after && (_jsxs(Link, { link: after, children: [_jsx("span", { children: after.description }), _jsx("strong", { children: after.label })] }))] })), _jsxs("footer", { class: "doc-footer", children: [_jsx("span", { children: settings.footer?.text ?? site.name }), _jsxs("span", { class: "doc-footer-links", children: [settings.footer?.links?.map((link) => (_jsxs(Link, { link: link, children: [link.label, _jsx(Icon, { name: "northeast", size: 12 })] }, link.href))), _jsxs("span", { class: "sourcey-attribution", children: ["Docs by", " ", _jsxs("a", { href: "https://sourcey.com", target: "_blank", rel: "noopener noreferrer", children: ["Sourcey", _jsx(Icon, { name: "northeast", size: 12 })] })] })] })] })] })) : (children) }), _jsxs("aside", { class: "docs-toc", "aria-label": "On this page", children: [headings.length > 0 && (_jsxs(_Fragment, { children: [_jsx("span", { class: "eyebrow", children: "On this page" }), _jsx("nav", { children: headings
62
+ .filter((heading) => heading.level === Math.min(...headings.map((h) => h.level)))
63
+ .map((heading) => (_jsx("a", { href: `#${heading.id}`, children: heading.text }))) })] })), settings.aside?.links?.map((link) => (_jsxs(Link, { className: "toc-example", link: link, children: [link.icon && _jsx(Icon, { name: link.icon, size: 19 }), link.description && _jsx("strong", { children: link.description }), _jsxs("span", { children: [link.label, _jsx(Icon, { size: 12 })] })] }, link.href)))] })] }), !searchHref && _jsx(SearchDialog, {})] }));
64
+ }
@@ -0,0 +1,2 @@
1
+ export declare function SearchDialog(): import("preact").JSX.Element;
2
+ //# sourceMappingURL=SearchDialog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SearchDialog.d.ts","sourceRoot":"","sources":["../../../src/components/layout/SearchDialog.tsx"],"names":[],"mappings":"AAAA,wBAAgB,YAAY,iCAyC3B"}
@@ -0,0 +1,4 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "preact/jsx-runtime";
2
+ export function SearchDialog() {
3
+ return (_jsx("div", { id: "search-dialog", role: "dialog", "aria-label": "Search", children: _jsxs("div", { class: "search-dialog-inner", children: [_jsxs("div", { class: "search-input-row", children: [_jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 20 20", fill: "currentColor", class: "search-input-icon", children: _jsx("path", { "fill-rule": "evenodd", d: "M9 3.5a5.5 5.5 0 1 0 0 11 5.5 5.5 0 0 0 0-11ZM2 9a7 7 0 1 1 12.452 4.391l3.328 3.329a.75.75 0 1 1-1.06 1.06l-3.329-3.328A7 7 0 0 1 2 9Z", "clip-rule": "evenodd" }) }), _jsx("input", { id: "search-input", "aria-label": "Search documentation", type: "text", placeholder: "Search docs...", autocomplete: "off", spellcheck: false })] }), _jsx("div", { id: "search-results" }), _jsxs("div", { class: "search-footer", children: [_jsxs("span", { class: "search-footer-hint", children: [_jsx("kbd", { children: "\u2191\u2193" }), " navigate"] }), _jsxs("span", { class: "search-footer-hint", children: [_jsx("kbd", { children: "\u21B5" }), " select"] }), _jsxs("span", { class: "search-footer-hint", children: [_jsx("kbd", { children: "esc" }), " close"] })] })] }) }));
4
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"Operation.d.ts","sourceRoot":"","sources":["../../../src/components/openapi/Operation.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,mBAAmB,EAAyB,MAAM,qBAAqB,CAAC;AAgBtF,UAAU,cAAc;IACtB,SAAS,EAAE,mBAAmB,CAAC;IAC/B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,cAAc,gCA0FrE"}
1
+ {"version":3,"file":"Operation.d.ts","sourceRoot":"","sources":["../../../src/components/openapi/Operation.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,mBAAmB,EAAyB,MAAM,qBAAqB,CAAC;AAgBtF,UAAU,cAAc;IACtB,SAAS,EAAE,mBAAmB,CAAC;IAC/B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,cAAc,gCAuGrE"}
@@ -21,12 +21,12 @@ import { McpReturnsCopy, McpReturnsExample } from "../mcp/McpReturns.js";
21
21
  */
22
22
  export function Operation({ operation: op, serverUrl }) {
23
23
  const site = useContext(SiteContext);
24
- const apiFirst = site.theme.preset === "api-first";
24
+ const apiFirst = site.theme.name === "api-first";
25
25
  const id = `operation-${htmlId(op.path)}-${htmlId(op.method)}`;
26
26
  const hasParams = op.parameters.length > 0;
27
27
  const hasBody = !!op.requestBody;
28
28
  const mcp = op.mcpExtras;
29
- return (_jsxs("div", { id: id, class: "py-8 border-t border-[rgb(var(--color-gray-100))] dark:border-[rgb(var(--color-gray-800))]", "data-traverse-target": id, children: [_jsx("header", { class: "mb-6", children: op.summary && (_jsxs("div", { class: "flex items-baseline gap-2 flex-wrap", children: [_jsx("h2", { class: "text-2xl sm:text-3xl text-[rgb(var(--color-gray-900))] dark:text-[rgb(var(--color-gray-200))] tracking-tight font-bold mb-2", children: _jsx(Markdown, { content: op.summary, inline: true }) }), op.deprecated && _jsx(DeprecatedBadge, {}), mcp?.annotations && _jsx(AnnotationBadges, { annotations: mcp.annotations })] })) }), mcp ? (_jsx(McpEndpointBar, { method: op.method, path: op.path })) : (_jsx(EndpointBar, { method: op.method, path: op.path, serverUrl: serverUrl })), _jsxs("div", { class: `flex flex-col ${apiFirst ? "lg:flex-row" : "xl:flex-row"} gap-8`, children: [_jsxs("div", { class: "flex-1 min-w-0", children: [op.description && (_jsx(Markdown, { content: op.description, class: "mb-6 max-w-none" })), hasBody && (_jsxs("div", { class: "mt-6", children: [_jsx(SectionLabel, { meta: bodyMediaType(op.requestBody), children: "Body" }), _jsx(RequestBody, { body: op.requestBody })] })), hasParams && (_jsxs("div", { class: "mt-6", children: [_jsx(SectionLabel, { children: "Parameters" }), _jsx(Parameters, { parameters: op.parameters })] })), mcp ? (_jsx(McpReturnsCopy, { schema: mcp.outputSchema })) : (op.responses.length > 0 && (_jsxs("div", { class: "mt-6", children: [_jsx(SectionLabel, { children: "Response" }), _jsx(ResponsesCopy, { responses: op.responses })] }))), !mcp && _jsx(SecurityCopy, { security: op.security })] }), _jsxs("aside", { class: `hidden ${apiFirst ? "lg:block" : "xl:block"} w-[28rem] shrink-0 sticky self-start overflow-y-auto space-y-4`, style: "top: calc(var(--header-height) + 2.5rem); max-height: calc(100vh - var(--header-height) - 5rem)", children: [_jsx(CodeSamplesExamples, { operation: op, serverUrl: serverUrl, codeSampleLangs: site.codeSamples }), hasBody && _jsx(RequestBodyExample, { body: op.requestBody }), mcp ? (_jsx(McpReturnsExample, { schema: mcp.outputSchema })) : (_jsx(ResponsesExamples, { responses: op.responses }))] })] }), _jsxs("div", { class: `${apiFirst ? "lg:hidden" : "xl:hidden"} mt-8 space-y-4`, children: [_jsx(CodeSamplesExamples, { operation: op, serverUrl: serverUrl, codeSampleLangs: site.codeSamples }), hasBody && _jsx(RequestBodyExample, { body: op.requestBody }), mcp ? (_jsx(McpReturnsExample, { schema: mcp.outputSchema })) : (_jsx(ResponsesExamples, { responses: op.responses }))] })] }));
29
+ return (_jsxs("div", { id: id, class: "py-8 border-t border-[rgb(var(--color-gray-100))] dark:border-[rgb(var(--color-gray-800))]", "data-traverse-target": id, children: [_jsx("header", { class: "mb-6", children: op.summary && (_jsxs("div", { class: "flex items-baseline gap-2 flex-wrap", children: [_jsx("h2", { class: "text-2xl sm:text-3xl text-[rgb(var(--color-gray-900))] dark:text-[rgb(var(--color-gray-200))] tracking-tight font-bold mb-2", children: _jsx(Markdown, { content: op.summary, inline: true }) }), op.deprecated && _jsx(DeprecatedBadge, {}), mcp?.annotations && _jsx(AnnotationBadges, { annotations: mcp.annotations })] })) }), mcp ? (_jsx(McpEndpointBar, { method: op.method, path: op.path })) : (_jsx(EndpointBar, { method: op.method, path: op.path, serverUrl: serverUrl })), _jsxs("div", { class: `flex flex-col ${apiFirst ? "lg:flex-row" : "xl:flex-row"} gap-8`, children: [_jsxs("div", { class: "flex-1 min-w-0", children: [op.description && _jsx(Markdown, { content: op.description, class: "mb-6 max-w-none" }), hasBody && (_jsxs("div", { class: "mt-6", children: [_jsx(SectionLabel, { meta: bodyMediaType(op.requestBody), children: "Body" }), _jsx(RequestBody, { body: op.requestBody })] })), hasParams && (_jsxs("div", { class: "mt-6", children: [_jsx(SectionLabel, { children: "Parameters" }), _jsx(Parameters, { parameters: op.parameters })] })), mcp ? (_jsx(McpReturnsCopy, { schema: mcp.outputSchema })) : (op.responses.length > 0 && (_jsxs("div", { class: "mt-6", children: [_jsx(SectionLabel, { children: "Response" }), _jsx(ResponsesCopy, { responses: op.responses })] }))), !mcp && _jsx(SecurityCopy, { security: op.security })] }), _jsxs("aside", { class: `hidden ${apiFirst ? "lg:block" : "xl:block"} w-[28rem] shrink-0 sticky self-start overflow-y-auto space-y-4`, style: "top: calc(var(--header-height) + 2.5rem); max-height: calc(100vh - var(--header-height) - 5rem)", children: [_jsx(CodeSamplesExamples, { operation: op, serverUrl: serverUrl, codeSampleLangs: site.codeSamples }), hasBody && _jsx(RequestBodyExample, { body: op.requestBody }), mcp ? (_jsx(McpReturnsExample, { schema: mcp.outputSchema })) : (_jsx(ResponsesExamples, { responses: op.responses }))] })] }), _jsxs("div", { class: `${apiFirst ? "lg:hidden" : "xl:hidden"} mt-8 space-y-4`, children: [_jsx(CodeSamplesExamples, { operation: op, serverUrl: serverUrl, codeSampleLangs: site.codeSamples }), hasBody && _jsx(RequestBodyExample, { body: op.requestBody }), mcp ? (_jsx(McpReturnsExample, { schema: mcp.outputSchema })) : (_jsx(ResponsesExamples, { responses: op.responses }))] })] }));
30
30
  }
31
31
  function bodyMediaType(body) {
32
32
  const types = Object.keys(body.content);
package/dist/config.d.ts CHANGED
@@ -1,10 +1,58 @@
1
1
  import type { PrettyUrls } from "./site-url.js";
2
2
  import type { MarkdownPreprocessor } from "./core/markdown-loader.js";
3
3
  import type { ResolvedTabSource, SourceAdapter } from "./adapters/types.js";
4
+ import { type ThemeName } from "./themes/registry.js";
4
5
  export type { PrettyUrls } from "./site-url.js";
5
- export type ThemePreset = "default" | "minimal" | "api-first";
6
+ export type { ThemeName } from "./themes/registry.js";
7
+ /** @deprecated Use ThemeName. */
8
+ export type ThemePreset = ThemeName;
9
+ export interface ReaderLink {
10
+ /** Optional icon for reader sidebar and aside links. */
11
+ icon?: "code" | "layers";
12
+ label: string;
13
+ href: string;
14
+ /** Optional supporting line for an aside or pagination link. */
15
+ description?: string;
16
+ }
17
+ /** Editorial chrome for long-form documentation. All fields are optional. */
18
+ export interface ReaderThemeConfig {
19
+ document?: {
20
+ label: string;
21
+ title?: string;
22
+ version?: string;
23
+ status?: string;
24
+ /** Short badge when the full status is longer (for example, Draft). */
25
+ badge?: string;
26
+ /** Human-readable publication or revision date; never inferred from build time. */
27
+ updated?: string;
28
+ };
29
+ /** Show the site name beside a mark-only logo. Full wordmarks remain the default. */
30
+ logoMark?: boolean;
31
+ /** Host-authored links and note rendered below the chapter navigation. */
32
+ sidebar?: {
33
+ links?: ReaderLink[];
34
+ note?: string;
35
+ };
36
+ /** Host-authored links rendered below the generated table of contents. */
37
+ aside?: {
38
+ links?: ReaderLink[];
39
+ };
40
+ pagination?: {
41
+ before?: ReaderLink;
42
+ after?: ReaderLink;
43
+ };
44
+ footer?: {
45
+ text?: string;
46
+ links?: ReaderLink[];
47
+ };
48
+ /** Use a host site's search route instead of Sourcey's search dialog. */
49
+ searchHref?: string;
50
+ }
6
51
  export interface ThemeConfig {
7
- preset?: ThemePreset;
52
+ /** Selects the complete rendering theme. */
53
+ name?: ThemeName;
54
+ /** @deprecated Use `name`. Retained for compatibility through the 3.x line. */
55
+ preset?: ThemeName;
8
56
  colors?: {
9
57
  primary: string;
10
58
  light?: string;
@@ -13,6 +61,8 @@ export interface ThemeConfig {
13
61
  fonts?: {
14
62
  sans?: string;
15
63
  mono?: string;
64
+ /** Disable Google Fonts when fonts are supplied through custom CSS. */
65
+ google?: boolean;
16
66
  };
17
67
  layout?: {
18
68
  sidebar?: string;
@@ -20,6 +70,7 @@ export interface ThemeConfig {
20
70
  content?: string;
21
71
  };
22
72
  css?: string[];
73
+ reader?: ReaderThemeConfig;
23
74
  }
24
75
  export interface ChangelogConfig {
25
76
  /** Disable changelog auto-detection for CHANGELOG.md and layout: changelog pages. */
@@ -268,7 +319,7 @@ export interface NavbarLink {
268
319
  }
269
320
  export declare function defineConfig(config: SourceyConfig): SourceyConfig;
270
321
  export interface ResolvedTheme {
271
- preset: ThemePreset;
322
+ name: ThemeName;
272
323
  colors: {
273
324
  primary: string;
274
325
  light: string;
@@ -277,7 +328,7 @@ export interface ResolvedTheme {
277
328
  fonts: {
278
329
  sans: string;
279
330
  mono: string;
280
- googleFont: string;
331
+ googleFont: string | false;
281
332
  };
282
333
  layout: {
283
334
  sidebar: string;
@@ -285,6 +336,7 @@ export interface ResolvedTheme {
285
336
  content: string;
286
337
  };
287
338
  css: string[];
339
+ reader?: ReaderThemeConfig;
288
340
  }
289
341
  export interface ResolvedChangelogConfig {
290
342
  enabled: boolean;