svedocs 0.1.0-beta.10
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/LICENSE +5 -0
- package/README.md +85 -0
- package/dist/ai/openai-compatible.d.ts +13 -0
- package/dist/ai/openai-compatible.d.ts.map +1 -0
- package/dist/ai/openai-compatible.js +92 -0
- package/dist/ai/providers.d.ts +20 -0
- package/dist/ai/providers.d.ts.map +1 -0
- package/dist/ai/providers.js +185 -0
- package/dist/ai/rate-limit.d.ts +18 -0
- package/dist/ai/rate-limit.d.ts.map +1 -0
- package/dist/ai/rate-limit.js +52 -0
- package/dist/ai/response.d.ts +4 -0
- package/dist/ai/response.d.ts.map +1 -0
- package/dist/ai/response.js +151 -0
- package/dist/ai/runtime.d.ts +32 -0
- package/dist/ai/runtime.d.ts.map +1 -0
- package/dist/ai/runtime.js +111 -0
- package/dist/ai/types.d.ts +93 -0
- package/dist/ai/types.d.ts.map +1 -0
- package/dist/ai/types.js +1 -0
- package/dist/ai.d.ts +7 -0
- package/dist/ai.d.ts.map +1 -0
- package/dist/ai.js +6 -0
- package/dist/ambient.d.ts +5 -0
- package/dist/cloudflare.d.ts +29 -0
- package/dist/cloudflare.d.ts.map +1 -0
- package/dist/cloudflare.js +149 -0
- package/dist/config.d.ts +373 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +299 -0
- package/dist/core/checks.d.ts +4 -0
- package/dist/core/checks.d.ts.map +1 -0
- package/dist/core/checks.js +267 -0
- package/dist/core/config.d.ts +6 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +178 -0
- package/dist/core/content.d.ts +7 -0
- package/dist/core/content.d.ts.map +1 -0
- package/dist/core/content.js +340 -0
- package/dist/core/i18n.d.ts +5 -0
- package/dist/core/i18n.d.ts.map +1 -0
- package/dist/core/i18n.js +117 -0
- package/dist/core/links.d.ts +5 -0
- package/dist/core/links.d.ts.map +1 -0
- package/dist/core/links.js +60 -0
- package/dist/core/messages.d.ts +149 -0
- package/dist/core/messages.d.ts.map +1 -0
- package/dist/core/messages.js +163 -0
- package/dist/core/navigation.d.ts +5 -0
- package/dist/core/navigation.d.ts.map +1 -0
- package/dist/core/navigation.js +144 -0
- package/dist/core/routes.d.ts +36 -0
- package/dist/core/routes.d.ts.map +1 -0
- package/dist/core/routes.js +152 -0
- package/dist/core/search.d.ts +5 -0
- package/dist/core/search.d.ts.map +1 -0
- package/dist/core/search.js +41 -0
- package/dist/core/types.d.ts +468 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +4 -0
- package/dist/core/utils.d.ts +13 -0
- package/dist/core/utils.d.ts.map +1 -0
- package/dist/core/utils.js +60 -0
- package/dist/core.d.ts +9 -0
- package/dist/core.d.ts.map +1 -0
- package/dist/core.js +8 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/mdx/ast.d.ts +32 -0
- package/dist/mdx/ast.d.ts.map +1 -0
- package/dist/mdx/ast.js +148 -0
- package/dist/mdx/code.d.ts +17 -0
- package/dist/mdx/code.d.ts.map +1 -0
- package/dist/mdx/code.js +327 -0
- package/dist/mdx/compile.d.ts +29 -0
- package/dist/mdx/compile.d.ts.map +1 -0
- package/dist/mdx/compile.js +59 -0
- package/dist/mdx/diff.d.ts +9 -0
- package/dist/mdx/diff.d.ts.map +1 -0
- package/dist/mdx/diff.js +171 -0
- package/dist/mdx/headings.d.ts +4 -0
- package/dist/mdx/headings.d.ts.map +1 -0
- package/dist/mdx/headings.js +42 -0
- package/dist/mdx/links.d.ts +4 -0
- package/dist/mdx/links.d.ts.map +1 -0
- package/dist/mdx/links.js +144 -0
- package/dist/mdx/utils.d.ts +10 -0
- package/dist/mdx/utils.d.ts.map +1 -0
- package/dist/mdx/utils.js +64 -0
- package/dist/og/image.d.ts +25 -0
- package/dist/og/image.d.ts.map +1 -0
- package/dist/og/image.js +224 -0
- package/dist/og/metadata.d.ts +7 -0
- package/dist/og/metadata.d.ts.map +1 -0
- package/dist/og/metadata.js +198 -0
- package/dist/og/response.d.ts +4 -0
- package/dist/og/response.d.ts.map +1 -0
- package/dist/og/response.js +49 -0
- package/dist/og/rss.d.ts +4 -0
- package/dist/og/rss.d.ts.map +1 -0
- package/dist/og/rss.js +96 -0
- package/dist/og/sitemap.d.ts +7 -0
- package/dist/og/sitemap.d.ts.map +1 -0
- package/dist/og/sitemap.js +90 -0
- package/dist/og/types.d.ts +65 -0
- package/dist/og/types.d.ts.map +1 -0
- package/dist/og/types.js +1 -0
- package/dist/og.d.ts +6 -0
- package/dist/og.d.ts.map +1 -0
- package/dist/og.js +5 -0
- package/dist/routes.d.ts +2 -0
- package/dist/routes.d.ts.map +1 -0
- package/dist/routes.js +1 -0
- package/dist/search/algolia.d.ts +10 -0
- package/dist/search/algolia.d.ts.map +1 -0
- package/dist/search/algolia.js +82 -0
- package/dist/search/cloudflare-sync.d.ts +5 -0
- package/dist/search/cloudflare-sync.d.ts.map +1 -0
- package/dist/search/cloudflare-sync.js +169 -0
- package/dist/search/cloudflare.d.ts +11 -0
- package/dist/search/cloudflare.d.ts.map +1 -0
- package/dist/search/cloudflare.js +126 -0
- package/dist/search/local.d.ts +9 -0
- package/dist/search/local.d.ts.map +1 -0
- package/dist/search/local.js +165 -0
- package/dist/search/runtime.d.ts +41 -0
- package/dist/search/runtime.d.ts.map +1 -0
- package/dist/search/runtime.js +152 -0
- package/dist/search/types.d.ts +172 -0
- package/dist/search/types.d.ts.map +1 -0
- package/dist/search/types.js +1 -0
- package/dist/search/typesense.d.ts +11 -0
- package/dist/search/typesense.d.ts.map +1 -0
- package/dist/search/typesense.js +91 -0
- package/dist/search/utils.d.ts +11 -0
- package/dist/search/utils.d.ts.map +1 -0
- package/dist/search/utils.js +93 -0
- package/dist/search.d.ts +8 -0
- package/dist/search.d.ts.map +1 -0
- package/dist/search.js +7 -0
- package/dist/svelte.d.ts +27 -0
- package/dist/svelte.d.ts.map +1 -0
- package/dist/svelte.js +45 -0
- package/dist/testing.d.ts +3 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +23 -0
- package/dist/theme/Article.svelte +145 -0
- package/dist/theme/Article.svelte.d.ts +36 -0
- package/dist/theme/Article.svelte.d.ts.map +1 -0
- package/dist/theme/AskAiPanel.svelte +241 -0
- package/dist/theme/AskAiPanel.svelte.d.ts +31 -0
- package/dist/theme/AskAiPanel.svelte.d.ts.map +1 -0
- package/dist/theme/Brand.svelte +19 -0
- package/dist/theme/Brand.svelte.d.ts +22 -0
- package/dist/theme/Brand.svelte.d.ts.map +1 -0
- package/dist/theme/Button.svelte +34 -0
- package/dist/theme/Button.svelte.d.ts +41 -0
- package/dist/theme/Button.svelte.d.ts.map +1 -0
- package/dist/theme/Checkbox.svelte +63 -0
- package/dist/theme/Checkbox.svelte.d.ts +45 -0
- package/dist/theme/Checkbox.svelte.d.ts.map +1 -0
- package/dist/theme/CodeBlock.svelte +6 -0
- package/dist/theme/CodeBlock.svelte.d.ts +22 -0
- package/dist/theme/CodeBlock.svelte.d.ts.map +1 -0
- package/dist/theme/DocPage.svelte +15 -0
- package/dist/theme/DocPage.svelte.d.ts +33 -0
- package/dist/theme/DocPage.svelte.d.ts.map +1 -0
- package/dist/theme/DocsApp.svelte +194 -0
- package/dist/theme/DocsApp.svelte.d.ts +60 -0
- package/dist/theme/DocsApp.svelte.d.ts.map +1 -0
- package/dist/theme/DocsLayout.svelte +99 -0
- package/dist/theme/DocsLayout.svelte.d.ts +39 -0
- package/dist/theme/DocsLayout.svelte.d.ts.map +1 -0
- package/dist/theme/DocsShell.svelte +91 -0
- package/dist/theme/DocsShell.svelte.d.ts +34 -0
- package/dist/theme/DocsShell.svelte.d.ts.map +1 -0
- package/dist/theme/ErrorPage.svelte +113 -0
- package/dist/theme/ErrorPage.svelte.d.ts +34 -0
- package/dist/theme/ErrorPage.svelte.d.ts.map +1 -0
- package/dist/theme/FloatingToolbar.svelte +8 -0
- package/dist/theme/FloatingToolbar.svelte.d.ts +22 -0
- package/dist/theme/FloatingToolbar.svelte.d.ts.map +1 -0
- package/dist/theme/Footer.svelte +18 -0
- package/dist/theme/Footer.svelte.d.ts +24 -0
- package/dist/theme/Footer.svelte.d.ts.map +1 -0
- package/dist/theme/FooterLinks.svelte +37 -0
- package/dist/theme/FooterLinks.svelte.d.ts +22 -0
- package/dist/theme/FooterLinks.svelte.d.ts.map +1 -0
- package/dist/theme/FormField.svelte +41 -0
- package/dist/theme/FormField.svelte.d.ts +35 -0
- package/dist/theme/FormField.svelte.d.ts.map +1 -0
- package/dist/theme/HomePage.svelte +284 -0
- package/dist/theme/HomePage.svelte.d.ts +65 -0
- package/dist/theme/HomePage.svelte.d.ts.map +1 -0
- package/dist/theme/Input.svelte +36 -0
- package/dist/theme/Input.svelte.d.ts +34 -0
- package/dist/theme/Input.svelte.d.ts.map +1 -0
- package/dist/theme/LayoutShell.svelte +120 -0
- package/dist/theme/LayoutShell.svelte.d.ts +43 -0
- package/dist/theme/LayoutShell.svelte.d.ts.map +1 -0
- package/dist/theme/LocalizedLink.svelte +21 -0
- package/dist/theme/LocalizedLink.svelte.d.ts +38 -0
- package/dist/theme/LocalizedLink.svelte.d.ts.map +1 -0
- package/dist/theme/MobileNav.svelte +20 -0
- package/dist/theme/MobileNav.svelte.d.ts +26 -0
- package/dist/theme/MobileNav.svelte.d.ts.map +1 -0
- package/dist/theme/Navbar.svelte +69 -0
- package/dist/theme/Navbar.svelte.d.ts +29 -0
- package/dist/theme/Navbar.svelte.d.ts.map +1 -0
- package/dist/theme/PageLayout.svelte +49 -0
- package/dist/theme/PageLayout.svelte.d.ts +34 -0
- package/dist/theme/PageLayout.svelte.d.ts.map +1 -0
- package/dist/theme/PageShell.svelte +98 -0
- package/dist/theme/PageShell.svelte.d.ts +35 -0
- package/dist/theme/PageShell.svelte.d.ts.map +1 -0
- package/dist/theme/PageTools.svelte +87 -0
- package/dist/theme/PageTools.svelte.d.ts +25 -0
- package/dist/theme/PageTools.svelte.d.ts.map +1 -0
- package/dist/theme/RenderError.svelte +62 -0
- package/dist/theme/RenderError.svelte.d.ts +31 -0
- package/dist/theme/RenderError.svelte.d.ts.map +1 -0
- package/dist/theme/RootLayout.svelte +274 -0
- package/dist/theme/RootLayout.svelte.d.ts +47 -0
- package/dist/theme/RootLayout.svelte.d.ts.map +1 -0
- package/dist/theme/RouteRenderError.svelte +53 -0
- package/dist/theme/RouteRenderError.svelte.d.ts +34 -0
- package/dist/theme/RouteRenderError.svelte.d.ts.map +1 -0
- package/dist/theme/SafeRenderError.svelte +49 -0
- package/dist/theme/SafeRenderError.svelte.d.ts +33 -0
- package/dist/theme/SafeRenderError.svelte.d.ts.map +1 -0
- package/dist/theme/ScopeSwitcher.svelte +107 -0
- package/dist/theme/ScopeSwitcher.svelte.d.ts +26 -0
- package/dist/theme/ScopeSwitcher.svelte.d.ts.map +1 -0
- package/dist/theme/SearchDialog.svelte +200 -0
- package/dist/theme/SearchDialog.svelte.d.ts +31 -0
- package/dist/theme/SearchDialog.svelte.d.ts.map +1 -0
- package/dist/theme/Select.svelte +37 -0
- package/dist/theme/Select.svelte.d.ts +42 -0
- package/dist/theme/Select.svelte.d.ts.map +1 -0
- package/dist/theme/SidebarTree.svelte +148 -0
- package/dist/theme/SidebarTree.svelte.d.ts +24 -0
- package/dist/theme/SidebarTree.svelte.d.ts.map +1 -0
- package/dist/theme/SocialNav.svelte +17 -0
- package/dist/theme/SocialNav.svelte.d.ts +22 -0
- package/dist/theme/SocialNav.svelte.d.ts.map +1 -0
- package/dist/theme/TableOfContents.svelte +73 -0
- package/dist/theme/TableOfContents.svelte.d.ts +25 -0
- package/dist/theme/TableOfContents.svelte.d.ts.map +1 -0
- package/dist/theme/Textarea.svelte +33 -0
- package/dist/theme/Textarea.svelte.d.ts +33 -0
- package/dist/theme/Textarea.svelte.d.ts.map +1 -0
- package/dist/theme/ThemeInit.svelte +16 -0
- package/dist/theme/ThemeInit.svelte.d.ts +23 -0
- package/dist/theme/ThemeInit.svelte.d.ts.map +1 -0
- package/dist/theme/ThemeToggle.svelte +37 -0
- package/dist/theme/ThemeToggle.svelte.d.ts +23 -0
- package/dist/theme/ThemeToggle.svelte.d.ts.map +1 -0
- package/dist/theme/TopNav.svelte +23 -0
- package/dist/theme/TopNav.svelte.d.ts +22 -0
- package/dist/theme/TopNav.svelte.d.ts.map +1 -0
- package/dist/theme/base.css +240 -0
- package/dist/theme/defaults.d.ts +4 -0
- package/dist/theme/defaults.d.ts.map +1 -0
- package/dist/theme/defaults.js +55 -0
- package/dist/theme/forms.d.ts +4 -0
- package/dist/theme/forms.d.ts.map +1 -0
- package/dist/theme/forms.js +3 -0
- package/dist/theme/headless.d.ts +62 -0
- package/dist/theme/headless.d.ts.map +1 -0
- package/dist/theme/headless.js +1064 -0
- package/dist/theme/index.d.ts +41 -0
- package/dist/theme/index.d.ts.map +1 -0
- package/dist/theme/index.js +38 -0
- package/dist/theme/portal.d.ts +6 -0
- package/dist/theme/portal.d.ts.map +1 -0
- package/dist/theme/portal.js +59 -0
- package/dist/theme/styles.css +4232 -0
- package/dist/theme/types.d.ts +363 -0
- package/dist/theme/types.d.ts.map +1 -0
- package/dist/theme/types.js +1 -0
- package/dist/virtual.d.ts +65 -0
- package/dist/vite.d.ts +16 -0
- package/dist/vite.d.ts.map +1 -0
- package/dist/vite.js +386 -0
- package/package.json +132 -0
package/dist/mdx/ast.js
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import GithubSlugger from 'github-slugger';
|
|
2
|
+
import remarkGfm from 'remark-gfm';
|
|
3
|
+
import remarkMath from 'remark-math';
|
|
4
|
+
import remarkParse from 'remark-parse';
|
|
5
|
+
import { unified } from 'unified';
|
|
6
|
+
import { visit } from 'unist-util-visit';
|
|
7
|
+
import { stripHtml } from '../core/utils.js';
|
|
8
|
+
export function parseMarkdownAst(markdown) {
|
|
9
|
+
return unified()
|
|
10
|
+
.use(remarkParse)
|
|
11
|
+
.use(remarkGfm)
|
|
12
|
+
.use(remarkMath)
|
|
13
|
+
.parse(markdown);
|
|
14
|
+
}
|
|
15
|
+
export function extractMarkdownOutline(markdown) {
|
|
16
|
+
const tree = parseMarkdownAst(markdown);
|
|
17
|
+
const slugger = new GithubSlugger();
|
|
18
|
+
const headings = [];
|
|
19
|
+
let title;
|
|
20
|
+
visit(tree, 'heading', (node) => {
|
|
21
|
+
const depth = node.depth ?? 0;
|
|
22
|
+
const text = nodeToText(node).trim();
|
|
23
|
+
if (!text)
|
|
24
|
+
return;
|
|
25
|
+
const id = slugger.slug(text);
|
|
26
|
+
if (depth === 1 && !title)
|
|
27
|
+
title = text;
|
|
28
|
+
if (depth >= 2 && depth <= 4) {
|
|
29
|
+
headings.push({ id, depth: depth, text });
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
return { ...(title ? { title } : {}), headings };
|
|
33
|
+
}
|
|
34
|
+
export function markdownAstToPlainText(markdown) {
|
|
35
|
+
return nodeToText(parseMarkdownAst(markdown)).replace(/\s+/g, ' ').trim();
|
|
36
|
+
}
|
|
37
|
+
export function extractMarkdownSections(markdown) {
|
|
38
|
+
const tree = parseMarkdownAst(markdown);
|
|
39
|
+
const slugger = new GithubSlugger();
|
|
40
|
+
const sections = [];
|
|
41
|
+
let current;
|
|
42
|
+
function flush() {
|
|
43
|
+
if (!current)
|
|
44
|
+
return;
|
|
45
|
+
const content = current.nodes.map(nodeToText).join(' ').replace(/\s+/g, ' ').trim();
|
|
46
|
+
if (content.length >= 8) {
|
|
47
|
+
sections.push({
|
|
48
|
+
id: current.id,
|
|
49
|
+
depth: current.depth,
|
|
50
|
+
title: current.title,
|
|
51
|
+
content
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
current = undefined;
|
|
55
|
+
}
|
|
56
|
+
for (const node of tree.children ?? []) {
|
|
57
|
+
if (node.type === 'heading' && typeof node.depth === 'number') {
|
|
58
|
+
const text = nodeToText(node).trim();
|
|
59
|
+
if (text) {
|
|
60
|
+
const id = slugger.slug(text);
|
|
61
|
+
if (node.depth >= 2 && node.depth <= 4) {
|
|
62
|
+
flush();
|
|
63
|
+
current = { id, depth: node.depth, title: text, nodes: [] };
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
current?.nodes.push(node);
|
|
69
|
+
}
|
|
70
|
+
flush();
|
|
71
|
+
return sections;
|
|
72
|
+
}
|
|
73
|
+
export function extractMarkdownLinksFromAst(markdown) {
|
|
74
|
+
const tree = parseMarkdownAst(markdown);
|
|
75
|
+
const definitions = new Map();
|
|
76
|
+
const links = [];
|
|
77
|
+
visit(tree, 'definition', (node) => {
|
|
78
|
+
if (node.identifier && node.url)
|
|
79
|
+
definitions.set(node.identifier.toLowerCase(), node.url);
|
|
80
|
+
});
|
|
81
|
+
visit(tree, (node) => {
|
|
82
|
+
if (node.type === 'link' && node.url) {
|
|
83
|
+
links.push(createLinkReference(node.url, nodeToText(node), 'link', node));
|
|
84
|
+
}
|
|
85
|
+
if (node.type === 'image' && node.url) {
|
|
86
|
+
links.push(createLinkReference(node.url, node.alt ?? node.url, 'image', node));
|
|
87
|
+
}
|
|
88
|
+
if ((node.type === 'linkReference' || node.type === 'imageReference') && node.identifier) {
|
|
89
|
+
const href = definitions.get(node.identifier.toLowerCase());
|
|
90
|
+
if (href) {
|
|
91
|
+
links.push(createLinkReference(href, nodeToText(node) || node.label || href, node.type === 'imageReference' ? 'image' : 'link', node));
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
if (node.type === 'html' && node.value) {
|
|
95
|
+
links.push(...extractHtmlLinks(node.value, node.position?.start?.line ?? 1));
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
return links;
|
|
99
|
+
}
|
|
100
|
+
function createLinkReference(href, text, source, node) {
|
|
101
|
+
return {
|
|
102
|
+
href,
|
|
103
|
+
text: text || href,
|
|
104
|
+
kind: source === 'image' ? 'asset' : classifyHref(href),
|
|
105
|
+
line: node.position?.start?.line ?? 1
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
function extractHtmlLinks(html, line) {
|
|
109
|
+
const links = [];
|
|
110
|
+
const pattern = /<a\s+[^>]*href=(["'])(.*?)\1[^>]*>(.*?)<\/a>/gis;
|
|
111
|
+
let match;
|
|
112
|
+
while ((match = pattern.exec(html))) {
|
|
113
|
+
const href = match[2];
|
|
114
|
+
if (!href)
|
|
115
|
+
continue;
|
|
116
|
+
links.push({
|
|
117
|
+
href,
|
|
118
|
+
text: stripHtml(match[3] ?? href),
|
|
119
|
+
kind: classifyHref(href),
|
|
120
|
+
line
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
return links;
|
|
124
|
+
}
|
|
125
|
+
function classifyHref(href) {
|
|
126
|
+
if (href.startsWith('#'))
|
|
127
|
+
return 'anchor';
|
|
128
|
+
if (href.startsWith('mailto:'))
|
|
129
|
+
return 'mailto';
|
|
130
|
+
if (href.startsWith('tel:'))
|
|
131
|
+
return 'tel';
|
|
132
|
+
if (/^(https?:)?\/\//.test(href) || /^[a-z][a-z0-9+.-]*:/i.test(href))
|
|
133
|
+
return 'external';
|
|
134
|
+
if (/\.(avif|gif|jpe?g|png|svg|webp|pdf|zip)([#?].*)?$/i.test(href))
|
|
135
|
+
return 'asset';
|
|
136
|
+
return 'internal';
|
|
137
|
+
}
|
|
138
|
+
function nodeToText(node) {
|
|
139
|
+
if (!node)
|
|
140
|
+
return '';
|
|
141
|
+
if (typeof node.value === 'string')
|
|
142
|
+
return stripHtml(node.value);
|
|
143
|
+
if (node.type === 'image')
|
|
144
|
+
return node.alt ?? '';
|
|
145
|
+
if (!node.children?.length)
|
|
146
|
+
return '';
|
|
147
|
+
return node.children.map(nodeToText).filter(Boolean).join(' ');
|
|
148
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { SvedocsCodeBlock, SvedocsMessages } from '../core/types.js';
|
|
2
|
+
export type SvedocsMarkdownMessages = Pick<SvedocsMessages, 'code.copy' | 'code.copyDiff' | 'diff.label' | 'diff.aria' | 'diff.before' | 'diff.after'> & Partial<Pick<SvedocsMessages, 'heading.anchor'>>;
|
|
3
|
+
export declare function extractCodeBlocks(markdown: string): SvedocsCodeBlock[];
|
|
4
|
+
export declare function rehypeCodeBlocks(codeBlocks?: SvedocsCodeBlock[]): (tree: unknown) => void;
|
|
5
|
+
export declare function remarkSvedocsCodeBlocks(codeBlocks?: SvedocsCodeBlock[], options?: {
|
|
6
|
+
theme?: string;
|
|
7
|
+
themes?: {
|
|
8
|
+
light?: string;
|
|
9
|
+
dark?: string;
|
|
10
|
+
};
|
|
11
|
+
transformers?: unknown[];
|
|
12
|
+
lineNumbers?: boolean;
|
|
13
|
+
wrap?: boolean;
|
|
14
|
+
copyButton?: boolean;
|
|
15
|
+
messages?: SvedocsMarkdownMessages | undefined;
|
|
16
|
+
}): (tree: unknown) => Promise<void>;
|
|
17
|
+
//# sourceMappingURL=code.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"code.d.ts","sourceRoot":"","sources":["../../src/mdx/code.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAY1E,MAAM,MAAM,uBAAuB,GAAG,IAAI,CACxC,eAAe,EACf,WAAW,GAAG,eAAe,GAAG,YAAY,GAAG,WAAW,GAAG,aAAa,GAAG,YAAY,CAC1F,GAAG,OAAO,CAAC,IAAI,CAAC,eAAe,EAAE,gBAAgB,CAAC,CAAC,CAAC;AAErD,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,gBAAgB,EAAE,CA6BtE;AAED,wBAAgB,gBAAgB,CAAC,UAAU,GAAE,gBAAgB,EAAO,IAC1D,MAAM,OAAO,UAwBtB;AAED,wBAAgB,uBAAuB,CACrC,UAAU,GAAE,gBAAgB,EAAO,EACnC,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAAC,YAAY,CAAC,EAAE,OAAO,EAAE,CAAC;IAAC,WAAW,CAAC,EAAE,OAAO,CAAC;IAAC,IAAI,CAAC,EAAE,OAAO,CAAC;IAAC,UAAU,CAAC,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,uBAAuB,GAAG,SAAS,CAAA;CAAO,IAErM,MAAM,OAAO,mBA4D5B"}
|
package/dist/mdx/code.js
ADDED
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
import { visit } from 'unist-util-visit';
|
|
2
|
+
import { createDiffRows, createDiffSplitRows, renderSplitDiffHtml } from './diff.js';
|
|
3
|
+
import { escapeAttribute, escapeHtml, mergeClassNames, mergeHtmlClass, normalizeShikiLanguage, parseLineSet, readQuotedMeta } from './utils.js';
|
|
4
|
+
export function extractCodeBlocks(markdown) {
|
|
5
|
+
const blocks = [];
|
|
6
|
+
const fencePattern = /```([^\n\r]*)\r?\n([\s\S]*?)```/g;
|
|
7
|
+
let match;
|
|
8
|
+
while ((match = fencePattern.exec(markdown))) {
|
|
9
|
+
const info = match[1]?.trim() ?? '';
|
|
10
|
+
const raw = match[2] ?? '';
|
|
11
|
+
const parsed = parseCodeInfo(info);
|
|
12
|
+
const diffRows = parsed.diff ? createDiffRows(raw) : [];
|
|
13
|
+
const splitRows = parsed.diffMode === 'split' ? createDiffSplitRows(diffRows) : [];
|
|
14
|
+
blocks.push({
|
|
15
|
+
id: `code-${blocks.length + 1}`,
|
|
16
|
+
language: parsed.language,
|
|
17
|
+
raw,
|
|
18
|
+
meta: parsed.meta,
|
|
19
|
+
highlightLines: parsed.highlightLines,
|
|
20
|
+
focusLines: parsed.focusLines,
|
|
21
|
+
...(parsed.title ? { title: parsed.title } : {}),
|
|
22
|
+
diff: parsed.diff,
|
|
23
|
+
...(parsed.diffMode ? { diffMode: parsed.diffMode } : {}),
|
|
24
|
+
diffRows,
|
|
25
|
+
splitRows,
|
|
26
|
+
addedLines: diffRows.filter((row) => row.kind === 'add').length,
|
|
27
|
+
removedLines: diffRows.filter((row) => row.kind === 'remove').length,
|
|
28
|
+
...(parsed.noLineNumbers ? { noLineNumbers: true } : {}),
|
|
29
|
+
...(typeof parsed.wrap === 'boolean' ? { wrap: parsed.wrap } : {})
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
return blocks;
|
|
33
|
+
}
|
|
34
|
+
export function rehypeCodeBlocks(codeBlocks = []) {
|
|
35
|
+
return (tree) => {
|
|
36
|
+
let index = 0;
|
|
37
|
+
visit(tree, 'element', (node) => {
|
|
38
|
+
if (node.tagName !== 'pre')
|
|
39
|
+
return;
|
|
40
|
+
const code = node.children?.find((child) => child.tagName === 'code');
|
|
41
|
+
const block = codeBlocks[index++];
|
|
42
|
+
const className = Array.isArray(code?.properties?.className)
|
|
43
|
+
? code.properties.className.join(' ')
|
|
44
|
+
: '';
|
|
45
|
+
const language = block?.language ?? /language-([^\s]+)/.exec(className)?.[1] ?? 'text';
|
|
46
|
+
node.properties = {
|
|
47
|
+
...node.properties,
|
|
48
|
+
className: mergeClassNames(node.properties?.className, 'sd-code'),
|
|
49
|
+
'data-language': language,
|
|
50
|
+
...(block?.title ? { 'data-title': block.title } : {}),
|
|
51
|
+
...(block?.highlightLines.length ? { 'data-highlight-lines': block.highlightLines.join(',') } : {}),
|
|
52
|
+
...(block?.focusLines.length ? { 'data-focus-lines': block.focusLines.join(',') } : {}),
|
|
53
|
+
...(block?.diff ? { 'data-diff': 'true' } : {}),
|
|
54
|
+
...(block?.diffMode ? { 'data-diff-mode': block.diffMode } : {}),
|
|
55
|
+
...(block && block.addedLines > 0 ? { 'data-added-lines': String(block.addedLines) } : {}),
|
|
56
|
+
...(block && block.removedLines > 0 ? { 'data-removed-lines': String(block.removedLines) } : {})
|
|
57
|
+
};
|
|
58
|
+
});
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
export function remarkSvedocsCodeBlocks(codeBlocks = [], options = {}) {
|
|
62
|
+
return async (tree) => {
|
|
63
|
+
let index = 0;
|
|
64
|
+
const shiki = await import('shiki').catch(() => undefined);
|
|
65
|
+
const transforms = [];
|
|
66
|
+
const showLineNumbers = options.lineNumbers !== false;
|
|
67
|
+
const globalWrap = options.wrap === true;
|
|
68
|
+
visit(tree, 'code', (node, childIndex, parent) => {
|
|
69
|
+
const block = codeBlocks[index++];
|
|
70
|
+
if (!block || childIndex === undefined || !parent?.children)
|
|
71
|
+
return;
|
|
72
|
+
if (block.diff && block.diffMode === 'split') {
|
|
73
|
+
parent.children[childIndex] = {
|
|
74
|
+
type: 'html',
|
|
75
|
+
value: renderSplitDiffHtml(block, { copyButton: options.copyButton !== false, messages: options.messages })
|
|
76
|
+
};
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
if (!shiki)
|
|
80
|
+
return;
|
|
81
|
+
const themes = options.theme !== undefined
|
|
82
|
+
? undefined
|
|
83
|
+
: options.themes ?? { light: 'github-light', dark: 'github-dark' };
|
|
84
|
+
const useDualTheme = Boolean(themes?.light && themes?.dark);
|
|
85
|
+
const renderLineNumbers = showLineNumbers && !block.noLineNumbers;
|
|
86
|
+
const wrapLines = typeof block.wrap === 'boolean' ? block.wrap : globalWrap;
|
|
87
|
+
transforms.push(shiki
|
|
88
|
+
.codeToHtml(node.value, {
|
|
89
|
+
lang: normalizeShikiLanguage(block.language),
|
|
90
|
+
...(useDualTheme
|
|
91
|
+
? {
|
|
92
|
+
themes: { light: themes.light, dark: themes.dark },
|
|
93
|
+
defaultColor: false
|
|
94
|
+
}
|
|
95
|
+
: { theme: options.theme ?? themes?.dark ?? 'github-dark' }),
|
|
96
|
+
...(options.transformers ? { transformers: options.transformers } : {})
|
|
97
|
+
})
|
|
98
|
+
.then((html) => {
|
|
99
|
+
parent.children[childIndex] = {
|
|
100
|
+
type: 'html',
|
|
101
|
+
value: decorateHighlightedCode(html, block, {
|
|
102
|
+
showLineNumbers: renderLineNumbers,
|
|
103
|
+
wrap: wrapLines,
|
|
104
|
+
copyButton: options.copyButton !== false,
|
|
105
|
+
messages: options.messages
|
|
106
|
+
})
|
|
107
|
+
};
|
|
108
|
+
})
|
|
109
|
+
.catch(() => {
|
|
110
|
+
node.data = {
|
|
111
|
+
...(node.data ?? {}),
|
|
112
|
+
hProperties: createCodeProperties(block, renderLineNumbers, wrapLines)
|
|
113
|
+
};
|
|
114
|
+
}));
|
|
115
|
+
});
|
|
116
|
+
await Promise.all(transforms);
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
function parseCodeInfo(info) {
|
|
120
|
+
const [languageToken = 'text', ...rest] = info.split(/\s+/).filter(Boolean);
|
|
121
|
+
const language = languageToken || 'text';
|
|
122
|
+
const meta = rest.join(' ');
|
|
123
|
+
const title = readQuotedMeta(meta, 'title') ?? readQuotedMeta(meta, 'filename');
|
|
124
|
+
const highlightLines = parseLineSet(/\{([^}]+)\}/.exec(meta)?.[1]);
|
|
125
|
+
const focusLines = parseLineSet(/focus=("[^"]+"|'[^']+'|[^\s]+)/.exec(meta)?.[1]?.replace(/^["']|["']$/g, ''));
|
|
126
|
+
const diff = language === 'diff' || /\bdiff\b/.test(meta);
|
|
127
|
+
const diffMode = diff && /\bsplit\b/.test(meta) ? 'split' : diff ? 'unified' : undefined;
|
|
128
|
+
const noLineNumbers = /\b(no-?line-?numbers|nolinenumbers)\b/i.test(meta)
|
|
129
|
+
|| /\bshowLineNumbers=(false|0|no)\b/i.test(meta)
|
|
130
|
+
|| /\blineNumbers=(false|0|no)\b/i.test(meta);
|
|
131
|
+
const wrapTrue = /\bwrap\b(?!=)/i.test(meta) || /\bwrap=(true|1|yes)\b/i.test(meta);
|
|
132
|
+
const wrapFalse = /\bno-?wrap\b/i.test(meta) || /\bwrap=(false|0|no)\b/i.test(meta);
|
|
133
|
+
const wrap = wrapTrue ? true : wrapFalse ? false : undefined;
|
|
134
|
+
return {
|
|
135
|
+
language,
|
|
136
|
+
meta,
|
|
137
|
+
highlightLines,
|
|
138
|
+
focusLines,
|
|
139
|
+
...(title ? { title } : {}),
|
|
140
|
+
diff,
|
|
141
|
+
...(diffMode ? { diffMode } : {}),
|
|
142
|
+
diffRows: [],
|
|
143
|
+
splitRows: [],
|
|
144
|
+
addedLines: 0,
|
|
145
|
+
removedLines: 0,
|
|
146
|
+
...(noLineNumbers ? { noLineNumbers: true } : {}),
|
|
147
|
+
...(typeof wrap === 'boolean' ? { wrap } : {})
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
function createCodeProperties(block, showLineNumbers = true, wrap = false) {
|
|
151
|
+
return {
|
|
152
|
+
className: ['sd-code'],
|
|
153
|
+
'data-language': block.language,
|
|
154
|
+
...(block.title ? { 'data-title': block.title } : {}),
|
|
155
|
+
...(block.highlightLines.length ? { 'data-highlight-lines': block.highlightLines.join(',') } : {}),
|
|
156
|
+
...(block.focusLines.length ? { 'data-focus-lines': block.focusLines.join(',') } : {}),
|
|
157
|
+
...(block.diff ? { 'data-diff': 'true' } : {}),
|
|
158
|
+
...(block.diffMode ? { 'data-diff-mode': block.diffMode } : {}),
|
|
159
|
+
...(block.addedLines > 0 ? { 'data-added-lines': String(block.addedLines) } : {}),
|
|
160
|
+
...(block.removedLines > 0 ? { 'data-removed-lines': String(block.removedLines) } : {}),
|
|
161
|
+
...(showLineNumbers ? {} : { 'data-no-line-numbers': 'true' }),
|
|
162
|
+
...(wrap ? { 'data-wrap': 'true' } : {})
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
function decorateHighlightedCode(html, block, options) {
|
|
166
|
+
const showLineNumbers = options.showLineNumbers;
|
|
167
|
+
const wrap = options.wrap;
|
|
168
|
+
const trimmed = stripTrailingEmptyLine(html);
|
|
169
|
+
const withDecoratedLines = decorateCodeLines(trimmed, block, showLineNumbers);
|
|
170
|
+
const header = renderCodeHeader(block, { copyButton: options.copyButton !== false, messages: options.messages });
|
|
171
|
+
return withDecoratedLines.replace(/<pre([^>]*)>/, (_match, attrs) => {
|
|
172
|
+
const cleanAttrs = attrs.replace(/\sclass="[^"]*"/, '').replace(/\stabindex="[^"]*"/, '');
|
|
173
|
+
return `<pre${cleanAttrs} class="${mergeHtmlClass(attrs, 'sd-code')}" data-language="${escapeAttribute(block.language)}" data-copy="${escapeAttribute(block.raw)}" data-enhanced="true"${block.title ? ` data-title="${escapeAttribute(block.title)}"` : ''}${block.highlightLines.length ? ` data-highlight-lines="${block.highlightLines.join(',')}"` : ''}${block.focusLines.length ? ` data-focus-lines="${block.focusLines.join(',')}"` : ''}${block.diff ? ' data-diff="true"' : ''}${block.diffMode ? ` data-diff-mode="${block.diffMode}"` : ''}${block.addedLines > 0 ? ` data-added-lines="${block.addedLines}"` : ''}${block.removedLines > 0 ? ` data-removed-lines="${block.removedLines}"` : ''}${showLineNumbers ? '' : ' data-no-line-numbers="true"'}${wrap ? ' data-wrap="true"' : ''}>${header}`;
|
|
174
|
+
}).replace(/<code([^>]*)>/, (_match, attrs) => `<code${attrs} data-copy="${escapeAttribute(block.raw)}">`);
|
|
175
|
+
}
|
|
176
|
+
function decorateCodeLines(html, block, showLineNumbers) {
|
|
177
|
+
return html.replace(/<code([^>]*)>([\s\S]*?)<\/code>/, (_match, attrs, code) => {
|
|
178
|
+
const lines = readShikiLines(code);
|
|
179
|
+
if (lines.length === 0)
|
|
180
|
+
return `<code${attrs}>${code}</code>`;
|
|
181
|
+
const highlighted = new Set(block.highlightLines);
|
|
182
|
+
const focused = new Set(block.focusLines);
|
|
183
|
+
const decorated = lines.map((content, index) => {
|
|
184
|
+
const line = index + 1;
|
|
185
|
+
const diffRow = block.diffRows[line - 1];
|
|
186
|
+
const classes = ['line'];
|
|
187
|
+
if (highlighted.has(line))
|
|
188
|
+
classes.push('sd-line-highlight');
|
|
189
|
+
if (focused.has(line))
|
|
190
|
+
classes.push('sd-line-focus');
|
|
191
|
+
if (block.diff) {
|
|
192
|
+
if (diffRow?.kind === 'add')
|
|
193
|
+
classes.push('sd-line-add');
|
|
194
|
+
if (diffRow?.kind === 'remove')
|
|
195
|
+
classes.push('sd-line-remove');
|
|
196
|
+
if (diffRow?.kind === 'meta')
|
|
197
|
+
classes.push('sd-line-meta');
|
|
198
|
+
}
|
|
199
|
+
let lineNoText = String(line);
|
|
200
|
+
if (block.diff && diffRow) {
|
|
201
|
+
if (diffRow.kind === 'add')
|
|
202
|
+
lineNoText = '+';
|
|
203
|
+
else if (diffRow.kind === 'remove')
|
|
204
|
+
lineNoText = '-';
|
|
205
|
+
else if (diffRow.kind === 'meta')
|
|
206
|
+
lineNoText = '·';
|
|
207
|
+
}
|
|
208
|
+
const lineNo = showLineNumbers
|
|
209
|
+
? `<span class="sd-line-no" aria-hidden="true">${lineNoText}</span>`
|
|
210
|
+
: '';
|
|
211
|
+
const contentAttrs = content.length === 0 ? ' data-empty="true"' : '';
|
|
212
|
+
return `<span class="${classes.join(' ')}" data-line="${line}"${diffRow ? ` data-diff-kind="${diffRow.kind}"` : ''}>${lineNo}<span class="sd-line-content"${contentAttrs}>${content}</span></span>`;
|
|
213
|
+
}).join('');
|
|
214
|
+
return `<code${attrs}>${decorated}</code>`;
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
function readShikiLines(code) {
|
|
218
|
+
const lines = [];
|
|
219
|
+
const open = '<span class="line">';
|
|
220
|
+
let offset = 0;
|
|
221
|
+
while (offset < code.length) {
|
|
222
|
+
const start = code.indexOf(open, offset);
|
|
223
|
+
if (start < 0)
|
|
224
|
+
break;
|
|
225
|
+
const contentStart = start + open.length;
|
|
226
|
+
const end = findClosingSpan(code, contentStart);
|
|
227
|
+
if (end < 0)
|
|
228
|
+
break;
|
|
229
|
+
lines.push(code.slice(contentStart, end));
|
|
230
|
+
offset = end + '</span>'.length;
|
|
231
|
+
}
|
|
232
|
+
return lines;
|
|
233
|
+
}
|
|
234
|
+
function findClosingSpan(source, offset) {
|
|
235
|
+
const spanTagPattern = /<\/?span\b[^>]*>/g;
|
|
236
|
+
spanTagPattern.lastIndex = offset;
|
|
237
|
+
let depth = 1;
|
|
238
|
+
let match;
|
|
239
|
+
while ((match = spanTagPattern.exec(source))) {
|
|
240
|
+
if (match[0].startsWith('</')) {
|
|
241
|
+
depth -= 1;
|
|
242
|
+
if (depth === 0)
|
|
243
|
+
return match.index;
|
|
244
|
+
}
|
|
245
|
+
else {
|
|
246
|
+
depth += 1;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
return -1;
|
|
250
|
+
}
|
|
251
|
+
function renderCodeHeader(block, options) {
|
|
252
|
+
const language = block.language || 'text';
|
|
253
|
+
const languageLabel = displayLanguage(language, options.messages);
|
|
254
|
+
const parts = [];
|
|
255
|
+
parts.push(`<span class="sd-code-language" data-language="${escapeAttribute(language)}">${escapeHtml(languageLabel)}</span>`);
|
|
256
|
+
if (block.title) {
|
|
257
|
+
parts.push(`<span class="sd-code-title">${escapeHtml(block.title)}</span>`);
|
|
258
|
+
}
|
|
259
|
+
if (block.addedLines > 0 || block.removedLines > 0) {
|
|
260
|
+
const stats = [];
|
|
261
|
+
if (block.addedLines > 0) {
|
|
262
|
+
stats.push(`<span class="sd-code-stat-add">+${block.addedLines}</span>`);
|
|
263
|
+
}
|
|
264
|
+
if (block.removedLines > 0) {
|
|
265
|
+
stats.push(`<span class="sd-code-stat-remove">-${block.removedLines}</span>`);
|
|
266
|
+
}
|
|
267
|
+
parts.push(`<span class="sd-code-stats">${stats.join('')}</span>`);
|
|
268
|
+
}
|
|
269
|
+
if (options.copyButton) {
|
|
270
|
+
const label = options.messages?.['code.copy'] ?? 'Copy code';
|
|
271
|
+
parts.push(`<button type="button" class="sd-code-copy" data-sd-copy="" aria-label="${escapeAttribute(label)}" title="${escapeAttribute(label)}"><svg viewBox="0 0 24 24" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M9 5h9v14H9zM6 8v12h10"/></svg></button>`);
|
|
272
|
+
}
|
|
273
|
+
return `<div class="sd-code-header">${parts.join('')}</div>`;
|
|
274
|
+
}
|
|
275
|
+
const LANGUAGE_DISPLAY_NAMES = {
|
|
276
|
+
ts: 'TypeScript',
|
|
277
|
+
tsx: 'TSX',
|
|
278
|
+
js: 'JavaScript',
|
|
279
|
+
jsx: 'JSX',
|
|
280
|
+
mjs: 'JavaScript',
|
|
281
|
+
cjs: 'JavaScript',
|
|
282
|
+
svelte: 'Svelte',
|
|
283
|
+
svx: 'Svelte',
|
|
284
|
+
vue: 'Vue',
|
|
285
|
+
html: 'HTML',
|
|
286
|
+
css: 'CSS',
|
|
287
|
+
scss: 'SCSS',
|
|
288
|
+
sass: 'Sass',
|
|
289
|
+
json: 'JSON',
|
|
290
|
+
jsonc: 'JSON',
|
|
291
|
+
yaml: 'YAML',
|
|
292
|
+
yml: 'YAML',
|
|
293
|
+
toml: 'TOML',
|
|
294
|
+
md: 'Markdown',
|
|
295
|
+
mdx: 'MDX',
|
|
296
|
+
sh: 'Shell',
|
|
297
|
+
shell: 'Shell',
|
|
298
|
+
bash: 'Bash',
|
|
299
|
+
zsh: 'Zsh',
|
|
300
|
+
ps1: 'PowerShell',
|
|
301
|
+
python: 'Python',
|
|
302
|
+
py: 'Python',
|
|
303
|
+
rs: 'Rust',
|
|
304
|
+
rust: 'Rust',
|
|
305
|
+
go: 'Go',
|
|
306
|
+
java: 'Java',
|
|
307
|
+
kt: 'Kotlin',
|
|
308
|
+
swift: 'Swift',
|
|
309
|
+
c: 'C',
|
|
310
|
+
cpp: 'C++',
|
|
311
|
+
cs: 'C#',
|
|
312
|
+
sql: 'SQL',
|
|
313
|
+
diff: 'Diff',
|
|
314
|
+
text: 'Text',
|
|
315
|
+
txt: 'Text',
|
|
316
|
+
plaintext: 'Text'
|
|
317
|
+
};
|
|
318
|
+
function displayLanguage(language, messages) {
|
|
319
|
+
if (language === 'diff')
|
|
320
|
+
return messages?.['diff.label'] ?? LANGUAGE_DISPLAY_NAMES.diff ?? 'Diff';
|
|
321
|
+
return LANGUAGE_DISPLAY_NAMES[language] ?? language.toUpperCase();
|
|
322
|
+
}
|
|
323
|
+
function stripTrailingEmptyLine(html) {
|
|
324
|
+
return html
|
|
325
|
+
.replace(/<span class="line"><\/span>(\s*)(<\/code>)/, '$2')
|
|
326
|
+
.replace(/<span class="line">\s*<\/span>(\s*)(<\/code>)/, '$2');
|
|
327
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { SvedocsCodeBlock, SvedocsHeading } from '../core/types.js';
|
|
2
|
+
import { extractCodeBlocks, type SvedocsMarkdownMessages } from './code.js';
|
|
3
|
+
import { createDiffRows, createDiffSplitRows } from './diff.js';
|
|
4
|
+
import { markdownToPlainText } from './utils.js';
|
|
5
|
+
export interface CompiledMarkdown {
|
|
6
|
+
html: string;
|
|
7
|
+
plainText: string;
|
|
8
|
+
headings: SvedocsHeading[];
|
|
9
|
+
codeBlocks: SvedocsCodeBlock[];
|
|
10
|
+
title?: string;
|
|
11
|
+
}
|
|
12
|
+
export interface CompileMarkdownOptions {
|
|
13
|
+
remarkPlugins?: unknown[];
|
|
14
|
+
rehypePlugins?: unknown[];
|
|
15
|
+
codeTheme?: string;
|
|
16
|
+
codeThemes?: {
|
|
17
|
+
light?: string;
|
|
18
|
+
dark?: string;
|
|
19
|
+
};
|
|
20
|
+
shikiTransformers?: unknown[];
|
|
21
|
+
codeLineNumbers?: boolean;
|
|
22
|
+
codeWrap?: boolean;
|
|
23
|
+
codeCopyButton?: boolean;
|
|
24
|
+
messages?: SvedocsMarkdownMessages;
|
|
25
|
+
resolveHref?: (href: string) => string;
|
|
26
|
+
}
|
|
27
|
+
export declare function compileMarkdown(markdown: string, options?: CompileMarkdownOptions): Promise<CompiledMarkdown>;
|
|
28
|
+
export { createDiffRows, createDiffSplitRows, extractCodeBlocks, markdownToPlainText };
|
|
29
|
+
//# sourceMappingURL=compile.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compile.d.ts","sourceRoot":"","sources":["../../src/mdx/compile.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEzE,OAAO,EAAE,iBAAiB,EAA6C,KAAK,uBAAuB,EAAE,MAAM,WAAW,CAAC;AACvH,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAGhE,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEjD,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,cAAc,EAAE,CAAC;IAC3B,UAAU,EAAE,gBAAgB,EAAE,CAAC;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,sBAAsB;IACrC,aAAa,CAAC,EAAE,OAAO,EAAE,CAAC;IAC1B,aAAa,CAAC,EAAE,OAAO,EAAE,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/C,iBAAiB,CAAC,EAAE,OAAO,EAAE,CAAC;IAC9B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,EAAE,uBAAuB,CAAC;IACnC,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;CACxC;AAED,wBAAsB,eAAe,CACnC,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,gBAAgB,CAAC,CAmD3B;AAED,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,CAAC"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import rehypeKatex from 'rehype-katex';
|
|
2
|
+
import rehypeRaw from 'rehype-raw';
|
|
3
|
+
import rehypeSlug from 'rehype-slug';
|
|
4
|
+
import rehypeStringify from 'rehype-stringify';
|
|
5
|
+
import remarkGfm from 'remark-gfm';
|
|
6
|
+
import remarkMath from 'remark-math';
|
|
7
|
+
import remarkParse from 'remark-parse';
|
|
8
|
+
import remarkRehype from 'remark-rehype';
|
|
9
|
+
import { unified } from 'unified';
|
|
10
|
+
import { extractMarkdownOutline, markdownAstToPlainText } from './ast.js';
|
|
11
|
+
import { extractCodeBlocks, rehypeCodeBlocks, remarkSvedocsCodeBlocks } from './code.js';
|
|
12
|
+
import { createDiffRows, createDiffSplitRows } from './diff.js';
|
|
13
|
+
import { rehypeSvedocsHeadingAnchors } from './headings.js';
|
|
14
|
+
import { rehypeSvedocsLinks } from './links.js';
|
|
15
|
+
import { markdownToPlainText } from './utils.js';
|
|
16
|
+
export async function compileMarkdown(markdown, options = {}) {
|
|
17
|
+
const extracted = extractMarkdownOutline(markdown);
|
|
18
|
+
const codeBlocks = extractCodeBlocks(markdown);
|
|
19
|
+
const processor = unified()
|
|
20
|
+
.use(remarkParse)
|
|
21
|
+
.use(remarkGfm)
|
|
22
|
+
.use(remarkMath);
|
|
23
|
+
for (const plugin of options.remarkPlugins ?? []) {
|
|
24
|
+
processor.use(plugin);
|
|
25
|
+
}
|
|
26
|
+
processor
|
|
27
|
+
.use(remarkSvedocsCodeBlocks, codeBlocks, {
|
|
28
|
+
...(options.codeTheme ? { theme: options.codeTheme } : {}),
|
|
29
|
+
...(options.codeThemes ? { themes: options.codeThemes } : {}),
|
|
30
|
+
...(options.shikiTransformers ? { transformers: options.shikiTransformers } : {}),
|
|
31
|
+
...(typeof options.codeLineNumbers === 'boolean' ? { lineNumbers: options.codeLineNumbers } : {}),
|
|
32
|
+
...(typeof options.codeWrap === 'boolean' ? { wrap: options.codeWrap } : {}),
|
|
33
|
+
...(typeof options.codeCopyButton === 'boolean' ? { copyButton: options.codeCopyButton } : {}),
|
|
34
|
+
...(options.messages ? { messages: options.messages } : {})
|
|
35
|
+
})
|
|
36
|
+
.use(remarkRehype, { allowDangerousHtml: true })
|
|
37
|
+
.use(rehypeRaw)
|
|
38
|
+
.use(rehypeSlug)
|
|
39
|
+
.use(rehypeSvedocsHeadingAnchors, options.messages?.['heading.anchor']
|
|
40
|
+
? { label: options.messages['heading.anchor'] }
|
|
41
|
+
: {})
|
|
42
|
+
.use(rehypeKatex)
|
|
43
|
+
.use(rehypeSvedocsLinks, options.resolveHref ? { resolveHref: options.resolveHref } : {});
|
|
44
|
+
for (const plugin of options.rehypePlugins ?? []) {
|
|
45
|
+
processor.use(plugin);
|
|
46
|
+
}
|
|
47
|
+
const file = await processor
|
|
48
|
+
.use(rehypeCodeBlocks, codeBlocks)
|
|
49
|
+
.use(rehypeStringify, { allowDangerousHtml: true })
|
|
50
|
+
.process(markdown);
|
|
51
|
+
return {
|
|
52
|
+
html: String(file),
|
|
53
|
+
plainText: markdownAstToPlainText(markdown),
|
|
54
|
+
headings: extracted.headings,
|
|
55
|
+
codeBlocks,
|
|
56
|
+
...(extracted.title ? { title: extracted.title } : {})
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
export { createDiffRows, createDiffSplitRows, extractCodeBlocks, markdownToPlainText };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { SvedocsCodeBlock, SvedocsDiffRow, SvedocsDiffSplitRow } from '../core/types.js';
|
|
2
|
+
import type { SvedocsMarkdownMessages } from './code.js';
|
|
3
|
+
export declare function createDiffRows(raw: string): SvedocsDiffRow[];
|
|
4
|
+
export declare function createDiffSplitRows(rows: SvedocsDiffRow[]): SvedocsDiffSplitRow[];
|
|
5
|
+
export declare function renderSplitDiffHtml(block: SvedocsCodeBlock, options?: {
|
|
6
|
+
copyButton?: boolean;
|
|
7
|
+
messages?: SvedocsMarkdownMessages | undefined;
|
|
8
|
+
}): string;
|
|
9
|
+
//# sourceMappingURL=diff.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../../src/mdx/diff.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAC9F,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,WAAW,CAAC;AAGzD,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,EAAE,CA4C5D;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,cAAc,EAAE,GAAG,mBAAmB,EAAE,CA4CjF;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,gBAAgB,EAAE,OAAO,GAAE;IAAE,UAAU,CAAC,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,uBAAuB,GAAG,SAAS,CAAA;CAAO,GAAG,MAAM,CAe3J"}
|