svedocs 0.1.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (192) hide show
  1. package/LICENSE +5 -0
  2. package/README.md +38 -0
  3. package/dist/ai/openai-compatible.d.ts +13 -0
  4. package/dist/ai/openai-compatible.d.ts.map +1 -0
  5. package/dist/ai/openai-compatible.js +92 -0
  6. package/dist/ai/providers.d.ts +19 -0
  7. package/dist/ai/providers.d.ts.map +1 -0
  8. package/dist/ai/providers.js +185 -0
  9. package/dist/ai/rate-limit.d.ts +18 -0
  10. package/dist/ai/rate-limit.d.ts.map +1 -0
  11. package/dist/ai/rate-limit.js +52 -0
  12. package/dist/ai/response.d.ts +4 -0
  13. package/dist/ai/response.d.ts.map +1 -0
  14. package/dist/ai/response.js +151 -0
  15. package/dist/ai/runtime.d.ts +30 -0
  16. package/dist/ai/runtime.d.ts.map +1 -0
  17. package/dist/ai/runtime.js +105 -0
  18. package/dist/ai/types.d.ts +93 -0
  19. package/dist/ai/types.d.ts.map +1 -0
  20. package/dist/ai/types.js +1 -0
  21. package/dist/ai.d.ts +7 -0
  22. package/dist/ai.d.ts.map +1 -0
  23. package/dist/ai.js +6 -0
  24. package/dist/ambient.d.ts +5 -0
  25. package/dist/cloudflare.d.ts +27 -0
  26. package/dist/cloudflare.d.ts.map +1 -0
  27. package/dist/cloudflare.js +146 -0
  28. package/dist/config.d.ts +311 -0
  29. package/dist/config.d.ts.map +1 -0
  30. package/dist/config.js +243 -0
  31. package/dist/core/checks.d.ts +4 -0
  32. package/dist/core/checks.d.ts.map +1 -0
  33. package/dist/core/checks.js +252 -0
  34. package/dist/core/config.d.ts +5 -0
  35. package/dist/core/config.d.ts.map +1 -0
  36. package/dist/core/config.js +182 -0
  37. package/dist/core/content.d.ts +7 -0
  38. package/dist/core/content.d.ts.map +1 -0
  39. package/dist/core/content.js +211 -0
  40. package/dist/core/links.d.ts +8 -0
  41. package/dist/core/links.d.ts.map +1 -0
  42. package/dist/core/links.js +94 -0
  43. package/dist/core/navigation.d.ts +5 -0
  44. package/dist/core/navigation.d.ts.map +1 -0
  45. package/dist/core/navigation.js +144 -0
  46. package/dist/core/search.d.ts +5 -0
  47. package/dist/core/search.d.ts.map +1 -0
  48. package/dist/core/search.js +41 -0
  49. package/dist/core/types.d.ts +269 -0
  50. package/dist/core/types.d.ts.map +1 -0
  51. package/dist/core/types.js +4 -0
  52. package/dist/core/utils.d.ts +12 -0
  53. package/dist/core/utils.d.ts.map +1 -0
  54. package/dist/core/utils.js +52 -0
  55. package/dist/core.d.ts +8 -0
  56. package/dist/core.d.ts.map +1 -0
  57. package/dist/core.js +7 -0
  58. package/dist/index.d.ts +6 -0
  59. package/dist/index.d.ts.map +1 -0
  60. package/dist/index.js +3 -0
  61. package/dist/mdx/ast.d.ts +32 -0
  62. package/dist/mdx/ast.d.ts.map +1 -0
  63. package/dist/mdx/ast.js +148 -0
  64. package/dist/mdx/code.d.ts +14 -0
  65. package/dist/mdx/code.d.ts.map +1 -0
  66. package/dist/mdx/code.js +315 -0
  67. package/dist/mdx/compile.d.ts +26 -0
  68. package/dist/mdx/compile.d.ts.map +1 -0
  69. package/dist/mdx/compile.js +63 -0
  70. package/dist/mdx/diff.d.ts +5 -0
  71. package/dist/mdx/diff.d.ts.map +1 -0
  72. package/dist/mdx/diff.js +160 -0
  73. package/dist/mdx/utils.d.ts +10 -0
  74. package/dist/mdx/utils.d.ts.map +1 -0
  75. package/dist/mdx/utils.js +64 -0
  76. package/dist/og/image.d.ts +21 -0
  77. package/dist/og/image.d.ts.map +1 -0
  78. package/dist/og/image.js +216 -0
  79. package/dist/og/metadata.d.ts +7 -0
  80. package/dist/og/metadata.d.ts.map +1 -0
  81. package/dist/og/metadata.js +160 -0
  82. package/dist/og/types.d.ts +59 -0
  83. package/dist/og/types.d.ts.map +1 -0
  84. package/dist/og/types.js +1 -0
  85. package/dist/og.d.ts +4 -0
  86. package/dist/og.d.ts.map +1 -0
  87. package/dist/og.js +3 -0
  88. package/dist/search/algolia.d.ts +10 -0
  89. package/dist/search/algolia.d.ts.map +1 -0
  90. package/dist/search/algolia.js +82 -0
  91. package/dist/search/cloudflare-sync.d.ts +5 -0
  92. package/dist/search/cloudflare-sync.d.ts.map +1 -0
  93. package/dist/search/cloudflare-sync.js +169 -0
  94. package/dist/search/cloudflare.d.ts +9 -0
  95. package/dist/search/cloudflare.d.ts.map +1 -0
  96. package/dist/search/cloudflare.js +115 -0
  97. package/dist/search/local.d.ts +9 -0
  98. package/dist/search/local.d.ts.map +1 -0
  99. package/dist/search/local.js +122 -0
  100. package/dist/search/runtime.d.ts +41 -0
  101. package/dist/search/runtime.d.ts.map +1 -0
  102. package/dist/search/runtime.js +151 -0
  103. package/dist/search/types.d.ts +172 -0
  104. package/dist/search/types.d.ts.map +1 -0
  105. package/dist/search/types.js +1 -0
  106. package/dist/search/typesense.d.ts +11 -0
  107. package/dist/search/typesense.d.ts.map +1 -0
  108. package/dist/search/typesense.js +91 -0
  109. package/dist/search/utils.d.ts +10 -0
  110. package/dist/search/utils.d.ts.map +1 -0
  111. package/dist/search/utils.js +55 -0
  112. package/dist/search.d.ts +8 -0
  113. package/dist/search.d.ts.map +1 -0
  114. package/dist/search.js +7 -0
  115. package/dist/svelte.d.ts +24 -0
  116. package/dist/svelte.d.ts.map +1 -0
  117. package/dist/svelte.js +51 -0
  118. package/dist/testing.d.ts +3 -0
  119. package/dist/testing.d.ts.map +1 -0
  120. package/dist/testing.js +23 -0
  121. package/dist/theme/AskAiPanel.svelte +433 -0
  122. package/dist/theme/AskAiPanel.svelte.d.ts +27 -0
  123. package/dist/theme/AskAiPanel.svelte.d.ts.map +1 -0
  124. package/dist/theme/Button.svelte +34 -0
  125. package/dist/theme/Button.svelte.d.ts +41 -0
  126. package/dist/theme/Button.svelte.d.ts.map +1 -0
  127. package/dist/theme/Checkbox.svelte +63 -0
  128. package/dist/theme/Checkbox.svelte.d.ts +45 -0
  129. package/dist/theme/Checkbox.svelte.d.ts.map +1 -0
  130. package/dist/theme/CodeBlock.svelte +6 -0
  131. package/dist/theme/CodeBlock.svelte.d.ts +22 -0
  132. package/dist/theme/CodeBlock.svelte.d.ts.map +1 -0
  133. package/dist/theme/DocPage.svelte +121 -0
  134. package/dist/theme/DocPage.svelte.d.ts +33 -0
  135. package/dist/theme/DocPage.svelte.d.ts.map +1 -0
  136. package/dist/theme/DocsApp.svelte +78 -0
  137. package/dist/theme/DocsApp.svelte.d.ts +63 -0
  138. package/dist/theme/DocsApp.svelte.d.ts.map +1 -0
  139. package/dist/theme/DocsLayout.svelte +167 -0
  140. package/dist/theme/DocsLayout.svelte.d.ts +40 -0
  141. package/dist/theme/DocsLayout.svelte.d.ts.map +1 -0
  142. package/dist/theme/FloatingToolbar.svelte +73 -0
  143. package/dist/theme/FloatingToolbar.svelte.d.ts +22 -0
  144. package/dist/theme/FloatingToolbar.svelte.d.ts.map +1 -0
  145. package/dist/theme/FormField.svelte +41 -0
  146. package/dist/theme/FormField.svelte.d.ts +35 -0
  147. package/dist/theme/FormField.svelte.d.ts.map +1 -0
  148. package/dist/theme/HomePage.svelte +228 -0
  149. package/dist/theme/HomePage.svelte.d.ts +58 -0
  150. package/dist/theme/HomePage.svelte.d.ts.map +1 -0
  151. package/dist/theme/Input.svelte +36 -0
  152. package/dist/theme/Input.svelte.d.ts +34 -0
  153. package/dist/theme/Input.svelte.d.ts.map +1 -0
  154. package/dist/theme/PageLayout.svelte +36 -0
  155. package/dist/theme/PageLayout.svelte.d.ts +31 -0
  156. package/dist/theme/PageLayout.svelte.d.ts.map +1 -0
  157. package/dist/theme/RootLayout.svelte +330 -0
  158. package/dist/theme/RootLayout.svelte.d.ts +40 -0
  159. package/dist/theme/RootLayout.svelte.d.ts.map +1 -0
  160. package/dist/theme/ScopeSwitcher.svelte +103 -0
  161. package/dist/theme/ScopeSwitcher.svelte.d.ts +24 -0
  162. package/dist/theme/ScopeSwitcher.svelte.d.ts.map +1 -0
  163. package/dist/theme/SearchDialog.svelte +253 -0
  164. package/dist/theme/SearchDialog.svelte.d.ts +28 -0
  165. package/dist/theme/SearchDialog.svelte.d.ts.map +1 -0
  166. package/dist/theme/Select.svelte +37 -0
  167. package/dist/theme/Select.svelte.d.ts +42 -0
  168. package/dist/theme/Select.svelte.d.ts.map +1 -0
  169. package/dist/theme/SidebarTree.svelte +136 -0
  170. package/dist/theme/SidebarTree.svelte.d.ts +24 -0
  171. package/dist/theme/SidebarTree.svelte.d.ts.map +1 -0
  172. package/dist/theme/Textarea.svelte +33 -0
  173. package/dist/theme/Textarea.svelte.d.ts +33 -0
  174. package/dist/theme/Textarea.svelte.d.ts.map +1 -0
  175. package/dist/theme/ThemeToggle.svelte +39 -0
  176. package/dist/theme/ThemeToggle.svelte.d.ts +21 -0
  177. package/dist/theme/ThemeToggle.svelte.d.ts.map +1 -0
  178. package/dist/theme/forms.d.ts +4 -0
  179. package/dist/theme/forms.d.ts.map +1 -0
  180. package/dist/theme/forms.js +3 -0
  181. package/dist/theme/index.d.ts +21 -0
  182. package/dist/theme/index.d.ts.map +1 -0
  183. package/dist/theme/index.js +19 -0
  184. package/dist/theme/portal.d.ts +5 -0
  185. package/dist/theme/portal.d.ts.map +1 -0
  186. package/dist/theme/portal.js +19 -0
  187. package/dist/theme/styles.css +3697 -0
  188. package/dist/virtual.d.ts +59 -0
  189. package/dist/vite.d.ts +10 -0
  190. package/dist/vite.d.ts.map +1 -0
  191. package/dist/vite.js +304 -0
  192. package/package.json +118 -0
@@ -0,0 +1,6 @@
1
+ export { defineConfig } from './config.js';
2
+ export type { SvedocsConfig, SvedocsResolvedConfig } from './config.js';
3
+ export { createPageTree, createSearchRecords, loadSvedocsContent, resolveSvedocsConfig, svedocsPackage } from './core.js';
4
+ export type { SvedocsContentManifest, SvedocsContentIssue, SvedocsCodeBlock, SvedocsDiffRow, SvedocsDiffSplitRow, SvedocsHeading, SvedocsLink, SvedocsLinkReference, SvedocsLocale, SvedocsPage, SvedocsSearchRecord, SvedocsSeo, SvedocsTreeItem } from './core.js';
5
+ export declare const version = "0.0.0";
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,YAAY,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACxE,OAAO,EACL,cAAc,EACd,mBAAmB,EACnB,kBAAkB,EAClB,oBAAoB,EACpB,cAAc,EACf,MAAM,WAAW,CAAC;AACnB,YAAY,EACV,sBAAsB,EACtB,mBAAmB,EACnB,gBAAgB,EAChB,cAAc,EACd,mBAAmB,EACnB,cAAc,EACd,WAAW,EACX,oBAAoB,EACpB,aAAa,EACb,WAAW,EACX,mBAAmB,EACnB,UAAU,EACV,eAAe,EAChB,MAAM,WAAW,CAAC;AAEnB,eAAO,MAAM,OAAO,UAAU,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export { defineConfig } from './config.js';
2
+ export { createPageTree, createSearchRecords, loadSvedocsContent, resolveSvedocsConfig, svedocsPackage } from './core.js';
3
+ export const version = '0.0.0';
@@ -0,0 +1,32 @@
1
+ import type { SvedocsHeading, SvedocsLinkReference } from '../core/types.js';
2
+ interface MarkdownNode {
3
+ type: string;
4
+ value?: string;
5
+ alt?: string;
6
+ url?: string;
7
+ identifier?: string;
8
+ label?: string;
9
+ children?: MarkdownNode[];
10
+ depth?: number;
11
+ position?: {
12
+ start?: {
13
+ line?: number;
14
+ };
15
+ };
16
+ }
17
+ export interface MarkdownSection {
18
+ id: string;
19
+ depth: 2 | 3 | 4;
20
+ title: string;
21
+ content: string;
22
+ }
23
+ export declare function parseMarkdownAst(markdown: string): MarkdownNode;
24
+ export declare function extractMarkdownOutline(markdown: string): {
25
+ title?: string;
26
+ headings: SvedocsHeading[];
27
+ };
28
+ export declare function markdownAstToPlainText(markdown: string): string;
29
+ export declare function extractMarkdownSections(markdown: string): MarkdownSection[];
30
+ export declare function extractMarkdownLinksFromAst(markdown: string): SvedocsLinkReference[];
31
+ export {};
32
+ //# sourceMappingURL=ast.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ast.d.ts","sourceRoot":"","sources":["../../src/mdx/ast.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAG7E,UAAU,YAAY;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,YAAY,EAAE,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE;QACT,KAAK,CAAC,EAAE;YACN,IAAI,CAAC,EAAE,MAAM,CAAC;SACf,CAAC;KACH,CAAC;CACH;AAED,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,YAAY,CAM/D;AAED,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,cAAc,EAAE,CAAA;CAAE,CAkBvG;AAED,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE/D;AAED,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,eAAe,EAAE,CAqC3E;AAED,wBAAgB,2BAA2B,CAAC,QAAQ,EAAE,MAAM,GAAG,oBAAoB,EAAE,CA4BpF"}
@@ -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,14 @@
1
+ import type { SvedocsCodeBlock } from '../core/types.js';
2
+ export declare function extractCodeBlocks(markdown: string): SvedocsCodeBlock[];
3
+ export declare function rehypeCodeBlocks(codeBlocks?: SvedocsCodeBlock[]): (tree: unknown) => void;
4
+ export declare function remarkSvedocsCodeBlocks(codeBlocks?: SvedocsCodeBlock[], options?: {
5
+ theme?: string;
6
+ themes?: {
7
+ light?: string;
8
+ dark?: string;
9
+ };
10
+ transformers?: unknown[];
11
+ lineNumbers?: boolean;
12
+ wrap?: boolean;
13
+ }): (tree: unknown) => Promise<void>;
14
+ //# 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,MAAM,kBAAkB,CAAC;AAYzD,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,CAAA;CAAO,IAE/H,MAAM,OAAO,mBAqD5B"}
@@ -0,0 +1,315 @@
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)
76
+ };
77
+ return;
78
+ }
79
+ if (!shiki)
80
+ return;
81
+ const themes = options.themes ?? { light: 'github-light', dark: 'github-dark' };
82
+ const useDualTheme = Boolean(themes.light && themes.dark);
83
+ const renderLineNumbers = showLineNumbers && !block.noLineNumbers;
84
+ const wrapLines = typeof block.wrap === 'boolean' ? block.wrap : globalWrap;
85
+ transforms.push(shiki
86
+ .codeToHtml(node.value, {
87
+ lang: normalizeShikiLanguage(block.language),
88
+ ...(useDualTheme
89
+ ? {
90
+ themes: { light: themes.light, dark: themes.dark },
91
+ defaultColor: false
92
+ }
93
+ : { theme: options.theme ?? themes.dark ?? 'github-dark' }),
94
+ ...(options.transformers ? { transformers: options.transformers } : {})
95
+ })
96
+ .then((html) => {
97
+ parent.children[childIndex] = {
98
+ type: 'html',
99
+ value: decorateHighlightedCode(html, block, { showLineNumbers: renderLineNumbers, wrap: wrapLines })
100
+ };
101
+ })
102
+ .catch(() => {
103
+ node.data = {
104
+ ...(node.data ?? {}),
105
+ hProperties: createCodeProperties(block, renderLineNumbers, wrapLines)
106
+ };
107
+ }));
108
+ });
109
+ await Promise.all(transforms);
110
+ };
111
+ }
112
+ function parseCodeInfo(info) {
113
+ const [languageToken = 'text', ...rest] = info.split(/\s+/).filter(Boolean);
114
+ const language = languageToken || 'text';
115
+ const meta = rest.join(' ');
116
+ const title = readQuotedMeta(meta, 'title') ?? readQuotedMeta(meta, 'filename');
117
+ const highlightLines = parseLineSet(/\{([^}]+)\}/.exec(meta)?.[1]);
118
+ const focusLines = parseLineSet(/focus=("[^"]+"|'[^']+'|[^\s]+)/.exec(meta)?.[1]?.replace(/^["']|["']$/g, ''));
119
+ const diff = language === 'diff' || /\bdiff\b/.test(meta);
120
+ const diffMode = diff && /\bsplit\b/.test(meta) ? 'split' : diff ? 'unified' : undefined;
121
+ const noLineNumbers = /\b(no-?line-?numbers|nolinenumbers)\b/i.test(meta)
122
+ || /\bshowLineNumbers=(false|0|no)\b/i.test(meta)
123
+ || /\blineNumbers=(false|0|no)\b/i.test(meta);
124
+ const wrapTrue = /\bwrap\b(?!=)/i.test(meta) || /\bwrap=(true|1|yes)\b/i.test(meta);
125
+ const wrapFalse = /\bno-?wrap\b/i.test(meta) || /\bwrap=(false|0|no)\b/i.test(meta);
126
+ const wrap = wrapTrue ? true : wrapFalse ? false : undefined;
127
+ return {
128
+ language,
129
+ meta,
130
+ highlightLines,
131
+ focusLines,
132
+ ...(title ? { title } : {}),
133
+ diff,
134
+ ...(diffMode ? { diffMode } : {}),
135
+ diffRows: [],
136
+ splitRows: [],
137
+ addedLines: 0,
138
+ removedLines: 0,
139
+ ...(noLineNumbers ? { noLineNumbers: true } : {}),
140
+ ...(typeof wrap === 'boolean' ? { wrap } : {})
141
+ };
142
+ }
143
+ function createCodeProperties(block, showLineNumbers = true, wrap = false) {
144
+ return {
145
+ className: ['sd-code'],
146
+ 'data-language': block.language,
147
+ ...(block.title ? { 'data-title': block.title } : {}),
148
+ ...(block.highlightLines.length ? { 'data-highlight-lines': block.highlightLines.join(',') } : {}),
149
+ ...(block.focusLines.length ? { 'data-focus-lines': block.focusLines.join(',') } : {}),
150
+ ...(block.diff ? { 'data-diff': 'true' } : {}),
151
+ ...(block.diffMode ? { 'data-diff-mode': block.diffMode } : {}),
152
+ ...(block.addedLines > 0 ? { 'data-added-lines': String(block.addedLines) } : {}),
153
+ ...(block.removedLines > 0 ? { 'data-removed-lines': String(block.removedLines) } : {}),
154
+ ...(showLineNumbers ? {} : { 'data-no-line-numbers': 'true' }),
155
+ ...(wrap ? { 'data-wrap': 'true' } : {})
156
+ };
157
+ }
158
+ function decorateHighlightedCode(html, block, options) {
159
+ const showLineNumbers = options.showLineNumbers;
160
+ const wrap = options.wrap;
161
+ const trimmed = stripTrailingEmptyLine(html);
162
+ const withDecoratedLines = decorateCodeLines(trimmed, block, showLineNumbers);
163
+ const header = renderCodeHeader(block);
164
+ return withDecoratedLines.replace(/<pre([^>]*)>/, (_match, attrs) => {
165
+ const cleanAttrs = attrs.replace(/\sclass="[^"]*"/, '').replace(/\stabindex="[^"]*"/, '');
166
+ 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}`;
167
+ }).replace(/<code([^>]*)>/, (_match, attrs) => `<code${attrs} data-copy="${escapeAttribute(block.raw)}">`);
168
+ }
169
+ function decorateCodeLines(html, block, showLineNumbers) {
170
+ return html.replace(/<code([^>]*)>([\s\S]*?)<\/code>/, (_match, attrs, code) => {
171
+ const lines = readShikiLines(code);
172
+ if (lines.length === 0)
173
+ return `<code${attrs}>${code}</code>`;
174
+ const highlighted = new Set(block.highlightLines);
175
+ const focused = new Set(block.focusLines);
176
+ const decorated = lines.map((content, index) => {
177
+ const line = index + 1;
178
+ const diffRow = block.diffRows[line - 1];
179
+ const classes = ['line'];
180
+ if (highlighted.has(line))
181
+ classes.push('sd-line-highlight');
182
+ if (focused.has(line))
183
+ classes.push('sd-line-focus');
184
+ if (block.diff) {
185
+ if (diffRow?.kind === 'add')
186
+ classes.push('sd-line-add');
187
+ if (diffRow?.kind === 'remove')
188
+ classes.push('sd-line-remove');
189
+ if (diffRow?.kind === 'meta')
190
+ classes.push('sd-line-meta');
191
+ }
192
+ let lineNoText = String(line);
193
+ if (block.diff && diffRow) {
194
+ if (diffRow.kind === 'add')
195
+ lineNoText = '+';
196
+ else if (diffRow.kind === 'remove')
197
+ lineNoText = '-';
198
+ else if (diffRow.kind === 'meta')
199
+ lineNoText = '·';
200
+ }
201
+ const lineNo = showLineNumbers
202
+ ? `<span class="sd-line-no" aria-hidden="true">${lineNoText}</span>`
203
+ : '';
204
+ const contentAttrs = content.length === 0 ? ' data-empty="true"' : '';
205
+ return `<span class="${classes.join(' ')}" data-line="${line}"${diffRow ? ` data-diff-kind="${diffRow.kind}"` : ''}>${lineNo}<span class="sd-line-content"${contentAttrs}>${content}</span></span>`;
206
+ }).join('');
207
+ return `<code${attrs}>${decorated}</code>`;
208
+ });
209
+ }
210
+ function readShikiLines(code) {
211
+ const lines = [];
212
+ const open = '<span class="line">';
213
+ let offset = 0;
214
+ while (offset < code.length) {
215
+ const start = code.indexOf(open, offset);
216
+ if (start < 0)
217
+ break;
218
+ const contentStart = start + open.length;
219
+ const end = findClosingSpan(code, contentStart);
220
+ if (end < 0)
221
+ break;
222
+ lines.push(code.slice(contentStart, end));
223
+ offset = end + '</span>'.length;
224
+ }
225
+ return lines;
226
+ }
227
+ function findClosingSpan(source, offset) {
228
+ const spanTagPattern = /<\/?span\b[^>]*>/g;
229
+ spanTagPattern.lastIndex = offset;
230
+ let depth = 1;
231
+ let match;
232
+ while ((match = spanTagPattern.exec(source))) {
233
+ if (match[0].startsWith('</')) {
234
+ depth -= 1;
235
+ if (depth === 0)
236
+ return match.index;
237
+ }
238
+ else {
239
+ depth += 1;
240
+ }
241
+ }
242
+ return -1;
243
+ }
244
+ function renderCodeHeader(block) {
245
+ const language = block.language || 'text';
246
+ const languageLabel = displayLanguage(language);
247
+ const parts = [];
248
+ parts.push(`<span class="sd-code-language" data-language="${escapeAttribute(language)}">${escapeHtml(languageLabel)}</span>`);
249
+ if (block.title) {
250
+ parts.push(`<span class="sd-code-title">${escapeHtml(block.title)}</span>`);
251
+ }
252
+ if (block.addedLines > 0 || block.removedLines > 0) {
253
+ const stats = [];
254
+ if (block.addedLines > 0) {
255
+ stats.push(`<span class="sd-code-stat-add">+${block.addedLines}</span>`);
256
+ }
257
+ if (block.removedLines > 0) {
258
+ stats.push(`<span class="sd-code-stat-remove">-${block.removedLines}</span>`);
259
+ }
260
+ parts.push(`<span class="sd-code-stats">${stats.join('')}</span>`);
261
+ }
262
+ parts.push(`<button type="button" class="sd-code-copy" data-sd-copy="" aria-label="Copy code" title="Copy code"><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>`);
263
+ return `<div class="sd-code-header">${parts.join('')}</div>`;
264
+ }
265
+ const LANGUAGE_DISPLAY_NAMES = {
266
+ ts: 'TypeScript',
267
+ tsx: 'TSX',
268
+ js: 'JavaScript',
269
+ jsx: 'JSX',
270
+ mjs: 'JavaScript',
271
+ cjs: 'JavaScript',
272
+ svelte: 'Svelte',
273
+ svx: 'Svelte',
274
+ vue: 'Vue',
275
+ html: 'HTML',
276
+ css: 'CSS',
277
+ scss: 'SCSS',
278
+ sass: 'Sass',
279
+ json: 'JSON',
280
+ jsonc: 'JSON',
281
+ yaml: 'YAML',
282
+ yml: 'YAML',
283
+ toml: 'TOML',
284
+ md: 'Markdown',
285
+ mdx: 'MDX',
286
+ sh: 'Shell',
287
+ shell: 'Shell',
288
+ bash: 'Bash',
289
+ zsh: 'Zsh',
290
+ ps1: 'PowerShell',
291
+ python: 'Python',
292
+ py: 'Python',
293
+ rs: 'Rust',
294
+ rust: 'Rust',
295
+ go: 'Go',
296
+ java: 'Java',
297
+ kt: 'Kotlin',
298
+ swift: 'Swift',
299
+ c: 'C',
300
+ cpp: 'C++',
301
+ cs: 'C#',
302
+ sql: 'SQL',
303
+ diff: 'Diff',
304
+ text: 'Text',
305
+ txt: 'Text',
306
+ plaintext: 'Text'
307
+ };
308
+ function displayLanguage(language) {
309
+ return LANGUAGE_DISPLAY_NAMES[language] ?? language.toUpperCase();
310
+ }
311
+ function stripTrailingEmptyLine(html) {
312
+ return html
313
+ .replace(/<span class="line"><\/span>(\s*)(<\/code>)/, '$2')
314
+ .replace(/<span class="line">\s*<\/span>(\s*)(<\/code>)/, '$2');
315
+ }
@@ -0,0 +1,26 @@
1
+ import type { SvedocsCodeBlock, SvedocsHeading } from '../core/types.js';
2
+ import { extractCodeBlocks } 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
+ }
24
+ export declare function compileMarkdown(markdown: string, options?: CompileMarkdownOptions): Promise<CompiledMarkdown>;
25
+ export { createDiffRows, createDiffSplitRows, extractCodeBlocks, markdownToPlainText };
26
+ //# sourceMappingURL=compile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compile.d.ts","sourceRoot":"","sources":["../../src/mdx/compile.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEzE,OAAO,EAAE,iBAAiB,EAA6C,MAAM,WAAW,CAAC;AACzF,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAChE,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;CACpB;AAED,wBAAsB,eAAe,CACnC,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,gBAAgB,CAAC,CAwD3B;AAED,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,CAAC"}
@@ -0,0 +1,63 @@
1
+ import rehypeAutolinkHeadings from 'rehype-autolink-headings';
2
+ import rehypeKatex from 'rehype-katex';
3
+ import rehypeRaw from 'rehype-raw';
4
+ import rehypeSlug from 'rehype-slug';
5
+ import rehypeStringify from 'rehype-stringify';
6
+ import remarkGfm from 'remark-gfm';
7
+ import remarkMath from 'remark-math';
8
+ import remarkParse from 'remark-parse';
9
+ import remarkRehype from 'remark-rehype';
10
+ import { unified } from 'unified';
11
+ import { extractMarkdownOutline, markdownAstToPlainText } from './ast.js';
12
+ import { extractCodeBlocks, rehypeCodeBlocks, remarkSvedocsCodeBlocks } from './code.js';
13
+ import { createDiffRows, createDiffSplitRows } from './diff.js';
14
+ import { markdownToPlainText } from './utils.js';
15
+ export async function compileMarkdown(markdown, options = {}) {
16
+ const extracted = extractMarkdownOutline(markdown);
17
+ const codeBlocks = extractCodeBlocks(markdown);
18
+ const processor = unified()
19
+ .use(remarkParse)
20
+ .use(remarkGfm)
21
+ .use(remarkMath);
22
+ for (const plugin of options.remarkPlugins ?? []) {
23
+ processor.use(plugin);
24
+ }
25
+ processor
26
+ .use(remarkSvedocsCodeBlocks, codeBlocks, {
27
+ ...(options.codeTheme ? { theme: options.codeTheme } : {}),
28
+ ...(options.codeThemes ? { themes: options.codeThemes } : {}),
29
+ ...(options.shikiTransformers ? { transformers: options.shikiTransformers } : {}),
30
+ ...(typeof options.codeLineNumbers === 'boolean' ? { lineNumbers: options.codeLineNumbers } : {}),
31
+ ...(typeof options.codeWrap === 'boolean' ? { wrap: options.codeWrap } : {})
32
+ })
33
+ .use(remarkRehype, { allowDangerousHtml: true })
34
+ .use(rehypeRaw)
35
+ .use(rehypeSlug)
36
+ .use(rehypeAutolinkHeadings, {
37
+ behavior: 'append',
38
+ properties: {
39
+ className: ['sd-heading-anchor'],
40
+ ariaHidden: 'true'
41
+ },
42
+ content: {
43
+ type: 'text',
44
+ value: '#'
45
+ }
46
+ })
47
+ .use(rehypeKatex);
48
+ for (const plugin of options.rehypePlugins ?? []) {
49
+ processor.use(plugin);
50
+ }
51
+ const file = await processor
52
+ .use(rehypeCodeBlocks, codeBlocks)
53
+ .use(rehypeStringify, { allowDangerousHtml: true })
54
+ .process(markdown);
55
+ return {
56
+ html: String(file),
57
+ plainText: markdownAstToPlainText(markdown),
58
+ headings: extracted.headings,
59
+ codeBlocks,
60
+ ...(extracted.title ? { title: extracted.title } : {})
61
+ };
62
+ }
63
+ export { createDiffRows, createDiffSplitRows, extractCodeBlocks, markdownToPlainText };
@@ -0,0 +1,5 @@
1
+ import type { SvedocsCodeBlock, SvedocsDiffRow, SvedocsDiffSplitRow } from '../core/types.js';
2
+ export declare function createDiffRows(raw: string): SvedocsDiffRow[];
3
+ export declare function createDiffSplitRows(rows: SvedocsDiffRow[]): SvedocsDiffSplitRow[];
4
+ export declare function renderSplitDiffHtml(block: SvedocsCodeBlock): string;
5
+ //# 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;AAG9F,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,GAAG,MAAM,CAenE"}