sourcey 3.4.1 → 3.4.3

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.
@@ -4,5 +4,5 @@ import { jsx as _jsx, jsxs as _jsxs } from "preact/jsx-runtime";
4
4
  * Used for "Body", "Parameters", "Response" sections.
5
5
  */
6
6
  export function SectionLabel({ children, meta }) {
7
- return (_jsxs("div", { class: "flex items-baseline border-b pb-2.5 border-[rgb(var(--color-gray-100))] dark:border-[rgb(var(--color-gray-800))] w-full mb-4", children: [_jsx("h4", { class: "flex-1 mb-0 text-sm font-semibold text-[rgb(var(--color-gray-900))] dark:text-[rgb(var(--color-gray-200))]", children: children }), meta && (_jsx("div", { class: "flex items-center gap-2 text-xs font-medium font-mono text-[rgb(var(--color-gray-500))]", children: meta }))] }));
7
+ return (_jsxs("div", { class: "flex items-baseline border-b pb-2.5 border-[rgb(var(--color-gray-100))] dark:border-[rgb(var(--color-gray-800))] w-full mb-4", children: [_jsx("h3", { class: "flex-1 mb-0 text-sm font-semibold text-[rgb(var(--color-gray-900))] dark:text-[rgb(var(--color-gray-200))]", children: children }), meta && (_jsx("div", { class: "flex items-center gap-2 text-xs font-medium font-mono text-[rgb(var(--color-gray-500))]", children: meta }))] }));
8
8
  }
package/dist/config.js CHANGED
@@ -13,8 +13,8 @@ const DEFAULT_COLORS = {
13
13
  dark: "79 70 229",
14
14
  };
15
15
  const DEFAULT_FONTS = {
16
- sans: "'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif",
17
- mono: "'Geist Mono', 'SF Mono', 'Fira Code', 'Cascadia Code', Consolas, monospace",
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
18
  };
19
19
  const DEFAULT_LAYOUT = {
20
20
  sidebar: "18rem",
@@ -73,7 +73,7 @@ export async function resolveConfigFromRaw(raw, configDir) {
73
73
  name: raw.name ?? "",
74
74
  theme,
75
75
  logo,
76
- favicon: raw.favicon,
76
+ favicon: raw.favicon && !raw.favicon.startsWith("http") && !raw.favicon.startsWith("data:") ? resolve(configDir, raw.favicon) : raw.favicon,
77
77
  repo: raw.repo,
78
78
  editBranch: raw.editBranch,
79
79
  editBasePath: raw.editBasePath,
@@ -5,5 +5,6 @@ export interface DoxygenResult {
5
5
  pages: Map<string, MarkdownPage>;
6
6
  navTab: SiteTab;
7
7
  }
8
+ export declare function normalizeDoxygenDescription(description: string, markdown: string): string;
8
9
  export declare function loadDoxygenTab(config: ResolvedDoxygenConfig, tabSlug: string, tabLabel: string): Promise<DoxygenResult>;
9
10
  //# 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,wBAAsB,cAAc,CAClC,MAAM,EAAE,qBAAqB,EAC7B,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,aAAa,CAAC,CA4FxB"}
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,5 +1,13 @@
1
1
  import { generate } from "moxygen";
2
- import { renderMarkdown, extractHeadings } from "../utils/markdown.js";
2
+ import { renderMarkdown, extractHeadings, extractFirstParagraph, stripMarkdownLinks } from "../utils/markdown.js";
3
+ export function normalizeDoxygenDescription(description, markdown) {
4
+ if (!description)
5
+ return "";
6
+ if (!description.includes("{#ref "))
7
+ return description;
8
+ const firstParagraph = extractFirstParagraph(markdown);
9
+ return firstParagraph || description;
10
+ }
3
11
  export async function loadDoxygenTab(config, tabSlug, tabLabel) {
4
12
  const generated = await generate({
5
13
  directory: config.xml,
@@ -11,11 +19,12 @@ export async function loadDoxygenTab(config, tabSlug, tabLabel) {
11
19
  for (const page of generated) {
12
20
  if (!page.markdown.trim())
13
21
  continue;
22
+ const description = normalizeDoxygenDescription(page.description, page.markdown);
14
23
  const html = renderMarkdown(page.markdown);
15
24
  const headings = extractHeadings(page.markdown);
16
25
  pages.set(page.slug, {
17
26
  title: page.title,
18
- description: page.description,
27
+ description,
19
28
  slug: page.slug,
20
29
  html,
21
30
  headings,
@@ -130,7 +139,7 @@ function buildRichIndex(groupMap, pages) {
130
139
  continue;
131
140
  const typeCount = items.filter((i) => i.kind !== "group" && i.kind !== "namespace").length;
132
141
  const href = `${groupEntry.slug}.html`;
133
- const desc = page.description || "";
142
+ const desc = stripMarkdownLinks(page.description || "");
134
143
  const meta = typeCount > 0
135
144
  ? `<p style="margin:0.5rem 0 0;font-size:0.8rem;opacity:0.5">${typeCount} type${typeCount !== 1 ? "s" : ""}</p>`
136
145
  : "";
@@ -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;AA4TxD;;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,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;AAwXxD;;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"}
@@ -56,6 +56,45 @@ function preprocessComponents(body) {
56
56
  html = html.replace(/<Accordion\s+title="([^"]*)">\s*([\s\S]*?)\s*<\/Accordion>/g, (_m, title, content) => {
57
57
  return `:::accordion{title="${title}"}\n${content.trim()}\n:::`;
58
58
  });
59
+ // <Tabs> <Tab title="...">content</Tab> ... </Tabs> → :::tabs with ::tab children
60
+ html = html.replace(/<Tabs>\s*([\s\S]*?)\s*<\/Tabs>/g, (_m, inner) => {
61
+ const tabs = [];
62
+ inner.replace(/\s*<Tab\s+title="([^"]*)">\s*([\s\S]*?)\s*<\/Tab>/g, (_tm, title, content) => {
63
+ tabs.push(`::tab{title="${title}"}\n${content.trim()}\n::`);
64
+ return "";
65
+ });
66
+ return `:::tabs\n${tabs.join("\n")}\n:::`;
67
+ });
68
+ // <CodeGroup> with titled fenced code blocks → :::code-group
69
+ html = html.replace(/<CodeGroup>\s*([\s\S]*?)\s*<\/CodeGroup>/g, (_m, inner) => `:::code-group\n${inner.trim()}\n:::`);
70
+ // <Note>, <Warning>, <Tip>, <Info> → :::callout directives
71
+ for (const type of ["note", "warning", "tip", "info"]) {
72
+ const tag = type.charAt(0).toUpperCase() + type.slice(1);
73
+ html = html.replace(new RegExp(`<${tag}(?:\\s+title="([^"]*)")?\\s*>\\s*([\\s\\S]*?)\\s*<\\/${tag}>`, "g"), (_m, title, content) => {
74
+ const titleSuffix = title ? ` ${title}` : "";
75
+ return `:::${type}${titleSuffix}\n${content.trim()}\n:::`;
76
+ });
77
+ }
78
+ // <Video src="..." title="..." /> → ::video[url]{title="..."}
79
+ html = html.replace(/<Video\s+([^>]*?)\s*\/?\s*>/g, (_m, attrs) => {
80
+ const src = attrs.match(/src="([^"]*)"/)?.[1] ?? "";
81
+ const title = attrs.match(/title="([^"]*)"/)?.[1];
82
+ const titleAttr = title ? `{title="${title}"}` : "";
83
+ return `::video[${src}]${titleAttr}`;
84
+ });
85
+ // <Iframe src="..." title="..." height="..." /> → ::iframe[url]{attrs}
86
+ html = html.replace(/<Iframe\s+([^>]*?)\s*\/?\s*>/g, (_m, attrs) => {
87
+ const src = attrs.match(/src="([^"]*)"/)?.[1] ?? "";
88
+ const title = attrs.match(/title="([^"]*)"/)?.[1];
89
+ const height = attrs.match(/height="([^"]*)"/)?.[1];
90
+ const parts = [];
91
+ if (title)
92
+ parts.push(`title="${title}"`);
93
+ if (height)
94
+ parts.push(`height="${height}"`);
95
+ const attrStr = parts.length ? `{${parts.join(" ")}}` : "";
96
+ return `::iframe[${src}]${attrStr}`;
97
+ });
59
98
  return html;
60
99
  }
61
100
  // ---------------------------------------------------------------------------
@@ -439,7 +439,7 @@ async function buildSiteConfig(config) {
439
439
  name: config.name,
440
440
  theme: config.theme,
441
441
  logo: logo?.light ? logo : undefined,
442
- favicon: config.favicon,
442
+ favicon: config.favicon ? await resolveAssetUrl(config.favicon) : undefined,
443
443
  repo: config.repo,
444
444
  editBranch: config.editBranch,
445
445
  editBasePath: config.editBasePath,
package/dist/index.js CHANGED
@@ -158,7 +158,7 @@ async function buildSiteConfig(config) {
158
158
  name: config.name,
159
159
  theme: config.theme,
160
160
  logo: logo?.light ? logo : undefined,
161
- favicon: config.favicon,
161
+ favicon: config.favicon ? await resolveAssetUrl(config.favicon) : undefined,
162
162
  repo: config.repo,
163
163
  editBranch: config.editBranch,
164
164
  editBasePath: config.editBasePath,
package/dist/init.js CHANGED
@@ -243,7 +243,7 @@ import { myFunction } from "my-package";
243
243
  build: "sourcey build",
244
244
  },
245
245
  dependencies: {
246
- sourcey: "^3.3.5",
246
+ sourcey: "^3.4.3",
247
247
  },
248
248
  }, null, 2);
249
249
  writeFileSync(resolve(targetDir, "package.json"), pkg + "\n");
@@ -23,6 +23,7 @@
23
23
  --color-primary: 99 102 241;
24
24
  --color-primary-light: 129 140 248;
25
25
  --color-primary-dark: 79 70 229;
26
+ --color-primary-ink: 79 70 229;
26
27
 
27
28
  /* Backgrounds */
28
29
  --color-background-light: 255 255 255;
@@ -70,7 +71,6 @@
70
71
  --method-prompt: #2563eb;
71
72
 
72
73
  /* Typography */
73
- --font-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
74
- --font-mono: 'Geist Mono', 'SF Mono', 'Fira Code', 'Cascadia Code', Consolas, monospace;
74
+ --font-sans: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
75
+ --font-mono: ui-monospace, 'SF Mono', 'Cascadia Code', Consolas, 'Liberation Mono', Menlo, monospace;
75
76
  }
76
-
@@ -9,15 +9,19 @@
9
9
 
10
10
  /* ── Page Description (display font) ─────────────────────────────── */
11
11
 
12
- @import url('https://fonts.googleapis.com/css2?family=Playfair+Display:ital@0;1&display=swap');
13
-
14
12
  #sourcey .page-description {
15
- font-family: 'Playfair Display', Georgia, serif;
16
- font-size: 1.375rem;
17
- line-height: 1.4;
13
+ font-family: ui-serif, Georgia, Cambria, "Times New Roman", serif;
14
+ font-size: 1.125rem;
15
+ line-height: 1.35;
18
16
  font-style: italic;
19
17
  color: rgb(var(--color-gray-600));
20
18
  }
19
+ @media (min-width: 1024px) {
20
+ #sourcey .page-description {
21
+ font-size: 1.375rem;
22
+ line-height: 1.4;
23
+ }
24
+ }
21
25
  .dark #sourcey .page-description {
22
26
  color: rgb(var(--color-gray-400));
23
27
  }
@@ -245,7 +249,7 @@ h1[id], h2[id], h3[id], h4[id], h5[id], h6[id] {
245
249
  background: rgb(var(--color-gray-800) / 0.4);
246
250
  }
247
251
  #sourcey .nav-link.active {
248
- color: rgb(var(--color-primary));
252
+ color: rgb(var(--color-primary-ink));
249
253
  background: rgb(var(--color-primary) / 0.08);
250
254
  font-weight: 500;
251
255
  }
@@ -261,12 +265,15 @@ h1[id], h2[id], h3[id], h4[id], h5[id], h6[id] {
261
265
  padding-left: 0.75rem;
262
266
  transition: color 0.15s, border-color 0.15s;
263
267
  }
268
+ #sourcey #toc ul ul .toc-item {
269
+ margin-left: 0.75rem;
270
+ }
264
271
  .dark #sourcey #toc .toc-item {
265
272
  border-left-color: rgb(var(--color-gray-700));
266
273
  }
267
274
  #sourcey #toc .toc-item.active {
268
- color: rgb(var(--color-primary));
269
- border-left-color: rgb(var(--color-primary));
275
+ color: rgb(var(--color-primary-ink));
276
+ border-left-color: rgb(var(--color-primary-ink));
270
277
  }
271
278
  .dark #sourcey #toc .toc-item.active {
272
279
  color: rgb(var(--color-primary-light));
@@ -310,7 +317,7 @@ h1[id], h2[id], h3[id], h4[id], h5[id], h6[id] {
310
317
  }
311
318
 
312
319
  #sourcey .response-tab.active {
313
- color: rgb(var(--color-primary));
320
+ color: rgb(var(--color-primary-ink));
314
321
  }
315
322
  .dark #sourcey .response-tab.active {
316
323
  color: rgb(var(--color-primary-light));
@@ -511,7 +518,7 @@ h1[id], h2[id], h3[id], h4[id], h5[id], h6[id] {
511
518
  font-family: var(--font-mono);
512
519
  font-size: 0.875rem;
513
520
  font-weight: 600;
514
- color: rgb(var(--color-primary));
521
+ color: rgb(var(--color-primary-ink));
515
522
  background: transparent;
516
523
  border: none;
517
524
  padding: 0;
@@ -793,16 +800,17 @@ h1[id], h2[id], h3[id], h4[id], h5[id], h6[id] {
793
800
 
794
801
  #sourcey .callout {
795
802
  margin: 1.25rem 0;
796
- border-radius: var(--radius);
797
- border: 1px solid rgb(var(--color-gray-200) / 0.7);
798
- border-left-width: 3px;
803
+ border: none;
804
+ border-left: 1px solid;
805
+ border-radius: 0;
799
806
  padding: 0.875rem 1rem;
800
807
  font-size: 0.875rem;
801
808
  line-height: 1.6;
802
809
  color: rgb(var(--color-gray-700));
810
+ border-left-color: rgb(var(--color-gray-300));
803
811
  }
804
812
  .dark #sourcey .callout {
805
- border-color: rgb(var(--color-gray-800) / 0.5);
813
+ border-left-color: rgb(var(--color-gray-700));
806
814
  color: rgb(var(--color-gray-400));
807
815
  }
808
816
 
@@ -831,50 +839,26 @@ h1[id], h2[id], h3[id], h4[id], h5[id], h6[id] {
831
839
  }
832
840
 
833
841
  /* Note — blue */
834
- #sourcey .callout-note {
835
- border-left-color: #3b82f6;
836
- background: rgb(59 130 246 / 0.04);
837
- }
838
- .dark #sourcey .callout-note {
839
- border-left-color: #60a5fa;
840
- background: rgb(59 130 246 / 0.06);
841
- }
842
+ #sourcey .callout-note { border-left-color: #3b82f6; }
843
+ .dark #sourcey .callout-note { border-left-color: #60a5fa; }
842
844
  #sourcey .callout-note .callout-title { color: #3b82f6; }
843
845
  .dark #sourcey .callout-note .callout-title { color: #60a5fa; }
844
846
 
845
847
  /* Warning — amber */
846
- #sourcey .callout-warning {
847
- border-left-color: #f59e0b;
848
- background: rgb(245 158 11 / 0.04);
849
- }
850
- .dark #sourcey .callout-warning {
851
- border-left-color: #fbbf24;
852
- background: rgb(245 158 11 / 0.06);
853
- }
848
+ #sourcey .callout-warning { border-left-color: #f59e0b; }
849
+ .dark #sourcey .callout-warning { border-left-color: #fbbf24; }
854
850
  #sourcey .callout-warning .callout-title { color: #f59e0b; }
855
851
  .dark #sourcey .callout-warning .callout-title { color: #fbbf24; }
856
852
 
857
853
  /* Tip — green */
858
- #sourcey .callout-tip {
859
- border-left-color: #22c55e;
860
- background: rgb(34 197 94 / 0.04);
861
- }
862
- .dark #sourcey .callout-tip {
863
- border-left-color: #4ade80;
864
- background: rgb(34 197 94 / 0.06);
865
- }
854
+ #sourcey .callout-tip { border-left-color: #22c55e; }
855
+ .dark #sourcey .callout-tip { border-left-color: #4ade80; }
866
856
  #sourcey .callout-tip .callout-title { color: #22c55e; }
867
857
  .dark #sourcey .callout-tip .callout-title { color: #4ade80; }
868
858
 
869
859
  /* Info — violet */
870
- #sourcey .callout-info {
871
- border-left-color: #8b5cf6;
872
- background: rgb(139 92 246 / 0.04);
873
- }
874
- .dark #sourcey .callout-info {
875
- border-left-color: #a78bfa;
876
- background: rgb(139 92 246 / 0.06);
877
- }
860
+ #sourcey .callout-info { border-left-color: #8b5cf6; }
861
+ .dark #sourcey .callout-info { border-left-color: #a78bfa; }
878
862
  #sourcey .callout-info .callout-title { color: #8b5cf6; }
879
863
  .dark #sourcey .callout-info .callout-title { color: #a78bfa; }
880
864
 
@@ -921,7 +905,7 @@ h1[id], h2[id], h3[id], h4[id], h5[id], h6[id] {
921
905
  }
922
906
 
923
907
  #sourcey .directive-tab.active {
924
- color: rgb(var(--color-primary));
908
+ color: rgb(var(--color-primary-ink));
925
909
  }
926
910
  .dark #sourcey .directive-tab.active {
927
911
  color: rgb(var(--color-primary-light));
@@ -1097,7 +1081,7 @@ h1[id], h2[id], h3[id], h4[id], h5[id], h6[id] {
1097
1081
  background: rgb(var(--color-gray-800));
1098
1082
  }
1099
1083
  .drawer-dropdown-item.active {
1100
- color: rgb(var(--color-primary));
1084
+ color: rgb(var(--color-primary-ink));
1101
1085
  font-weight: 500;
1102
1086
  }
1103
1087
  .dark .drawer-dropdown-item.active {
@@ -14,6 +14,16 @@ export interface PageHeading {
14
14
  * No rendering needed; pure token walk.
15
15
  */
16
16
  export declare function extractHeadings(input: string): PageHeading[];
17
+ /**
18
+ * Extract the first paragraph token from markdown.
19
+ * Useful for generated docs where a summary paragraph is embedded in the body.
20
+ */
21
+ export declare function extractFirstParagraph(input?: string): string;
22
+ /**
23
+ * Replace markdown links with their visible labels.
24
+ * Useful when rendering inside an existing clickable container.
25
+ */
26
+ export declare function stripMarkdownLinks(input?: string): string;
17
27
  /**
18
28
  * Render Markdown to HTML.
19
29
  */
@@ -1 +1 @@
1
- {"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/utils/markdown.ts"],"names":[],"mappings":"AAKA;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CASnE;AAED,4CAA4C;AAC5C,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,CAAC,GAAG,CAAC,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;CACZ;AAgJD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,EAAE,CAe5D;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAGrD;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAG3D"}
1
+ {"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/utils/markdown.ts"],"names":[],"mappings":"AAKA;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CASnE;AAED,4CAA4C;AAC5C,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,CAAC,GAAG,CAAC,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;CACZ;AAgJD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,EAAE,CAe5D;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAY5D;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAGzD;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAGrD;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAG3D"}
@@ -157,6 +157,35 @@ export function extractHeadings(input) {
157
157
  }
158
158
  return headings;
159
159
  }
160
+ /**
161
+ * Extract the first paragraph token from markdown.
162
+ * Useful for generated docs where a summary paragraph is embedded in the body.
163
+ */
164
+ export function extractFirstParagraph(input) {
165
+ if (!input)
166
+ return "";
167
+ const tokens = marked.lexer(input);
168
+ for (const token of tokens) {
169
+ if (token.type === "paragraph") {
170
+ const raw = token.raw.trim();
171
+ if (!raw)
172
+ continue;
173
+ if (!raw.replace(/<[^>]+>/g, "").trim())
174
+ continue;
175
+ return raw;
176
+ }
177
+ }
178
+ return "";
179
+ }
180
+ /**
181
+ * Replace markdown links with their visible labels.
182
+ * Useful when rendering inside an existing clickable container.
183
+ */
184
+ export function stripMarkdownLinks(input) {
185
+ if (!input)
186
+ return "";
187
+ return input.replace(/\[([^\]]+)\]\(([^)]+)\)/g, "$1");
188
+ }
160
189
  /**
161
190
  * Render Markdown to HTML.
162
191
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sourcey",
3
- "version": "3.4.1",
3
+ "version": "3.4.3",
4
4
  "description": "Open source documentation platform. API references, guides, static output.",
5
5
  "type": "module",
6
6
  "engines": {