sourcey 3.4.4 → 3.4.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  > Your API docs shouldn't depend on someone else's SaaS.
4
4
 
5
- Sourcey is an open source documentation platform. Point it at an OpenAPI spec, add markdown guides, get a complete docs site. Static HTML you own; no dashboard, no monthly bill, no API calls to render your own documentation. Deploy anywhere.
5
+ Sourcey is an open source documentation platform. Point it at an OpenAPI spec, an MCP server, or a Doxygen XML directory; add markdown guides; get a complete docs site. Static HTML you own; no dashboard, no monthly bill, no API calls to render your own documentation. Deploy anywhere.
6
6
 
7
7
  [![npm](https://img.shields.io/npm/v/sourcey)](https://www.npmjs.com/package/sourcey)
8
8
  [![build](https://img.shields.io/github/actions/workflow/status/sourcey/sourcey/ci.yml?branch=master)](https://github.com/sourcey/sourcey/actions)
@@ -12,36 +12,39 @@ Sourcey is an open source documentation platform. Point it at an OpenAPI spec, a
12
12
  npx sourcey init
13
13
  ```
14
14
 
15
- ![Sourcey](assets/screenshot.jpg)
15
+ ![Sourcey](assets/hero-preview.jpg)
16
16
 
17
17
  **[Live demo](https://cheesestore.github.io/)** · [Documentation](https://sourcey.com/docs) · [GitHub](https://github.com/sourcey/sourcey)
18
18
 
19
19
  ## Features
20
20
 
21
21
  - **API reference from OpenAPI** — endpoints, parameters, request/response schemas, auto-generated code samples in 10 languages (cURL, JavaScript, TypeScript, Python, Go, Ruby, Java, PHP, Rust, C#)
22
- - **Markdown guides with rich components** — steps, cards, accordions, syntax-highlighted code blocks; everything you need for prose docs alongside your API reference
22
+ - **MCP server documentation** — tools, resources, prompts rendered as browsable reference with JSON-RPC, TypeScript, and Python code samples. Color-coded method types, annotation badges, connection config cards
23
+ - **Markdown guides with rich components** — steps, cards, accordions, syntax-highlighted code blocks; prose docs alongside your API reference
24
+ - **C++ and Doxygen** — feed Doxygen XML output, get modern searchable API docs. No new parser, no four-tool Breathe/Exhale/Sphinx pipeline
25
+ - **llms.txt generation** — auto-generate llms.txt and llms-full.txt alongside your HTML. Docs serve developers and AI agents from one build
23
26
  - **TypeScript config** — `sourcey.config.ts` with `defineConfig()` autocomplete; theme, navbar, CTA buttons, footer
24
27
  - **Theme presets** — default (sidebar + TOC), minimal (single column), api-first (Stripe-style three column); colors, fonts, layout dimensions, and custom CSS on top
25
28
  - **Vite dev server** — SSR hot reload on every component and CSS change; spec and markdown changes trigger instant refresh
26
29
  - **Dark mode** — semantic design tokens, light/dark logo variants, localStorage persistence
27
- - **Client-side search** — instant fuzzy search across all pages and API operations
30
+ - **Client-side search** — instant fuzzy search across all pages and API operations; Cmd+K
28
31
  - **Static HTML output** — no framework runtime, no vendor lock-in. Deploy to GitHub Pages, Vercel, Netlify, S3, anywhere
29
32
  - **Open source** — AGPL-3.0. Self-host, fork, extend. Your docs, your infrastructure
30
33
 
31
34
  ### Sourcey vs alternatives
32
35
 
33
- | | Sourcey | Mintlify | GitBook | Fern | Redocly | VitePress |
36
+ | | Sourcey | Redocly | GitBook | Mintlify | Fern | ReadMe |
34
37
  |---|---|---|---|---|---|---|
35
- | OpenAPI reference | Native | Native | No | Native | Native | Plugin |
36
- | Markdown guides | Native | Native | Native | Native | Native | Native |
37
- | Static output you own | Yes | No | No | No | Yes | Yes |
38
- | Zero JS shipped | Yes | No | No | No | No | No (Vue SPA) |
39
- | TypeScript config | Yes | JSON | GUI | YAML | YAML | TS |
40
- | Hot reload dev server | Vite SSR | Cloud | Cloud | Cloud | Webpack | Vite SPA |
41
- | Rich components | Yes | Yes | Limited | Yes | No | Vue |
42
- | Theme presets | Yes | No | No | No | No | Yes |
43
- | Self-hosted | Yes | No | No | No | Yes | Yes |
44
- | Pricing | Free / AGPL | $150+/mo | Free / paid | Paid | Free / paid | Free |
38
+ | Open source | Yes | Partial | No | No | No | No |
39
+ | Static output | Yes | Yes | No | No | No | No |
40
+ | Zero JS shipped | Yes | No | No | No | No | No |
41
+ | MCP server docs | Native | No | No | No | No | No |
42
+ | Doxygen / C++ docs | Native | No | No | No | No | No |
43
+ | Config format | TypeScript | YAML | GUI | JSON | YAML | GUI |
44
+ | Local preview | Vite SSR | Local | Cloud | Local | Local | Cloud |
45
+ | No account required | Yes | Partial | No | No | No | No |
46
+ | Self-hosted | Yes | Yes | No | No | Yes | No |
47
+ | Pricing | Free | $10–$24 | $65–$249 | $250+ | $150+ | $79–$3,000+ |
45
48
 
46
49
  ## Install
47
50
 
@@ -105,6 +108,10 @@ export default defineConfig({
105
108
  tab: "API Reference",
106
109
  openapi: "./openapi.yaml",
107
110
  },
111
+ {
112
+ tab: "MCP Server",
113
+ mcp: "./mcp.json",
114
+ },
108
115
  ],
109
116
  },
110
117
  navbar: {
@@ -117,7 +124,7 @@ export default defineConfig({
117
124
  });
118
125
  ```
119
126
 
120
- Each tab is either an `openapi` spec or `groups` of markdown pages. Pages are referenced by slug (e.g. `"quickstart"` resolves to `quickstart.md`).
127
+ Each tab is an `openapi` spec, an `mcp` snapshot, a `doxygen` directory, or `groups` of markdown pages. Pages are referenced by slug (e.g. `"quickstart"` resolves to `quickstart.md`).
121
128
 
122
129
  ### Markdown components
123
130
 
@@ -1 +1 @@
1
- {"version":3,"file":"Head.d.ts","sourceRoot":"","sources":["../../../src/components/layout/Head.tsx"],"names":[],"mappings":"AAKA,wBAAgB,IAAI,iCAqEnB"}
1
+ {"version":3,"file":"Head.d.ts","sourceRoot":"","sources":["../../../src/components/layout/Head.tsx"],"names":[],"mappings":"AAKA,wBAAgB,IAAI,iCAwEnB"}
@@ -44,5 +44,5 @@ export function Head() {
44
44
  body { margin: 0; background: rgb(var(--color-background-light)); }
45
45
  .dark body { background: rgb(var(--color-background-dark)); }
46
46
  `;
47
- 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}` }), _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 }), _jsx("meta", { name: "twitter:card", content: "summary" }), _jsx("meta", { name: "twitter:title", content: pageTitle }), _jsx("meta", { name: "twitter:description", content: pageDescription }), _jsx("meta", { name: "sourcey-search", content: `${options.assetBase}search-index.json` }), _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 })] }));
47
+ 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}` }), _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 }), _jsx("meta", { name: "twitter:card", content: "summary" }), _jsx("meta", { name: "twitter:title", content: pageTitle }), _jsx("meta", { name: "twitter:description", content: pageDescription }), _jsx("meta", { name: "sourcey-search", content: `${options.assetBase}search-index.json` }), _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 })] }));
48
48
  }
@@ -1 +1 @@
1
- {"version":3,"file":"Header.d.ts","sourceRoot":"","sources":["../../../src/components/layout/Header.tsx"],"names":[],"mappings":"AA6EA;;;;;GAKG;AACH,wBAAgB,MAAM,iCAiIrB"}
1
+ {"version":3,"file":"Header.d.ts","sourceRoot":"","sources":["../../../src/components/layout/Header.tsx"],"names":[],"mappings":"AA6EA;;;;;GAKG;AACH,wBAAgB,MAAM,iCAsIrB"}
@@ -39,10 +39,10 @@ export function Header() {
39
39
  const logoHref = site.logo?.href ?? `${base}${nav.tabs[0]?.href ?? ""}`;
40
40
  return (_jsxs("div", { id: "navbar", class: "z-30 fixed lg:sticky top-0 w-full", children: [_jsx("div", { class: "absolute w-full h-full flex-none border-b border-[rgb(var(--color-gray-200)/0.7)] dark:border-[rgb(var(--color-gray-300)/0.06)] bg-[rgb(var(--color-background-light))] dark:bg-[rgb(var(--color-background-dark))]" }), _jsxs("div", { class: "max-w-[92rem] mx-auto relative", children: [_jsx("div", { class: "relative", children: _jsx("div", { class: "flex items-center lg:px-12 h-16 min-w-0 mx-4 lg:mx-0", children: _jsxs("div", { class: "h-full relative flex-1 flex items-center gap-x-4 min-w-0 border-b border-[rgb(var(--color-gray-500)/0.08)] dark:border-[rgb(var(--color-gray-300)/0.08)]", children: [_jsx("div", { class: "flex-1 flex items-center gap-x-4", children: _jsx(Logo, { href: logoHref, logo: site.logo, name: site.name }) }), _jsx("div", { class: "relative hidden lg:flex items-center flex-1 z-20 gap-2", children: _jsx("button", { id: "search-open", type: "button", class: "group flex pointer-events-auto rounded-lg w-full items-center text-sm leading-6 h-9 pl-3.5 pr-3 text-[rgb(var(--color-gray-500))] dark:text-[rgb(var(--color-gray-400))] ring-1 ring-[rgb(var(--color-gray-400)/0.3)] hover:ring-[rgb(var(--color-gray-600)/0.3)] dark:ring-[rgb(var(--color-gray-600)/0.3)] dark:hover:ring-[rgb(var(--color-gray-500)/0.3)] justify-between truncate gap-2 min-w-[43px] cursor-pointer bg-[rgb(var(--color-background-light))] dark:bg-[rgb(var(--color-background-dark))] dark:brightness-110 dark:hover:brightness-125", children: _jsxs("div", { class: "flex items-center gap-2 min-w-[42px]", children: [_jsx(SearchIcon, {}), _jsxs("div", { class: "truncate min-w-0", children: ["Type ", _jsx("kbd", { children: "/" }), " to search"] })] }) }) }), _jsxs("div", { class: "flex-1 relative hidden lg:flex items-center ml-auto justify-end space-x-4", children: [_jsx("nav", { class: "text-sm", children: _jsxs("ul", { class: "flex space-x-6 items-center", children: [site.navbar.links.map((link) => (_jsx("li", { children: _jsx("a", { href: link.href, target: "_blank", rel: "noopener noreferrer", "aria-label": link.label ?? socialLabels[link.type] ?? link.href, class: "text-[rgb(var(--color-gray-500))] hover:text-[rgb(var(--color-gray-700))] dark:text-[rgb(var(--color-gray-400))] dark:hover:text-[rgb(var(--color-gray-300))]", children: link.type === "link"
41
41
  ? (link.label ?? link.href)
42
- : (_jsxs(_Fragment, { children: [_jsx(SocialIcon, { type: link.type }), link.label && _jsx("span", { class: "ml-1", children: link.label })] })) }) }, link.href))), site.navbar.primary && (_jsx("li", { children: _jsxs("a", { href: site.navbar.primary.href, target: "_blank", class: "group px-4 py-1.5 relative inline-flex items-center text-sm font-medium", children: [_jsx("span", { class: "absolute inset-0 bg-[rgb(var(--color-primary-dark))] rounded-lg group-hover:opacity-90" }), _jsx("span", { class: "z-10 text-white", children: site.navbar.primary.label })] }) }))] }) }), _jsxs("button", { id: "theme-toggle", type: "button", "aria-label": "Toggle theme", class: "p-2 flex items-center justify-center cursor-pointer text-[rgb(var(--color-gray-400))] hover:text-[rgb(var(--color-gray-600))] dark:text-[rgb(var(--color-gray-500))] dark:hover:text-[rgb(var(--color-gray-300))]", children: [_jsx(SunIcon, {}), _jsx(MoonIcon, {})] })] }), _jsxs("div", { class: "flex lg:hidden items-center gap-3", children: [_jsx("button", { id: "search-open-mobile", type: "button", "aria-label": "Search", class: "text-[rgb(var(--color-gray-500))] w-8 h-8 flex items-center justify-center", children: _jsx(SearchIcon, {}) }), _jsx("button", { type: "button", "data-drawer-slide": "right", "aria-label": "Open menu", class: "text-[rgb(var(--color-gray-500))] w-8 h-8 flex items-center justify-center hover:text-[rgb(var(--color-gray-600))]", children: _jsx("svg", { class: "h-4", fill: "currentColor", xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 448 512", children: _jsx("path", { d: "M0 96C0 78.3 14.3 64 32 64H416c17.7 0 32 14.3 32 32s-14.3 32-32 32H32C14.3 128 0 113.7 0 96zM0 256c0-17.7 14.3-32 32-32H416c17.7 0 32 14.3 32 32s-14.3 32-32 32H32c-17.7 0-32-14.3-32-32zM448 416c0 17.7-14.3 32-32 32H32c-17.7 0-32-14.3-32-32s14.3-32 32-32H416c17.7 0 32 14.3 32 32z" }) }) })] })] }) }) }), _jsx(MobileBreadcrumbs, { nav: nav }), nav.tabs.length > 1 && (_jsx("div", { class: "hidden lg:flex px-12 h-12", children: _jsx("div", { class: "h-full flex text-sm gap-x-6", children: nav.tabs.map((tab) => {
42
+ : (_jsxs(_Fragment, { children: [_jsx(SocialIcon, { type: link.type }), link.label && _jsx("span", { class: "ml-1", children: link.label })] })) }) }, link.href))), site.navbar.primary && (_jsx("li", { children: _jsxs("a", { href: site.navbar.primary.href, target: "_blank", class: "group px-4 py-1.5 relative inline-flex items-center text-sm font-medium", children: [_jsx("span", { class: "absolute inset-0 bg-[rgb(var(--color-primary-dark))] rounded-lg group-hover:opacity-90" }), _jsxs("div", { class: "mr-0.5 space-x-2.5 flex items-center text-white", children: [_jsx("span", { class: "z-10", children: site.navbar.primary.label }), _jsx("svg", { width: "3", height: "6", viewBox: "0 0 3 6", class: "overflow-visible opacity-90", children: _jsx("path", { d: "M0 0L3 3L0 6", fill: "none", stroke: "currentColor", "stroke-width": "1.5", "stroke-linecap": "round" }) })] })] }) }))] }) }), _jsxs("button", { id: "theme-toggle", type: "button", "aria-label": "Toggle theme", class: "p-2 flex items-center justify-center cursor-pointer text-[rgb(var(--color-gray-400))] hover:text-[rgb(var(--color-gray-600))] dark:text-[rgb(var(--color-gray-500))] dark:hover:text-[rgb(var(--color-gray-300))]", children: [_jsx(SunIcon, {}), _jsx(MoonIcon, {})] })] }), _jsxs("div", { class: "flex lg:hidden items-center gap-3", children: [_jsx("button", { id: "search-open-mobile", type: "button", "aria-label": "Search", class: "text-[rgb(var(--color-gray-500))] w-8 h-8 flex items-center justify-center", children: _jsx(SearchIcon, {}) }), _jsx("button", { type: "button", "data-drawer-slide": "right", "aria-label": "Open menu", class: "text-[rgb(var(--color-gray-500))] w-8 h-8 flex items-center justify-center hover:text-[rgb(var(--color-gray-600))]", children: _jsx("svg", { class: "h-4", fill: "currentColor", xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 448 512", children: _jsx("path", { d: "M0 96C0 78.3 14.3 64 32 64H416c17.7 0 32 14.3 32 32s-14.3 32-32 32H32C14.3 128 0 113.7 0 96zM0 256c0-17.7 14.3-32 32-32H416c17.7 0 32 14.3 32 32s-14.3 32-32 32H32c-17.7 0-32-14.3-32-32zM448 416c0 17.7-14.3 32-32 32H32c-17.7 0-32-14.3-32-32s14.3-32 32-32H416c17.7 0 32 14.3 32 32z" }) }) })] })] }) }) }), _jsx(MobileBreadcrumbs, { nav: nav }), nav.tabs.length > 1 && (_jsx("div", { class: "hidden lg:flex px-12 h-12", children: _jsx("div", { class: "h-full flex text-sm gap-x-6", children: nav.tabs.map((tab) => {
43
43
  const isActive = tab.slug === nav.activeTabSlug;
44
44
  return (_jsxs("a", { href: `${base}${tab.href}`, class: `group relative h-full gap-2 flex items-center font-medium cursor-pointer transition-colors ${isActive
45
- ? "text-[rgb(var(--color-gray-800))] dark:text-[rgb(var(--color-gray-200))]"
45
+ ? "text-[rgb(var(--color-gray-800))] dark:text-[rgb(var(--color-gray-200))] [text-shadow:-0.2px_0_0_currentColor,0.2px_0_0_currentColor]"
46
46
  : "text-[rgb(var(--color-gray-600))] dark:text-[rgb(var(--color-gray-400))] hover:text-[rgb(var(--color-gray-800))] dark:hover:text-[rgb(var(--color-gray-300))]"}`, children: [tab.label, isActive ? (_jsx("div", { class: "absolute bottom-0 h-[1.5px] w-full left-0 bg-[rgb(var(--color-primary))] dark:bg-[rgb(var(--color-primary-light))]" })) : (_jsx("div", { class: "absolute bottom-0 h-[1.5px] w-full left-0 group-hover:bg-[rgb(var(--color-gray-200))] dark:group-hover:bg-[rgb(var(--color-gray-700))]" }))] }, tab.slug));
47
47
  }) }) }))] })] }));
48
48
  }
@@ -1 +1 @@
1
- {"version":3,"file":"Page.d.ts","sourceRoot":"","sources":["../../../src/components/layout/Page.tsx"],"names":[],"mappings":"AAiPA,wBAAgB,IAAI,iCAqCnB"}
1
+ {"version":3,"file":"Page.d.ts","sourceRoot":"","sources":["../../../src/components/layout/Page.tsx"],"names":[],"mappings":"AAsPA,wBAAgB,IAAI,iCAqCnB"}
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "preact/jsx-runtime";
2
2
  import { useContext } from "preact/hooks";
3
- import { SpecContext, PageContext, NavigationContext, SiteContext } from "../../renderer/context.js";
3
+ import { SpecContext, PageContext, NavigationContext, OptionsContext, SiteContext } from "../../renderer/context.js";
4
4
  import { Markdown } from "../ui/Markdown.js";
5
5
  import { Header } from "./Header.js";
6
6
  import { Sidebar } from "./Sidebar.js";
@@ -32,6 +32,7 @@ function SpecPageContent({ className = "" }) {
32
32
  }
33
33
  function PageNavigation() {
34
34
  const nav = useContext(NavigationContext);
35
+ const options = useContext(OptionsContext);
35
36
  const activeTab = nav.tabs.find((t) => t.slug === nav.activeTabSlug);
36
37
  if (!activeTab)
37
38
  return null;
@@ -47,7 +48,8 @@ function PageNavigation() {
47
48
  const linkClass = "group flex flex-col gap-1 px-4 py-3 rounded-lg border border-[rgb(var(--color-gray-200)/0.7)] dark:border-[rgb(var(--color-gray-800)/0.5)] hover:border-[rgb(var(--color-primary)/0.4)] dark:hover:border-[rgb(var(--color-primary-light)/0.3)] transition-colors no-underline";
48
49
  const labelClass = "text-xs text-[rgb(var(--color-gray-500))] dark:text-[rgb(var(--color-gray-400))]";
49
50
  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";
50
- return (_jsxs("nav", { class: "mt-12 flex items-stretch justify-between gap-4", children: [prev ? (_jsxs("a", { href: 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: next.href, class: `${linkClass} text-right ml-auto`, children: [_jsx("span", { class: labelClass, children: "Next \u2192" }), _jsx("span", { class: titleClass, children: next.label })] })) : null] }));
51
+ const base = options.assetBase;
52
+ 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] }));
51
53
  }
52
54
  function ContentFooter() {
53
55
  const site = useContext(SiteContext);
@@ -55,10 +57,13 @@ function ContentFooter() {
55
57
  const links = site.footer.links;
56
58
  // Build "Edit this page" URL when repo + editBranch are configured
57
59
  let editUrl;
58
- if (site.repo && site.editBranch && page.kind === "markdown" && page.markdown?.sourcePath) {
60
+ const editPath = page.kind === "markdown"
61
+ ? (page.markdown?.editPath === undefined ? page.markdown?.sourcePath : page.markdown?.editPath)
62
+ : undefined;
63
+ if (site.repo && site.editBranch && editPath) {
59
64
  const repoBase = site.repo.replace(/\/$/, "");
60
65
  const basePath = site.editBasePath ? `${site.editBasePath.replace(/^\/|\/$/g, "")}/` : "";
61
- editUrl = `${repoBase}/edit/${site.editBranch}/${basePath}${page.markdown.sourcePath}`;
66
+ editUrl = `${repoBase}/edit/${site.editBranch}/${basePath}${editPath}`;
62
67
  }
63
68
  const linkStyle = "hover:text-[rgb(var(--color-gray-600))] dark:hover:text-[rgb(var(--color-gray-300))] transition-colors";
64
69
  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"
@@ -70,7 +75,7 @@ function ContentFooter() {
70
75
  // ---------------------------------------------------------------------------
71
76
  function DefaultLayout() {
72
77
  const page = useContext(PageContext);
73
- return (_jsxs("div", { class: "max-w-[92rem] mx-auto relative px-4 lg:px-12", children: [_jsx(Sidebar, {}), _jsx("main", { id: "docs", class: "pt-[8.5rem] lg:pt-10", children: page.kind === "markdown" ? (_jsxs("div", { class: "flex flex-row-reverse gap-12 box-border w-full", children: [_jsx(TableOfContents, { headings: page.markdown.headings }), _jsx(MarkdownPageContent, { page: page.markdown, className: "lg:pl-[23.7rem] lg:-ml-12 xl:w-[calc(100%-28rem)]" })] })) : (_jsx(SpecPageContent, { className: "lg:pl-[23.7rem] lg:-ml-12" })) })] }));
78
+ return (_jsxs("div", { class: "max-w-[92rem] mx-auto relative px-4 lg:px-8", children: [_jsx(Sidebar, {}), _jsx("main", { id: "docs", class: "pt-[8.5rem] lg:pt-10", children: page.kind === "markdown" ? (_jsxs("div", { class: "flex flex-row-reverse gap-12 box-border w-full", children: [_jsx(TableOfContents, { headings: page.markdown.headings }), _jsx(MarkdownPageContent, { page: page.markdown, className: "lg:pl-[23.7rem] lg:-ml-8 xl:w-[calc(100%-28rem)]" })] })) : (_jsx(SpecPageContent, { className: "lg:pl-[23.7rem] lg:-ml-8" })) })] }));
74
79
  }
75
80
  function MinimalLayout() {
76
81
  const page = useContext(PageContext);
@@ -78,7 +83,7 @@ function MinimalLayout() {
78
83
  }
79
84
  function ApiFirstLayout() {
80
85
  const page = useContext(PageContext);
81
- return (_jsxs("div", { class: "max-w-[92rem] mx-auto relative px-4 lg:px-12", children: [_jsx(Sidebar, {}), _jsx("main", { id: "docs", class: "pt-[8.5rem] lg:pt-10", children: page.kind === "markdown" ? (_jsxs("div", { class: "flex flex-row-reverse gap-12 box-border w-full", children: [_jsx(TableOfContents, { headings: page.markdown.headings }), _jsx(MarkdownPageContent, { page: page.markdown, className: "lg:pl-[23.7rem] lg:-ml-12 xl:w-[calc(100%-28rem)]" })] })) : (_jsx(SpecPageContent, { className: "lg:pl-[23.7rem] lg:-ml-12" })) })] }));
86
+ return (_jsxs("div", { class: "max-w-[92rem] mx-auto relative px-4 lg:px-8", children: [_jsx(Sidebar, {}), _jsx("main", { id: "docs", class: "pt-[8.5rem] lg:pt-10", children: page.kind === "markdown" ? (_jsxs("div", { class: "flex flex-row-reverse gap-12 box-border w-full", children: [_jsx(TableOfContents, { headings: page.markdown.headings }), _jsx(MarkdownPageContent, { page: page.markdown, className: "lg:pl-[23.7rem] lg:-ml-8 xl:w-[calc(100%-28rem)]" })] })) : (_jsx(SpecPageContent, { className: "lg:pl-[23.7rem] lg:-ml-8" })) })] }));
82
87
  }
83
88
  // ---------------------------------------------------------------------------
84
89
  // Page shell
@@ -32,7 +32,7 @@ function MethodPill({ method }) {
32
32
  * Shared nav group rendering used by both desktop sidebar and mobile drawer.
33
33
  */
34
34
  function NavGroups({ groups, activePageSlug, base }) {
35
- return (_jsx(_Fragment, { children: groups.map((group, gi) => (_jsxs("div", { class: gi > 0 ? "mt-5" : "", children: [group.label && (_jsx("h5", { class: "nav-group-label", children: group.label })), _jsx("ul", { class: "space-y-0.5", children: group.items.map((item) => {
35
+ return (_jsx(_Fragment, { children: groups.map((group, gi) => (_jsxs("div", { class: gi > 0 ? "mt-6 lg:mt-8" : "", children: [group.label && (_jsx("h5", { class: "nav-group-label", children: group.label })), _jsx("ul", { class: "space-y-px", children: group.items.map((item) => {
36
36
  const isActive = item.id === activePageSlug;
37
37
  return (_jsx("li", { children: _jsxs("a", { href: `${base}${item.href}`, class: `nav-link${isActive ? " active" : ""}`, children: [item.method && _jsx(MethodPill, { method: item.method }), _jsx("span", { class: "flex-1 break-words [word-break:break-word]", children: item.label })] }) }, item.id));
38
38
  }) })] }, group.label))) }));
@@ -17,10 +17,10 @@ function TocList({ headings }) {
17
17
  groups[groups.length - 1].children.push(h);
18
18
  }
19
19
  }
20
- return (_jsx("ul", { children: groups.map((g) => (_jsxs("li", { children: [_jsx("a", { href: `#${g.root.id}`, class: `${tocLink} py-1`, children: g.root.text }), g.children.length > 0 && (_jsx("ul", { children: g.children.map((c) => (_jsx("li", { children: _jsx("a", { href: `#${c.id}`, class: `${tocLink} pl-3 text-[13px] py-0.5`, children: c.text }) }, c.id))) }))] }, g.root.id))) }));
20
+ return (_jsx("ul", { children: groups.map((g) => (_jsxs("li", { children: [_jsx("a", { href: `#${g.root.id}`, class: `${tocLink} py-1 font-medium`, children: g.root.text }), g.children.length > 0 && (_jsx("ul", { class: "mb-2", children: g.children.map((c) => (_jsx("li", { children: _jsx("a", { href: `#${c.id}`, class: `${tocLink} pl-3 py-1 text-[rgb(var(--color-gray-500))]`, children: c.text }) }, c.id))) }))] }, g.root.id))) }));
21
21
  }
22
22
  export function TableOfContents({ headings }) {
23
23
  if (headings.length === 0)
24
24
  return null;
25
- return (_jsx("aside", { id: "toc", class: "hidden xl:flex self-start sticky xl:flex-col max-w-[28rem] z-[21]", style: "height: calc(100vh - var(--header-height) - 2.5rem); top: calc(var(--header-height) + 2.5rem)", children: _jsx("div", { class: "z-10 hidden xl:flex box-border max-h-full pl-10 w-[19rem]", children: _jsxs("div", { class: "text-[rgb(var(--color-gray-600))] text-sm leading-6 w-[16.5rem] overflow-y-auto space-y-2 pb-4 -mt-10 pt-10", children: [_jsxs("h5", { class: "font-semibold text-[rgb(var(--color-gray-900))] dark:text-[rgb(var(--color-gray-200))] flex items-center gap-1.5", children: [_jsx("svg", { class: "shrink-0", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "1.5", dangerouslySetInnerHTML: { __html: iconPath("book") ?? "" } }), "On this page"] }), _jsx("nav", { children: _jsx(TocList, { headings: headings }) })] }) }) }));
25
+ return (_jsx("aside", { id: "toc", class: "hidden xl:flex self-start sticky xl:flex-col max-w-[28rem] z-[21]", style: "height: calc(100vh - var(--header-height) - 2.5rem); top: calc(var(--header-height) + 2.5rem)", children: _jsx("div", { class: "z-10 hidden xl:flex box-border max-h-full pl-10 w-[19rem]", children: _jsxs("div", { class: "text-[rgb(var(--color-gray-600))] text-sm leading-6 w-[16.5rem] overflow-y-auto space-y-2 pb-4 -mt-10 pt-10", children: [_jsxs("h5", { class: "font-medium text-[rgb(var(--color-gray-700))] dark:text-[rgb(var(--color-gray-300))] flex items-center gap-2", children: [_jsx("svg", { class: "shrink-0", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "1.5", dangerouslySetInnerHTML: { __html: iconPath("book-open") ?? "" } }), "On this page"] }), _jsx("nav", { children: _jsx(TocList, { headings: headings }) })] }) }) }));
26
26
  }
package/dist/config.d.ts CHANGED
@@ -107,6 +107,7 @@ export interface ResolvedTheme {
107
107
  fonts: {
108
108
  sans: string;
109
109
  mono: string;
110
+ googleFont: string;
110
111
  };
111
112
  layout: {
112
113
  sidebar: string;
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
package/dist/config.js CHANGED
@@ -12,10 +12,9 @@ const DEFAULT_COLORS = {
12
12
  light: "129 140 248",
13
13
  dark: "79 70 229",
14
14
  };
15
- const DEFAULT_FONTS = {
16
- sans: "ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif",
17
- mono: "ui-monospace, 'SF Mono', 'Cascadia Code', Consolas, 'Liberation Mono', Menlo, monospace",
18
- };
15
+ const DEFAULT_FONT_SANS = "Inter";
16
+ const SYSTEM_SANS = "ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif";
17
+ const SYSTEM_MONO = "ui-monospace, 'SF Mono', 'Cascadia Code', Consolas, 'Liberation Mono', Menlo, monospace";
19
18
  const DEFAULT_LAYOUT = {
20
19
  sidebar: "18rem",
21
20
  toc: "19rem",
@@ -51,7 +50,7 @@ export function configFromSpec(specPath) {
51
50
  theme: {
52
51
  preset: "default",
53
52
  colors: { ...DEFAULT_COLORS },
54
- fonts: { ...DEFAULT_FONTS },
53
+ fonts: { sans: `'${DEFAULT_FONT_SANS}', ${SYSTEM_SANS}`, mono: SYSTEM_MONO, googleFont: DEFAULT_FONT_SANS },
55
54
  layout: { ...DEFAULT_LAYOUT },
56
55
  css: [],
57
56
  },
@@ -105,15 +104,12 @@ function resolveTheme(raw, configDir) {
105
104
  dark: rawColors.dark ? hexToRgb(rawColors.dark) : hexToRgb(rawColors.primary),
106
105
  }
107
106
  : { ...DEFAULT_COLORS };
108
- const userSans = raw.theme?.fonts?.sans;
109
- const userMono = raw.theme?.fonts?.mono;
107
+ const sansName = raw.theme?.fonts?.sans ?? DEFAULT_FONT_SANS;
108
+ const monoName = raw.theme?.fonts?.mono;
110
109
  const fonts = {
111
- sans: userSans
112
- ? `'${userSans}', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif`
113
- : DEFAULT_FONTS.sans,
114
- mono: userMono
115
- ? `'${userMono}', 'SF Mono', 'Fira Code', Consolas, monospace`
116
- : DEFAULT_FONTS.mono,
110
+ sans: `'${sansName}', ${SYSTEM_SANS}`,
111
+ mono: monoName ? `'${monoName}', ${SYSTEM_MONO}` : SYSTEM_MONO,
112
+ googleFont: sansName,
117
113
  };
118
114
  const layout = {
119
115
  sidebar: raw.theme?.layout?.sidebar ?? DEFAULT_LAYOUT.sidebar,
@@ -255,7 +251,11 @@ export function slugify(name) {
255
251
  }
256
252
  /** Build a path under a tab, handling empty slugs (root-level tabs). */
257
253
  export function tabPath(tabSlug, file) {
258
- return tabSlug ? `${tabSlug}/${file}` : file;
254
+ if (!tabSlug)
255
+ return file;
256
+ if (file.startsWith(`${tabSlug}/`))
257
+ return file;
258
+ return `${tabSlug}/${file}`;
259
259
  }
260
260
  export function hexToRgb(hex) {
261
261
  const h = hex.replace("#", "");
@@ -6,5 +6,9 @@ export interface DoxygenResult {
6
6
  navTab: SiteTab;
7
7
  }
8
8
  export declare function normalizeDoxygenDescription(description: string, markdown: string): string;
9
+ export declare function rewriteGeneratedDoxygenIncludePath(includePath: string): string;
10
+ export declare function rewriteGeneratedDoxygenMarkdown(markdown: string): string;
11
+ export declare function rewriteGeneratedDoxygenHref(href: string): string;
12
+ export declare function rewriteGeneratedDoxygenHtmlLinks(html: string): string;
9
13
  export declare function loadDoxygenTab(config: ResolvedDoxygenConfig, tabSlug: string, tabLabel: string): Promise<DoxygenResult>;
10
14
  //# sourceMappingURL=doxygen-loader.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"doxygen-loader.d.ts","sourceRoot":"","sources":["../../src/core/doxygen-loader.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAqB,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAE7E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,KAAK,EAAE,OAAO,EAA6B,MAAM,iBAAiB,CAAC;AAM1E,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IACjC,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,wBAAgB,2BAA2B,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAMzF;AAED,wBAAsB,cAAc,CAClC,MAAM,EAAE,qBAAqB,EAC7B,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,aAAa,CAAC,CA6FxB"}
1
+ {"version":3,"file":"doxygen-loader.d.ts","sourceRoot":"","sources":["../../src/core/doxygen-loader.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAqB,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAE7E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,KAAK,EAAE,OAAO,EAA6B,MAAM,iBAAiB,CAAC;AAM1E,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IACjC,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,wBAAgB,2BAA2B,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAMzF;AAED,wBAAgB,kCAAkC,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAoB9E;AAED,wBAAgB,+BAA+B,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAIxE;AAED,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAShE;AAED,wBAAgB,gCAAgC,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAQrE;AAED,wBAAsB,cAAc,CAClC,MAAM,EAAE,qBAAqB,EAC7B,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,aAAa,CAAC,CAgGxB"}
@@ -8,6 +8,47 @@ export function normalizeDoxygenDescription(description, markdown) {
8
8
  const firstParagraph = extractFirstParagraph(markdown);
9
9
  return firstParagraph || description;
10
10
  }
11
+ export function rewriteGeneratedDoxygenIncludePath(includePath) {
12
+ const normalized = includePath.replace(/\\/g, "/");
13
+ if (!normalized.startsWith("/") && !/^[A-Za-z]:\//.test(normalized)) {
14
+ return includePath;
15
+ }
16
+ const includeMarker = "/include/";
17
+ const includeIndex = normalized.lastIndexOf(includeMarker);
18
+ if (includeIndex !== -1) {
19
+ return normalized.slice(includeIndex + includeMarker.length);
20
+ }
21
+ const srcMarker = "/src/";
22
+ const srcIndex = normalized.indexOf(srcMarker);
23
+ if (srcIndex !== -1) {
24
+ return normalized.slice(srcIndex + 1);
25
+ }
26
+ const basename = normalized.split("/").pop();
27
+ return basename || includePath;
28
+ }
29
+ export function rewriteGeneratedDoxygenMarkdown(markdown) {
30
+ return markdown.replace(/^#include ([<"])([^>\n"]+)([>"])$/gm, (_match, open, includePath, close) => {
31
+ return `#include ${open}${rewriteGeneratedDoxygenIncludePath(includePath)}${close}`;
32
+ });
33
+ }
34
+ export function rewriteGeneratedDoxygenHref(href) {
35
+ const [path, hash] = href.split("#", 2);
36
+ if (!path.startsWith("api_") || !path.endsWith(".md"))
37
+ return href;
38
+ const slug = path
39
+ .slice("api_".length, -".md".length)
40
+ .replace(/--/g, "-");
41
+ return `${slug}.html${hash ? `#${hash}` : ""}`;
42
+ }
43
+ export function rewriteGeneratedDoxygenHtmlLinks(html) {
44
+ return html
45
+ .replace(/href="(api_[^"]+?\.md(?:#[^"]*)?)"/g, (_match, href) => {
46
+ return `href="${rewriteGeneratedDoxygenHref(href)}"`;
47
+ })
48
+ .replace(/<code>\[([^\]]+)\]\((api_[^)]+?\.md(?:#[^)]+)?)\)<\/code>/g, (_match, label, href) => {
49
+ return `<a href="${rewriteGeneratedDoxygenHref(href)}"><code>${label}</code></a>`;
50
+ });
51
+ }
11
52
  export async function loadDoxygenTab(config, tabSlug, tabLabel) {
12
53
  const generated = await generate({
13
54
  directory: config.xml,
@@ -19,16 +60,18 @@ export async function loadDoxygenTab(config, tabSlug, tabLabel) {
19
60
  for (const page of generated) {
20
61
  if (!page.markdown.trim())
21
62
  continue;
22
- const description = normalizeDoxygenDescription(page.description, page.markdown);
23
- const html = renderMarkdown(page.markdown);
24
- const headings = extractHeadings(page.markdown);
63
+ const markdown = rewriteGeneratedDoxygenMarkdown(page.markdown);
64
+ const description = normalizeDoxygenDescription(page.description, markdown);
65
+ const html = rewriteGeneratedDoxygenHtmlLinks(renderMarkdown(markdown));
66
+ const headings = extractHeadings(markdown);
25
67
  pages.set(page.slug, {
26
68
  title: page.title,
27
69
  description,
28
70
  slug: page.slug,
29
71
  html,
30
72
  headings,
31
- sourcePath: config.xml,
73
+ sourcePath: `api/${page.slug}.md`,
74
+ editPath: page.kind === "group" ? `api/${page.slug}.md` : null,
32
75
  });
33
76
  // Group by the last segment of namespace (e.g. "icy::http" -> "http")
34
77
  const groupKey = page.module ?? lastSegment(page.namespace) ?? "API";
@@ -74,7 +117,8 @@ export async function loadDoxygenTab(config, tabSlug, tabLabel) {
74
117
  slug: indexSlug,
75
118
  html: indexHtml,
76
119
  headings: indexHeadings,
77
- sourcePath: config.xml,
120
+ sourcePath: `api/${indexSlug}.md`,
121
+ editPath: null,
78
122
  });
79
123
  groups.unshift({
80
124
  label: tabLabel,
@@ -12,6 +12,8 @@ export interface MarkdownPage {
12
12
  headings: PageHeading[];
13
13
  /** Original file path (for error messages and dev server watching) */
14
14
  sourcePath: string;
15
+ /** Optional repo-relative path used for "Edit this page" links. Null disables the link. */
16
+ editPath?: string | null;
15
17
  }
16
18
  export type { PageHeading } from "../utils/markdown.js";
17
19
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"markdown-loader.d.ts","sourceRoot":"","sources":["../../src/core/markdown-loader.ts"],"names":[],"mappings":"AAKA,OAAO,EAAmC,KAAK,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAMzF,MAAM,WAAW,YAAY;IAC3B,kCAAkC;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,wCAAwC;IACxC,WAAW,EAAE,MAAM,CAAC;IACpB,qDAAqD;IACrD,IAAI,EAAE,MAAM,CAAC;IACb,yBAAyB;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,qDAAqD;IACrD,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,sEAAsE;IACtE,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,YAAY,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAmcxD;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,YAAY,CAAC,CAmBvB;AAUD;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAIrD"}
1
+ {"version":3,"file":"markdown-loader.d.ts","sourceRoot":"","sources":["../../src/core/markdown-loader.ts"],"names":[],"mappings":"AAKA,OAAO,EAKL,KAAK,WAAW,EACjB,MAAM,sBAAsB,CAAC;AAM9B,MAAM,WAAW,YAAY;IAC3B,kCAAkC;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,wCAAwC;IACxC,WAAW,EAAE,MAAM,CAAC;IACpB,qDAAqD;IACrD,IAAI,EAAE,MAAM,CAAC;IACb,yBAAyB;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,qDAAqD;IACrD,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,sEAAsE;IACtE,UAAU,EAAE,MAAM,CAAC;IACnB,2FAA2F;IAC3F,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,YAAY,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAuoCxD;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,YAAY,CAAC,CA6BvB;AAUD;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAIrD"}