@terrafirmagreg-team/kit 0.0.0-stage → 0.1.0

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 (78) hide show
  1. package/package.json +68 -3
  2. package/src/components/blocks/nav-title.tsx +65 -0
  3. package/src/components/docs-image.tsx +49 -0
  4. package/src/components/outline/dropdown.tsx +67 -0
  5. package/src/components/outline/index.ts +10 -0
  6. package/src/components/outline/list.tsx +120 -0
  7. package/src/components/outline/outline.tsx +49 -0
  8. package/src/components/outline/popover.tsx +76 -0
  9. package/src/components/outline/types.ts +29 -0
  10. package/src/components/page-actions.tsx +201 -0
  11. package/src/components/relative-link.tsx +18 -0
  12. package/src/components/search/dialog.tsx +145 -0
  13. package/src/components/toc/base.tsx +65 -0
  14. package/src/components/toc/block.tsx +111 -0
  15. package/src/components/toc/clerk.tsx +265 -0
  16. package/src/components/toc/default.tsx +333 -0
  17. package/src/components/version-menu.tsx +128 -0
  18. package/src/components/views/dataset.tsx +63 -0
  19. package/src/components/views/section.tsx +108 -0
  20. package/src/components/workspace/content.tsx +53 -0
  21. package/src/components/workspace/index.ts +12 -0
  22. package/src/components/workspace/pagination.tsx +73 -0
  23. package/src/components/workspace/workspace.tsx +148 -0
  24. package/src/hooks/toc.ts +9 -0
  25. package/src/hooks/use-catalog.ts +11 -0
  26. package/src/hooks/use-current-dataset.ts +14 -0
  27. package/src/hooks/use-dataset-accent.ts +13 -0
  28. package/src/hooks/use-nav-options.ts +84 -0
  29. package/src/hooks/use-version-pref.ts +30 -0
  30. package/src/lib/breadcrumb.ts +78 -0
  31. package/src/lib/config.ts +109 -0
  32. package/src/lib/dataset-links.ts +30 -0
  33. package/src/lib/datasets.ts +211 -0
  34. package/src/lib/landing.ts +46 -0
  35. package/src/lib/layout.ts +15 -0
  36. package/src/lib/legacy.ts +18 -0
  37. package/src/lib/location.ts +63 -0
  38. package/src/lib/markdown/dom.ts +90 -0
  39. package/src/lib/markdown/index.ts +13 -0
  40. package/src/lib/markdown/providers.ts +25 -0
  41. package/src/lib/mdx/accordions.ts +93 -0
  42. package/src/lib/mdx/banner.ts +52 -0
  43. package/src/lib/mdx/directive-utils.ts +125 -0
  44. package/src/lib/mdx/directives.ts +141 -0
  45. package/src/lib/mdx/game-export.ts +44 -0
  46. package/src/lib/mdx/html-style.ts +135 -0
  47. package/src/lib/mdx/preview.ts +252 -0
  48. package/src/lib/mdx/references.ts +56 -0
  49. package/src/lib/mdx/tabs.ts +80 -0
  50. package/src/lib/mdx-components.tsx +139 -0
  51. package/src/lib/order.ts +88 -0
  52. package/src/lib/pack-assets.ts +45 -0
  53. package/src/lib/page.ts +108 -0
  54. package/src/lib/pin-tree.ts +35 -0
  55. package/src/lib/preview/index.ts +8 -0
  56. package/src/lib/preview/lookup.ts +48 -0
  57. package/src/lib/preview/og.tsx +115 -0
  58. package/src/lib/preview/resolvers.ts +98 -0
  59. package/src/lib/search/config.ts +13 -0
  60. package/src/lib/search/filters.ts +22 -0
  61. package/src/lib/search/index.ts +19 -0
  62. package/src/lib/search/indexes.ts +43 -0
  63. package/src/lib/search/merge.ts +22 -0
  64. package/src/lib/search/server.ts +18 -0
  65. package/src/lib/search/sources.ts +19 -0
  66. package/src/lib/search/structured.ts +23 -0
  67. package/src/lib/section/schema.ts +36 -0
  68. package/src/lib/section/source.ts +40 -0
  69. package/src/lib/sources.ts +21 -0
  70. package/src/lib/tree.ts +60 -0
  71. package/src/lib/urls.ts +16 -0
  72. package/src/locales/en_us.json +10 -0
  73. package/src/locales/ru_ru.json +10 -0
  74. package/src/locales.ts +5 -0
  75. package/src/types/index.ts +83 -0
  76. package/src/types/mdx.ts +55 -0
  77. package/src/types/turndown-plugin-gfm.d.ts +9 -0
  78. package/README.md +0 -3
@@ -0,0 +1,135 @@
1
+ import type { MdastNode } from './directive-utils.ts';
2
+
3
+ type NodeWithValue = MdastNode & { value: string };
4
+ type NodeWithChildren = MdastNode & { children: MdastNode[] };
5
+
6
+ function objectToCss(body: string): string | undefined {
7
+ const entries: string[] = [];
8
+ const re = /(\w+)\s*:\s*['"]([^'"]*)['"]/g;
9
+ let m: RegExpExecArray | null;
10
+ while ((m = re.exec(body)) !== null) entries.push(`${m[1]}: ${m[2]}`);
11
+ return entries.length ? entries.join('; ') : undefined;
12
+ }
13
+
14
+ const JSX_ATTR = /(\w[\w-]*)=\{\{([\s\S]*?)\}\}/g;
15
+
16
+ function rewriteAttrs(html: string): string {
17
+ return html.replace(JSX_ATTR, (all, attr: string, body: string) => {
18
+ if (attr !== 'style') return all;
19
+ const css = objectToCss(body);
20
+ return css ? `style="${css}"` : all;
21
+ });
22
+ }
23
+
24
+ const OPEN_TAG = /<([a-zA-Z][\w-]*)((?:[^>"']|"[^"]*"|'[^']*'|\{\{[\s\S]*?\}\})*?)>/;
25
+
26
+ function stylesFromTag(tag: string): string | undefined {
27
+ const m = /style=\{\{([\s\S]*?)\}\}/.exec(tag);
28
+ return m ? objectToCss(m[1]!) : undefined;
29
+ }
30
+
31
+ function elementNode(
32
+ tag: string,
33
+ hName: string,
34
+ children: MdastNode[],
35
+ ): MdastNode {
36
+ const style = stylesFromTag(tag);
37
+ return {
38
+ type: 'emphasis',
39
+ children,
40
+ data: {
41
+ hName,
42
+ ...(style ? { hProperties: { style } } : {}),
43
+ },
44
+ } as MdastNode;
45
+ }
46
+
47
+ function textNode(value: string): MdastNode {
48
+ return { type: 'text', value } as MdastNode;
49
+ }
50
+
51
+ export function remarkHtmlStyle() {
52
+ return (tree: MdastNode) => {
53
+ const visitChildren = (parent: NodeWithChildren) => {
54
+ const kids = parent.children;
55
+ for (let i = 0; i < kids.length; i++) {
56
+ const child = kids[i]!;
57
+ if (child.type === 'html' && typeof child.value === 'string') {
58
+ (child as NodeWithValue).value = rewriteAttrs(child.value);
59
+ } else if (
60
+ child.type === 'text' &&
61
+ typeof child.value === 'string' &&
62
+ child.value.includes('={{')
63
+ ) {
64
+ if (fuseJsxStyleTags(kids, i)) i--;
65
+ } else if (child.children) {
66
+ visitChildren(child as NodeWithChildren);
67
+ }
68
+ }
69
+ };
70
+ visitChildren(tree as NodeWithChildren);
71
+ };
72
+ }
73
+
74
+ function fuseJsxStyleTags(kids: MdastNode[], i: number): boolean {
75
+ const text = kids[i] as NodeWithValue;
76
+ let open: RegExpExecArray | null;
77
+ const re = new RegExp(OPEN_TAG.source, 'g');
78
+ do {
79
+ open = re.exec(text.value);
80
+ } while (open && !open[2]?.includes('={{'));
81
+ if (!open) return false;
82
+
83
+ const [openTag, tagName] = open;
84
+ const prefix = text.value.slice(0, open.index);
85
+ const rest = text.value.slice(open.index + openTag.length);
86
+
87
+ const closeSelf = new RegExp(`</${tagName}\\s*>`).exec(rest);
88
+ if (closeSelf) {
89
+ const end = closeSelf.index + closeSelf[0].length;
90
+ kids.splice(
91
+ i,
92
+ 1,
93
+ ...compact([
94
+ prefix ? textNode(prefix) : undefined,
95
+ elementNode(openTag, tagName, [textNode(rest.slice(0, closeSelf.index))]),
96
+ rest.slice(end) ? textNode(rest.slice(end)) : undefined,
97
+ ]),
98
+ );
99
+ return true;
100
+ }
101
+
102
+ for (let j = i + 1; j < kids.length; j++) {
103
+ const sib = kids[j]!;
104
+ if (
105
+ sib.type === 'html' &&
106
+ typeof sib.value === 'string' &&
107
+ new RegExp(`^</${tagName}\\s*>$`).test(sib.value.trim())
108
+ ) {
109
+ const inner = rest ? [textNode(rest)] : [];
110
+ kids.splice(
111
+ i,
112
+ j - i + 1,
113
+ ...compact([
114
+ prefix ? textNode(prefix) : undefined,
115
+ elementNode(openTag, tagName, [...inner, ...kids.slice(i + 1, j)]),
116
+ ]),
117
+ );
118
+ return true;
119
+ }
120
+ }
121
+
122
+ kids.splice(
123
+ i,
124
+ 1,
125
+ ...compact([
126
+ prefix ? textNode(prefix) : undefined,
127
+ elementNode(openTag, tagName, rest ? [textNode(rest)] : []),
128
+ ]),
129
+ );
130
+ return true;
131
+ }
132
+
133
+ function compact(nodes: (MdastNode | undefined)[]): MdastNode[] {
134
+ return nodes.filter((n): n is MdastNode => n !== undefined);
135
+ }
@@ -0,0 +1,252 @@
1
+ import { createRequire } from 'node:module';
2
+ import { remarkDirectives } from './directives.ts';
3
+ import {
4
+ remarkCodeTab,
5
+ remarkHeading,
6
+ remarkImage,
7
+ remarkMdxFiles,
8
+ remarkMdxMermaid,
9
+ remarkNpm,
10
+ remarkSteps,
11
+ } from 'fumadocs-core/mdx-plugins';
12
+ import remarkDirective from 'remark-directive';
13
+ import remarkGfm from 'remark-gfm';
14
+ import remarkMath from 'remark-math';
15
+ import remarkParse from 'remark-parse';
16
+ import { unified, type Plugin } from 'unified';
17
+ import {
18
+ contentChildren,
19
+ extractDirectiveLabel,
20
+ jsxAttr,
21
+ type DirectiveNode,
22
+ type JsxElement,
23
+ type MdastNode,
24
+ } from './directive-utils.ts';
25
+
26
+ const require = createRequire(import.meta.url);
27
+
28
+ type VFileLike = {
29
+ path?: string;
30
+ cwd?: string;
31
+ value?: unknown;
32
+ };
33
+
34
+ type Positioned = {
35
+ position?: {
36
+ start?: { offset?: number };
37
+ end?: { offset?: number };
38
+ };
39
+ };
40
+
41
+ const previewSeq = new WeakMap<object, number>();
42
+
43
+ function nextPreviewId(file: VFileLike): number {
44
+ const key = file as object;
45
+ const n = (previewSeq.get(key) ?? 0) + 1;
46
+ previewSeq.set(key, n);
47
+ return n;
48
+ }
49
+
50
+ function slugify(text: string): string {
51
+ return (
52
+ text
53
+ .toLowerCase()
54
+ .replace(/[^\p{L}\p{N}]+/gu, '-')
55
+ .replace(/^-+|-+$/g, '') || 'section'
56
+ );
57
+ }
58
+
59
+ function walk(node: MdastNode, visit: (n: MdastNode) => void): void {
60
+ visit(node);
61
+ for (const child of node.children ?? []) walk(child, visit);
62
+ }
63
+
64
+ function markHeadingNoToc(heading: MdastNode): void {
65
+ const kids = heading.children ?? [];
66
+ const last = kids[kids.length - 1];
67
+ if (last?.type === 'text' && typeof last.value === 'string') {
68
+ if (!last.value.includes('[!toc]')) {
69
+ last.value = `${last.value.replace(/\s+$/, '')} [!toc]`;
70
+ }
71
+ return;
72
+ }
73
+ kids.push({ type: 'text', value: ' [!toc]' });
74
+ heading.children = kids;
75
+ }
76
+
77
+ function uniquifyHeadingIds(tree: MdastNode): void {
78
+ const used = new Set<string>();
79
+ walk(tree, (node) => {
80
+ if (node.type !== 'heading') return;
81
+ const props = (node.data?.hProperties ?? {}) as { id?: string };
82
+ node.data ??= {};
83
+ node.data.hProperties = props;
84
+ if (typeof props.id !== 'string' || props.id.length === 0) return;
85
+
86
+ let id = props.id;
87
+ if (!used.has(id)) {
88
+ used.add(id);
89
+ return;
90
+ }
91
+ let n = 1;
92
+ while (used.has(`${id}-${n}`)) n += 1;
93
+ props.id = `${id}-${n}`;
94
+ used.add(props.id);
95
+ });
96
+ }
97
+
98
+ export function remarkPreview() {
99
+ return async (tree: MdastNode, file: VFileLike) => {
100
+ previewSeq.set(file as object, 0);
101
+ await expandPreviews(tree, file);
102
+ uniquifyHeadingIds(tree);
103
+ };
104
+ }
105
+
106
+ async function expandPreviews(parent: MdastNode, file: VFileLike): Promise<void> {
107
+ const children = parent.children;
108
+ if (!children) return;
109
+
110
+ for (let i = 0; i < children.length; i++) {
111
+ const child = children[i]!;
112
+ if (child.type === 'containerDirective' && child.name === 'preview') {
113
+ const expanded = await expandPreview(child as DirectiveNode, file);
114
+ children.splice(i, 1, ...expanded);
115
+ i += expanded.length - 1;
116
+ continue;
117
+ }
118
+ await expandPreviews(child, file);
119
+ }
120
+ }
121
+
122
+ function isMdEscapeFence(node: MdastNode): boolean {
123
+ if (node.type !== 'code' || typeof node.value !== 'string') return false;
124
+ const lang = typeof node.lang === 'string' ? node.lang.toLowerCase() : '';
125
+ return lang === 'md' || lang === 'markdown';
126
+ }
127
+
128
+ function fileText(file: VFileLike): string {
129
+ if (typeof file.value === 'string') return file.value;
130
+ if (file.value == null) return '';
131
+ if (Buffer.isBuffer(file.value)) return file.value.toString('utf8');
132
+ return String(file.value);
133
+ }
134
+
135
+ function offsetOf(node: MdastNode, side: 'start' | 'end'): number | undefined {
136
+ const pos = (node as Positioned).position?.[side]?.offset;
137
+ return typeof pos === 'number' ? pos : undefined;
138
+ }
139
+
140
+ function sourceFromChildren(
141
+ kids: MdastNode[],
142
+ file: VFileLike,
143
+ ): string | undefined {
144
+ if (kids.length === 0) return undefined;
145
+
146
+ if (kids.length === 1 && isMdEscapeFence(kids[0]!)) {
147
+ return kids[0]!.value as string;
148
+ }
149
+
150
+ const raw = fileText(file);
151
+ const start = offsetOf(kids[0]!, 'start');
152
+ const end = offsetOf(kids[kids.length - 1]!, 'end');
153
+ if (raw && start != null && end != null && end >= start) {
154
+ return raw.slice(start, end).replace(/\r\n/g, '\n').trimEnd();
155
+ }
156
+
157
+ return undefined;
158
+ }
159
+
160
+ async function expandPreview(
161
+ node: DirectiveNode,
162
+ file: VFileLike,
163
+ ): Promise<MdastNode[]> {
164
+ const kids = contentChildren(node);
165
+ const source = sourceFromChildren(kids, file);
166
+ if (source === undefined) return kids;
167
+
168
+ const label = extractDirectiveLabel(node);
169
+ const previewNo = nextPreviewId(file);
170
+
171
+ const input: JsxElement = {
172
+ type: 'mdxJsxFlowElement',
173
+ name: 'Input',
174
+ attributes: label ? [jsxAttr('label', label)] : [],
175
+ children: [
176
+ {
177
+ type: 'code',
178
+ lang: 'md',
179
+ meta: 'title="example.md" lineNumbers',
180
+ value: source,
181
+ },
182
+ ],
183
+ };
184
+
185
+ const parsed = await processOutputBody(source, file, previewNo);
186
+
187
+ const output: JsxElement = {
188
+ type: 'mdxJsxFlowElement',
189
+ name: 'Output',
190
+ attributes: [],
191
+ children: parsed.children ?? [],
192
+ };
193
+
194
+ const preview: JsxElement = {
195
+ type: 'mdxJsxFlowElement',
196
+ name: 'Preview',
197
+ attributes: [],
198
+ children: [input as unknown as MdastNode, output as unknown as MdastNode],
199
+ };
200
+
201
+ return [preview as unknown as MdastNode];
202
+ }
203
+
204
+ async function processOutputBody(
205
+ source: string,
206
+ file: VFileLike,
207
+ previewNo: number,
208
+ ): Promise<MdastNode> {
209
+
210
+ const { remarkInclude } = require('fumadocs-mdx/config') as {
211
+ remarkInclude: Plugin;
212
+ };
213
+
214
+ const used = new Map<string, number>();
215
+
216
+ const processor = unified()
217
+ .use(remarkParse)
218
+ .use(remarkGfm)
219
+ .use(remarkMath)
220
+ .use(remarkDirective)
221
+ .use(remarkDirectives)
222
+ .use(remarkInclude)
223
+ .use(remarkImage, { publicDir: 'public', useImport: false })
224
+ .use(remarkNpm)
225
+ .use(remarkCodeTab)
226
+ .use(remarkMdxFiles)
227
+ .use(remarkMdxMermaid)
228
+ .use(remarkSteps)
229
+ .use(remarkHeading, {
230
+ generateToc: false,
231
+ customId: false,
232
+ slug: (_root, _heading, text: string) => {
233
+ const base = slugify(text);
234
+ const n = used.get(base) ?? 0;
235
+ used.set(base, n + 1);
236
+ const local = n === 0 ? base : `${base}-${n}`;
237
+ return `preview-${previewNo}-${local}`;
238
+ },
239
+ });
240
+
241
+ const tree = processor.parse({ value: source, path: file.path });
242
+ const result = (await processor.run(
243
+ tree,
244
+ file as never,
245
+ )) as unknown as MdastNode;
246
+
247
+ walk(result, (node) => {
248
+ if (node.type === 'heading') markHeadingNoToc(node);
249
+ });
250
+
251
+ return result;
252
+ }
@@ -0,0 +1,56 @@
1
+ type MdastNode = {
2
+ type: string;
3
+ value?: string;
4
+ url?: string;
5
+ children?: MdastNode[];
6
+ };
7
+
8
+ const ISSUE_REF = /^#\d+$/;
9
+ const USER_REF = /^@[a-zA-Z\d](?:[a-zA-Z\d-]{0,37}[a-zA-Z\d])?$/;
10
+ const AUTO_REF = /(\B#\d+\b|\B@[a-zA-Z\d](?:[a-zA-Z\d-]{0,37}[a-zA-Z\d])?)/g;
11
+ const SKIP = new Set([
12
+ 'link',
13
+ 'linkReference',
14
+ 'image',
15
+ 'imageReference',
16
+ 'code',
17
+ 'inlineCode',
18
+ 'html',
19
+ ]);
20
+
21
+ const CHANGELOG_PATH = /[/\\]changelog[/\\]([^/\\]+)[/\\]/;
22
+
23
+ export function remarkChangelogReferences(options: { datasetConfig?: Record<string, { repo?: string }> } = {}) {
24
+ const datasetConfig = options.datasetConfig ?? {};
25
+ return (tree: MdastNode, file: { path?: string }) => {
26
+ const pack = CHANGELOG_PATH.exec(file.path ?? '')?.[1];
27
+ const repo = pack ? datasetConfig[pack]?.repo : undefined;
28
+ if (!repo) return;
29
+ const repoUrl = `https://github.com/${repo}`;
30
+ const visit = (node: MdastNode) => {
31
+ if (SKIP.has(node.type) || !node.children) return;
32
+ node.children = node.children.flatMap((child): MdastNode[] => {
33
+ if (child.type !== 'text') {
34
+ visit(child);
35
+ return [child];
36
+ }
37
+ return (child.value ?? '').split(AUTO_REF).map((part) =>
38
+ ISSUE_REF.test(part)
39
+ ? {
40
+ type: 'link',
41
+ url: `${repoUrl}/issues/${part.slice(1)}`,
42
+ children: [{ type: 'text', value: part }],
43
+ }
44
+ : USER_REF.test(part)
45
+ ? {
46
+ type: 'link',
47
+ url: `https://github.com/${part.slice(1)}`,
48
+ children: [{ type: 'text', value: part }],
49
+ }
50
+ : { type: 'text', value: part },
51
+ );
52
+ });
53
+ };
54
+ visit(tree);
55
+ };
56
+ }
@@ -0,0 +1,80 @@
1
+ import {
2
+ estreeStringArray,
3
+ extractLeafLabel,
4
+ jsxExpression,
5
+ toJsxAttributes,
6
+ walkContainers,
7
+ type DirectiveNode,
8
+ type JsxElement,
9
+ type MdastNode,
10
+ } from './directive-utils.ts';
11
+
12
+
13
+ export function remarkTabs() {
14
+ return (tree: MdastNode) => {
15
+ walkContainers(tree, (directive) => {
16
+ if (directive.name !== 'tabs') return;
17
+ toTabs(directive);
18
+ return false;
19
+ });
20
+ };
21
+ }
22
+
23
+
24
+ function escapeValue(value: string): string {
25
+ return value.toLowerCase().replace(/\s/, '-');
26
+ }
27
+
28
+
29
+ function toTabs(node: DirectiveNode): void {
30
+ const items: string[] = [];
31
+ const tabs: JsxElement[] = [];
32
+ let current: JsxElement | undefined;
33
+
34
+ for (const item of node.children ?? []) {
35
+ if (item.type === 'leafDirective' && (item as { name?: string }).name === 'tab') {
36
+ const label = extractLeafLabel(item);
37
+ items.push(label);
38
+ current = {
39
+ type: 'mdxJsxFlowElement',
40
+ name: 'Tab',
41
+ attributes: [
42
+ {
43
+ type: 'mdxJsxAttribute',
44
+ name: 'value',
45
+ value: escapeValue(label),
46
+ },
47
+ ],
48
+ children: [],
49
+ };
50
+ tabs.push(current);
51
+ continue;
52
+ }
53
+
54
+ current?.children.push(item);
55
+ }
56
+
57
+ const attributes = toJsxAttributes(node).map((attribute) =>
58
+ attribute.name === 'default'
59
+ ? {
60
+ type: 'mdxJsxAttribute' as const,
61
+ name: 'defaultValue',
62
+ value: escapeValue(String(attribute.value)),
63
+ }
64
+ : attribute,
65
+ );
66
+ attributes.unshift({
67
+ type: 'mdxJsxAttribute',
68
+ name: 'items',
69
+ value: jsxExpression(estreeStringArray(items)),
70
+ });
71
+
72
+ Object.assign(node, {
73
+ type: 'mdxJsxFlowElement',
74
+ name: 'Tabs',
75
+ attributes,
76
+ children: tabs,
77
+ });
78
+ }
79
+
80
+
@@ -0,0 +1,139 @@
1
+ import {
2
+ Tab,
3
+ Tabs,
4
+ TabsContent,
5
+ TabsList,
6
+ TabsTrigger,
7
+ } from '@terrafirmagreg-team/ui/components/mdx/tabs';
8
+ import {
9
+ Accordion,
10
+ Accordions,
11
+ } from '@terrafirmagreg-team/ui/components/mdx/accordion';
12
+ import { Step, Steps } from '@terrafirmagreg-team/ui/components/mdx/steps';
13
+ import {
14
+ File,
15
+ Folder,
16
+ Files,
17
+ } from '@terrafirmagreg-team/ui/components/mdx/files';
18
+ import { ImageZoom } from '@terrafirmagreg-team/ui/components/mdx/image-zoom';
19
+ import { Banner } from '@terrafirmagreg-team/ui/components/mdx/banner';
20
+ import { TypeTable } from '@terrafirmagreg-team/ui/components/mdx/type-table';
21
+ import { Card, Cards } from '@terrafirmagreg-team/ui/components/mdx/card';
22
+ import { Table } from '@terrafirmagreg-team/ui/components/mdx/table';
23
+ import {
24
+ CalloutDescription,
25
+ CalloutTitle,
26
+ } from '@terrafirmagreg-team/ui/components/mdx/callout';
27
+ import {
28
+ CodeBlock,
29
+ CodeBlockTab,
30
+ CodeBlockTabs,
31
+ CodeBlockTabsList,
32
+ CodeBlockTabsTrigger,
33
+ Pre,
34
+ } from '@terrafirmagreg-team/ui/components/mdx/codeblock';
35
+ import { Heading } from '@terrafirmagreg-team/ui/components/blocks/page/heading';
36
+ import * as Twoslash from 'fumadocs-twoslash/ui';
37
+ import { Mermaid } from '@terrafirmagreg-team/ui/components/mdx/mermaid';
38
+ import { Callout, CalloutContainer } from '@terrafirmagreg-team/ui/components/mdx/callout';
39
+ import { Input, Output, Preview } from '@terrafirmagreg-team/ui/components/mdx/preview';
40
+ import { DocsImage } from '@terrafirmagreg-team/kit/components/docs-image';
41
+ import { Multiblock } from '@terrafirmagreg-team/ui/components/mdx/multiblock';
42
+ import { GradientText } from '@terrafirmagreg-team/ui/components/mdx/gradient-text';
43
+ import { GlowHeader } from '@terrafirmagreg-team/ui/components/mdx/glow-header';
44
+ import { LinkPreview } from '@terrafirmagreg-team/ui/components/blocks/link/link-preview';
45
+ import type { MDXComponents } from 'mdx/types';
46
+ import type { ComponentProps, HTMLAttributes } from 'react';
47
+
48
+ const extras: MDXComponents = {};
49
+
50
+ export function registerMdxComponents(map: MDXComponents): void {
51
+ Object.assign(extras, map);
52
+ }
53
+
54
+ export function getMDXComponents(components?: MDXComponents) {
55
+ return {
56
+ ...extras,
57
+ CodeBlockTab,
58
+ CodeBlockTabs,
59
+ CodeBlockTabsList,
60
+ CodeBlockTabsTrigger,
61
+ Tab,
62
+ Tabs,
63
+ TabsContent,
64
+ TabsList,
65
+ TabsTrigger,
66
+ ...Twoslash,
67
+ Accordion,
68
+ Accordions,
69
+ Step,
70
+ Steps,
71
+ File,
72
+ Folder,
73
+ Files,
74
+ Mermaid,
75
+ Banner,
76
+ TypeTable,
77
+ Card,
78
+ Cards,
79
+ Callout,
80
+ CalloutContainer,
81
+ CalloutTitle,
82
+ CalloutDescription,
83
+ Preview,
84
+ Input,
85
+ Output,
86
+ DocsImage,
87
+ Multiblock,
88
+ GradientText,
89
+ GlowHeader,
90
+ a: LinkPreview,
91
+ pre: (props: HTMLAttributes<HTMLPreElement>) => (
92
+ <CodeBlock {...props}>
93
+ <Pre>{props.children}</Pre>
94
+ </CodeBlock>
95
+ ),
96
+ h1: (props: HTMLAttributes<HTMLHeadingElement>) => (
97
+ <Heading as="h1" {...props} />
98
+ ),
99
+ h2: (props: HTMLAttributes<HTMLHeadingElement>) => (
100
+ <Heading as="h2" {...props} />
101
+ ),
102
+ h3: (props: HTMLAttributes<HTMLHeadingElement>) => (
103
+ <Heading as="h3" {...props} />
104
+ ),
105
+ h4: (props: HTMLAttributes<HTMLHeadingElement>) => (
106
+ <Heading as="h4" {...props} />
107
+ ),
108
+ h5: (props: HTMLAttributes<HTMLHeadingElement>) => (
109
+ <Heading as="h5" {...props} />
110
+ ),
111
+ h6: (props: HTMLAttributes<HTMLHeadingElement>) => (
112
+ <Heading as="h6" {...props} />
113
+ ),
114
+ table: Table,
115
+ img: (props: ComponentProps<'img'>) => {
116
+ if (typeof props.src !== 'string' || /^https?:\/\//i.test(props.src)) {
117
+ // eslint-disable-next-line @next/next/no-img-element
118
+ return <img {...props} alt={props.alt ?? ''} />;
119
+ }
120
+ const width = Number(props.width) || undefined;
121
+ const height = Number(props.height) || undefined;
122
+ return (
123
+ <ImageZoom
124
+ src={props.src}
125
+ alt={props.alt ?? ''}
126
+ width={width ?? 960}
127
+ height={height ?? 540}
128
+ sizes={props.sizes as string | undefined}
129
+ className={props.className}
130
+ />
131
+ );
132
+ },
133
+ ...components,
134
+ } as MDXComponents;
135
+ }
136
+
137
+ declare global {
138
+ type MDXProvidedComponents = ReturnType<typeof getMDXComponents>;
139
+ }