@xyd-js/content 0.0.0-build
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/CHANGELOG.md +14 -0
- package/ISSUES.md +1 -0
- package/LICENSE +21 -0
- package/README.md +3 -0
- package/TODO.md +2 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.js +1625 -0
- package/dist/index.js.map +1 -0
- package/dist/md.d.ts +72 -0
- package/dist/md.js +23508 -0
- package/dist/md.js.map +1 -0
- package/dist/mdToc-NBBxMJ4l.d.ts +12 -0
- package/dist/vite.d.ts +1066 -0
- package/dist/vite.js +20156 -0
- package/dist/vite.js.map +1 -0
- package/package.json +67 -0
- package/packages/md/index.ts +25 -0
- package/packages/md/plugins/component-directives/index.ts +3 -0
- package/packages/md/plugins/component-directives/mdComponentDirective.ts +577 -0
- package/packages/md/plugins/component-directives/types.ts +1 -0
- package/packages/md/plugins/component-directives/utils.ts +27 -0
- package/packages/md/plugins/composer/__fixtures__/1.single-example/input.md +7 -0
- package/packages/md/plugins/composer/__fixtures__/1.single-example/output.json +63 -0
- package/packages/md/plugins/composer/__fixtures__/2.single-example-with-name/input.md +7 -0
- package/packages/md/plugins/composer/__fixtures__/2.single-example-with-name/output.json +63 -0
- package/packages/md/plugins/composer/__fixtures__/3.multiple-examples/input.md +15 -0
- package/packages/md/plugins/composer/__fixtures__/3.multiple-examples/output.json +122 -0
- package/packages/md/plugins/composer/__fixtures__/4.example-groups/input.md +23 -0
- package/packages/md/plugins/composer/__fixtures__/4.example-groups/output.json +184 -0
- package/packages/md/plugins/composer/__tests__/mdComposer.test.ts +41 -0
- package/packages/md/plugins/composer/__tests__/testHelpers.ts +48 -0
- package/packages/md/plugins/composer/index.ts +1 -0
- package/packages/md/plugins/composer/mdComposer.ts +146 -0
- package/packages/md/plugins/developer-writing/index.ts +3 -0
- package/packages/md/plugins/developer-writing/mdCodeRehype.ts +81 -0
- package/packages/md/plugins/functions/__fixtures__/external.ts +4 -0
- package/packages/md/plugins/functions/__fixtures__/test-include.md +31 -0
- package/packages/md/plugins/functions/__fixtures__/test.js +11 -0
- package/packages/md/plugins/functions/__fixtures__/test.py +9 -0
- package/packages/md/plugins/functions/__fixtures__/test.ts +18 -0
- package/packages/md/plugins/functions/__tests__/mdFunctionImportCode.test.ts +314 -0
- package/packages/md/plugins/functions/__tests__/mdFunctionInclude.test.ts +44 -0
- package/packages/md/plugins/functions/__tests__/parseFunctionCall.test.ts +70 -0
- package/packages/md/plugins/functions/__tests__/testHelpers.ts +95 -0
- package/packages/md/plugins/functions/index.ts +15 -0
- package/packages/md/plugins/functions/mdFunctionChangelog.ts +135 -0
- package/packages/md/plugins/functions/mdFunctionImportCode.ts +92 -0
- package/packages/md/plugins/functions/mdFunctionInclude.ts +119 -0
- package/packages/md/plugins/functions/mdFunctionUniform.ts +79 -0
- package/packages/md/plugins/functions/types.ts +9 -0
- package/packages/md/plugins/functions/uniformProcessor.ts +349 -0
- package/packages/md/plugins/functions/utils.ts +457 -0
- package/packages/md/plugins/index.ts +125 -0
- package/packages/md/plugins/mdCode.ts +16 -0
- package/packages/md/plugins/mdHeadingId.ts +47 -0
- package/packages/md/plugins/mdImage.test.ts +59 -0
- package/packages/md/plugins/mdImage.ts +55 -0
- package/packages/md/plugins/mdImageRehype.ts +13 -0
- package/packages/md/plugins/mdPage.ts +35 -0
- package/packages/md/plugins/mdThemeSettings.ts +34 -0
- package/packages/md/plugins/mdToc.ts +229 -0
- package/packages/md/plugins/meta/index.ts +1 -0
- package/packages/md/plugins/meta/mdMeta.ts +198 -0
- package/packages/md/plugins/output-variables/__fixtures__/1.simple/input.md +22 -0
- package/packages/md/plugins/output-variables/__fixtures__/1.simple/output.json +191 -0
- package/packages/md/plugins/output-variables/__fixtures__/2.multiple-vars/input.md +21 -0
- package/packages/md/plugins/output-variables/__fixtures__/2.multiple-vars/output.json +127 -0
- package/packages/md/plugins/output-variables/__tests__/index.test.ts +28 -0
- package/packages/md/plugins/output-variables/__tests__/testHelpers.ts +36 -0
- package/packages/md/plugins/output-variables/index.ts +1 -0
- package/packages/md/plugins/output-variables/lib/const.ts +4 -0
- package/packages/md/plugins/output-variables/lib/factoryAttributes.ts +350 -0
- package/packages/md/plugins/output-variables/lib/factoryLabel.ts +135 -0
- package/packages/md/plugins/output-variables/lib/factoryName.ts +59 -0
- package/packages/md/plugins/output-variables/lib/index.ts +21 -0
- package/packages/md/plugins/output-variables/lib/outputVarsContainer.ts +328 -0
- package/packages/md/plugins/output-variables/lib/util.ts +494 -0
- package/packages/md/plugins/output-variables/remarkOutputVars.ts +22 -0
- package/packages/md/plugins/recmaOverrideComponents.ts +74 -0
- package/packages/md/plugins/rehypeHeading.ts +58 -0
- package/packages/md/plugins/types.ts +15 -0
- package/packages/md/plugins/utils/componentLike.ts +76 -0
- package/packages/md/plugins/utils/index.ts +2 -0
- package/packages/md/plugins/utils/injectCodeMeta.ts +59 -0
- package/packages/md/plugins/utils/mdParameters.test.ts +114 -0
- package/packages/md/plugins/utils/mdParameters.ts +249 -0
- package/packages/md/plugins/utils/mdastTypes.ts +42 -0
- package/packages/md/search/index.ts +257 -0
- package/packages/md/search/types.ts +36 -0
- package/packages/vite/index.ts +20 -0
- package/src/fs.ts +81 -0
- package/src/index.ts +7 -0
- package/src/navigation.ts +147 -0
- package/src/types.ts +8 -0
- package/tsconfig.json +49 -0
- package/tsup.config.ts +32 -0
- package/vitest.config.ts +17 -0
package/package.json
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@xyd-js/content",
|
|
3
|
+
"version": "0.0.0-build+6952c2c-20250813013245",
|
|
4
|
+
"description": "",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"exports": {
|
|
8
|
+
"./package.json": "./package.json",
|
|
9
|
+
".": "./dist/index.js",
|
|
10
|
+
"./vite": "./dist/vite.js",
|
|
11
|
+
"./md": "./dist/md.js"
|
|
12
|
+
},
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"@mapbox/hast-util-to-jsx": "^2.1.0",
|
|
15
|
+
"@mdx-js/mdx": "^3.1.0",
|
|
16
|
+
"@mdx-js/rollup": "^3.0.1",
|
|
17
|
+
"acorn-jsx": "^5.3.2",
|
|
18
|
+
"codehike": "^1.0.4",
|
|
19
|
+
"estree-util-is-identifier-name": "^3.0.0",
|
|
20
|
+
"estree-util-value-to-estree": "^3.1.2",
|
|
21
|
+
"github-slugger": "^2.0.0",
|
|
22
|
+
"gray-matter": "^4.0.3",
|
|
23
|
+
"mdast": "^3.0.0",
|
|
24
|
+
"mdast-util-mdx": "^3.0.0",
|
|
25
|
+
"mdast-util-mdx-jsx": "^3.2.0",
|
|
26
|
+
"mdast-util-to-string": "^4.0.0",
|
|
27
|
+
"micromark-extension-mdxjs": "^3.0.0",
|
|
28
|
+
"react-element-to-jsx-string": "^17.0.0",
|
|
29
|
+
"rehype-katex": "^7.0.1",
|
|
30
|
+
"rehype-raw": "^7.0.0",
|
|
31
|
+
"rehype-react": "^8.0.0",
|
|
32
|
+
"remark-directive": "^3.0.0",
|
|
33
|
+
"remark-frontmatter": "^5.0.0",
|
|
34
|
+
"remark-gfm": "^4.0.0",
|
|
35
|
+
"remark-math": "^6.0.0",
|
|
36
|
+
"remark-mdx-frontmatter": "^5.0.0",
|
|
37
|
+
"unified": "^11.0.5",
|
|
38
|
+
"unist-util-visit": "^5.0.0",
|
|
39
|
+
"vfile": "^6.0.3",
|
|
40
|
+
"vfile-matter": "^5.0.1",
|
|
41
|
+
"@xyd-js/context": "0.0.0-build+6952c2c-20250813013245",
|
|
42
|
+
"@xyd-js/core": "0.0.0-build+6952c2c-20250813013245",
|
|
43
|
+
"@xyd-js/gql": "0.0.0-build+6952c2c-20250813013245",
|
|
44
|
+
"@xyd-js/openapi": "0.0.0-build+6952c2c-20250813013245",
|
|
45
|
+
"@xyd-js/sources": "0.0.0-build+6952c2c-20250813013245"
|
|
46
|
+
},
|
|
47
|
+
"peerDependencies": {
|
|
48
|
+
"@xyd-js/components": "0.0.0-build+6952c2c-20250813013245"
|
|
49
|
+
},
|
|
50
|
+
"devDependencies": {
|
|
51
|
+
"@types/node": "^22.14.1",
|
|
52
|
+
"@vitest/coverage-v8": "^1.3.1",
|
|
53
|
+
"rimraf": "^3.0.2",
|
|
54
|
+
"tsup": "^8.3.0",
|
|
55
|
+
"typescript": "^4.5.5",
|
|
56
|
+
"vite": "^7.0.0",
|
|
57
|
+
"vitest": "^1.3.1"
|
|
58
|
+
},
|
|
59
|
+
"scripts": {
|
|
60
|
+
"clean": "rimraf build",
|
|
61
|
+
"prebuild": "pnpm clean",
|
|
62
|
+
"build": "tsup",
|
|
63
|
+
"watch": "tsup --watch",
|
|
64
|
+
"test": "vitest",
|
|
65
|
+
"test:watch": "vitest watch"
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { Settings } from "@xyd-js/core";
|
|
2
|
+
|
|
3
|
+
import { defaultRecmaPlugins, defaultRehypePlugins, defaultRemarkPlugins } from "./plugins"
|
|
4
|
+
import { RemarkMdxTocOptions } from "./plugins/mdToc";
|
|
5
|
+
|
|
6
|
+
export { RemarkMdxTocOptions, } from "./plugins/mdToc";
|
|
7
|
+
export { mapSettingsToDocSections } from "./search"
|
|
8
|
+
export type { DocSectionSchema } from "./search/types"
|
|
9
|
+
|
|
10
|
+
export async function markdownPlugins(
|
|
11
|
+
toc: RemarkMdxTocOptions, // TODO: unify this cuz it should come from core -global settings and toc options?
|
|
12
|
+
settings?: Settings
|
|
13
|
+
) {
|
|
14
|
+
const remarkPlugins = [...defaultRemarkPlugins(toc, settings)]
|
|
15
|
+
|
|
16
|
+
const rehypePlugins = [...(await defaultRehypePlugins(settings))]
|
|
17
|
+
|
|
18
|
+
const recmaPlugins = [...defaultRecmaPlugins(settings)]
|
|
19
|
+
|
|
20
|
+
return {
|
|
21
|
+
remarkPlugins,
|
|
22
|
+
rehypePlugins,
|
|
23
|
+
recmaPlugins,
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,577 @@
|
|
|
1
|
+
import { Plugin, unified } from "unified";
|
|
2
|
+
import remarkParse from "remark-parse";
|
|
3
|
+
import remarkMdx from "remark-mdx";
|
|
4
|
+
import { visit } from "unist-util-visit";
|
|
5
|
+
import { VFile } from "vfile";
|
|
6
|
+
import { Node as UnistNode } from "unist";
|
|
7
|
+
import { highlight } from "codehike/code"
|
|
8
|
+
|
|
9
|
+
import { Settings } from "@xyd-js/core";
|
|
10
|
+
import { uniformToMiniUniform } from "@xyd-js/sources/ts";
|
|
11
|
+
|
|
12
|
+
import { FunctionName } from "../functions/types";
|
|
13
|
+
import { MarkdownComponentDirectiveMap } from "./types";
|
|
14
|
+
import { functionMatch, parseFunctionCall } from "../functions/utils";
|
|
15
|
+
import { processUniformFunctionCall } from "../functions/uniformProcessor";
|
|
16
|
+
|
|
17
|
+
import { getComponentName } from "./utils";
|
|
18
|
+
import { Reference, TypeDocReferenceContext } from "@xyd-js/uniform";
|
|
19
|
+
import { mdParameters } from "../utils/mdParameters";
|
|
20
|
+
|
|
21
|
+
// TODO: in the future custom component: `this.registerComponent(MyComponent, "my-component")` ? but core should move to `symbolx`?
|
|
22
|
+
const supportedDirectives: MarkdownComponentDirectiveMap = {
|
|
23
|
+
details: true,
|
|
24
|
+
|
|
25
|
+
callout: true,
|
|
26
|
+
|
|
27
|
+
table: true,
|
|
28
|
+
|
|
29
|
+
subtitle: true,
|
|
30
|
+
|
|
31
|
+
steps: true,
|
|
32
|
+
|
|
33
|
+
"guide-card": "GuideCard",
|
|
34
|
+
|
|
35
|
+
"code-group": "DirectiveCodeGroup",
|
|
36
|
+
|
|
37
|
+
tabs: "Tabs",
|
|
38
|
+
|
|
39
|
+
atlas: true,
|
|
40
|
+
|
|
41
|
+
badge: true,
|
|
42
|
+
|
|
43
|
+
grid: "GridDecorator",
|
|
44
|
+
|
|
45
|
+
button: true,
|
|
46
|
+
|
|
47
|
+
update: true,
|
|
48
|
+
|
|
49
|
+
card: true,
|
|
50
|
+
|
|
51
|
+
feature: true,
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const supportedTextDirectives: MarkdownComponentDirectiveMap = {
|
|
55
|
+
icon: true,
|
|
56
|
+
br: true,
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const supportedLeafDirectives: MarkdownComponentDirectiveMap = {
|
|
60
|
+
atlas: true,
|
|
61
|
+
card: true,
|
|
62
|
+
"color-scheme-button": "ColorSchemeButton",
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const tableComponents: MarkdownComponentDirectiveMap = {
|
|
66
|
+
Table: true,
|
|
67
|
+
table: true
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const stepsComponents: MarkdownComponentDirectiveMap = {
|
|
71
|
+
Steps: true,
|
|
72
|
+
steps: true
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const codeComponents: MarkdownComponentDirectiveMap = {
|
|
76
|
+
"code-group": "DirectiveCodeGroup",
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const navComponents: MarkdownComponentDirectiveMap = {
|
|
80
|
+
tabs: "Tabs",
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const parseMarkdown = (content: string) => {
|
|
84
|
+
const ast = unified()
|
|
85
|
+
.use(remarkParse)
|
|
86
|
+
.use(remarkMdx)
|
|
87
|
+
.parse(content);
|
|
88
|
+
|
|
89
|
+
return ast.children;
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
// TODO: BETTER SETTINGS MANAGEMENT FOR MD
|
|
93
|
+
|
|
94
|
+
export function mdComponentDirective(settings?: Settings): Plugin {
|
|
95
|
+
return function () {
|
|
96
|
+
return async (tree: UnistNode, file: VFile) => {
|
|
97
|
+
console.time('plugin:mdComponentDirective');
|
|
98
|
+
const promises: Promise<void>[] = [];
|
|
99
|
+
|
|
100
|
+
visit(tree, 'containerDirective', recreateComponent(file, promises, supportedDirectives, settings));
|
|
101
|
+
visit(tree, 'textDirective', recreateComponent(file, promises, supportedTextDirectives, settings));
|
|
102
|
+
visit(tree, 'leafDirective', recreateComponent(file, promises, supportedLeafDirectives, settings));
|
|
103
|
+
|
|
104
|
+
await Promise.all(promises);
|
|
105
|
+
console.timeEnd('plugin:mdComponentDirective');
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function recreateComponent(
|
|
111
|
+
file: VFile,
|
|
112
|
+
promises: Promise<void>[],
|
|
113
|
+
directivesMap: MarkdownComponentDirectiveMap,
|
|
114
|
+
settings?: Settings,
|
|
115
|
+
) {
|
|
116
|
+
return function (node: any) {
|
|
117
|
+
if (!directivesMap[node.name]) {
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const attributes: any[] = [];
|
|
122
|
+
|
|
123
|
+
const componentName = getComponentName(node.name, directivesMap);
|
|
124
|
+
|
|
125
|
+
const isNavLike = navComponents[node.name];
|
|
126
|
+
const isTableLike = tableComponents[node.name];
|
|
127
|
+
const isStepsLike = stepsComponents[node.name];
|
|
128
|
+
const isCodeLike = codeComponents[node.name];
|
|
129
|
+
|
|
130
|
+
if (isNavLike) {
|
|
131
|
+
componentProps(
|
|
132
|
+
node,
|
|
133
|
+
attributes,
|
|
134
|
+
promises,
|
|
135
|
+
file,
|
|
136
|
+
settings,
|
|
137
|
+
);
|
|
138
|
+
|
|
139
|
+
mdNav(node, directivesMap, attributes);
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (isStepsLike) {
|
|
144
|
+
componentProps(
|
|
145
|
+
node,
|
|
146
|
+
attributes,
|
|
147
|
+
promises,
|
|
148
|
+
file,
|
|
149
|
+
settings,
|
|
150
|
+
);
|
|
151
|
+
|
|
152
|
+
mdSteps(node, directivesMap, attributes);
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
if (isTableLike) {
|
|
157
|
+
mdTable(node, directivesMap);
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if (isCodeLike) {
|
|
162
|
+
componentProps(
|
|
163
|
+
node,
|
|
164
|
+
attributes,
|
|
165
|
+
promises,
|
|
166
|
+
file,
|
|
167
|
+
settings,
|
|
168
|
+
);
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
mdCode(node, promises, directivesMap, settings, attributes);
|
|
172
|
+
return
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
if (node.attributes) {
|
|
176
|
+
componentProps(
|
|
177
|
+
node,
|
|
178
|
+
attributes,
|
|
179
|
+
promises,
|
|
180
|
+
file,
|
|
181
|
+
settings,
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// recreate component from markdown directive
|
|
186
|
+
const jsxNode = {
|
|
187
|
+
type: 'mdxJsxFlowElement',
|
|
188
|
+
name: componentName,
|
|
189
|
+
attributes: attributes,
|
|
190
|
+
children: node.children,
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
Object.assign(node, jsxNode);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
function mdNav(node: any, directivesMap: MarkdownComponentDirectiveMap, attributes: any[]) {
|
|
198
|
+
const componentName = getComponentName(node.name, directivesMap);
|
|
199
|
+
|
|
200
|
+
// Parse the nav directive content to extract tabs and their content
|
|
201
|
+
const tabItems: any[] = [];
|
|
202
|
+
const tabContents: any[] = [];
|
|
203
|
+
|
|
204
|
+
// Process each child node
|
|
205
|
+
node.children.forEach((child: any) => {
|
|
206
|
+
// Check if this is a list (ordered or unordered)
|
|
207
|
+
if (child.type === 'list') {
|
|
208
|
+
// Process each list item
|
|
209
|
+
child.children.forEach((listItem: any) => {
|
|
210
|
+
if (listItem.type === 'listItem') {
|
|
211
|
+
// The first child of a list item should be a paragraph with a link
|
|
212
|
+
const paragraph = listItem.children[0];
|
|
213
|
+
if (paragraph && paragraph.type === 'paragraph') {
|
|
214
|
+
const link = paragraph.children[0];
|
|
215
|
+
|
|
216
|
+
if (!link || link.type !== 'link' || !link.url) {
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// Extract tab value and label
|
|
221
|
+
let tabValue = '';
|
|
222
|
+
const linkUrlFormula = (link.url || "").split(" ").join("&")
|
|
223
|
+
if (link.url.startsWith('#')) {
|
|
224
|
+
tabValue = link.url;
|
|
225
|
+
} else {
|
|
226
|
+
tabValue = linkUrlFormula
|
|
227
|
+
}
|
|
228
|
+
const tabLabel = link.children[0].value;
|
|
229
|
+
|
|
230
|
+
// Create tab item
|
|
231
|
+
tabItems.push({
|
|
232
|
+
type: 'mdxJsxFlowElement',
|
|
233
|
+
name: `${componentName}.Item`,
|
|
234
|
+
attributes: [
|
|
235
|
+
{
|
|
236
|
+
type: 'mdxJsxAttribute',
|
|
237
|
+
name: 'value',
|
|
238
|
+
value: tabValue
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
type: 'mdxJsxAttribute',
|
|
242
|
+
name: 'href',
|
|
243
|
+
value: tabValue
|
|
244
|
+
}
|
|
245
|
+
],
|
|
246
|
+
children: [{
|
|
247
|
+
type: 'text',
|
|
248
|
+
value: tabLabel
|
|
249
|
+
}]
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
// Get the content for this tab (everything after the paragraph)
|
|
253
|
+
const tabContent = listItem.children.slice(1);
|
|
254
|
+
|
|
255
|
+
// Create tab content
|
|
256
|
+
tabContents.push({
|
|
257
|
+
type: 'mdxJsxFlowElement',
|
|
258
|
+
name: `${componentName}.Content`,
|
|
259
|
+
attributes: [{
|
|
260
|
+
type: 'mdxJsxAttribute',
|
|
261
|
+
name: 'value',
|
|
262
|
+
value: tabValue
|
|
263
|
+
}],
|
|
264
|
+
children: tabContent
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
// Create the Tabs component with tabs and content
|
|
273
|
+
const jsxNode = {
|
|
274
|
+
type: 'mdxJsxFlowElement',
|
|
275
|
+
name: componentName,
|
|
276
|
+
attributes,
|
|
277
|
+
// attributes: [
|
|
278
|
+
// // We don't need to provide value or onChange for uncontrolled mode
|
|
279
|
+
// ],
|
|
280
|
+
children: [...tabItems, ...tabContents]
|
|
281
|
+
};
|
|
282
|
+
|
|
283
|
+
Object.assign(node, jsxNode);
|
|
284
|
+
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
function mdSteps(node: any, directivesMap: MarkdownComponentDirectiveMap, attributes: any[]) {
|
|
289
|
+
const componentName = getComponentName(node.name, directivesMap);
|
|
290
|
+
|
|
291
|
+
const steps = node.children.map((child: any) => {
|
|
292
|
+
if (child.type !== "list") {
|
|
293
|
+
return child
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
return child.children.map((item: any) => {
|
|
297
|
+
if (item.type !== "listItem") {
|
|
298
|
+
return
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
const attributes: any[] = []
|
|
302
|
+
|
|
303
|
+
if (item.children.length) {
|
|
304
|
+
const firstChild = item.children[0]
|
|
305
|
+
|
|
306
|
+
if (firstChild?.children?.length === 1) {
|
|
307
|
+
const step = firstChild?.children[0]
|
|
308
|
+
if (step?.type === "text" || step?.type === "paragraph" && step?.value) {
|
|
309
|
+
const stepParams = mdParameters(step.value)
|
|
310
|
+
|
|
311
|
+
// TODO: sanitize text
|
|
312
|
+
if (stepParams.attributes && Object.keys(stepParams.attributes).length) {
|
|
313
|
+
firstChild.children[0].value = stepParams.sanitizedText
|
|
314
|
+
|
|
315
|
+
for (const [key, value] of Object.entries(stepParams.attributes)) {
|
|
316
|
+
attributes.push({
|
|
317
|
+
type: 'mdxJsxAttribute',
|
|
318
|
+
name: key,
|
|
319
|
+
value: value
|
|
320
|
+
})
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
return {
|
|
328
|
+
type: 'mdxJsxFlowElement',
|
|
329
|
+
name: `${componentName}.Item`,
|
|
330
|
+
attributes,
|
|
331
|
+
children: item.children
|
|
332
|
+
};
|
|
333
|
+
}).flat();
|
|
334
|
+
}).flat();
|
|
335
|
+
|
|
336
|
+
const jsxNode = {
|
|
337
|
+
type: 'mdxJsxFlowElement',
|
|
338
|
+
name: componentName,
|
|
339
|
+
attributes,
|
|
340
|
+
children: steps
|
|
341
|
+
};
|
|
342
|
+
|
|
343
|
+
Object.assign(node, jsxNode);
|
|
344
|
+
|
|
345
|
+
return;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
// TODO: support tsx tables like: [<>`Promise<Reference[]>`</>] ?
|
|
349
|
+
function mdTable(node: any, directivesMap: MarkdownComponentDirectiveMap) {
|
|
350
|
+
const componentName = getComponentName(node.name, directivesMap);
|
|
351
|
+
const tableData = JSON.parse(node.children[0].value);
|
|
352
|
+
const [header, ...rows] = tableData;
|
|
353
|
+
|
|
354
|
+
const jsxNode = {
|
|
355
|
+
type: 'mdxJsxFlowElement',
|
|
356
|
+
name: componentName,
|
|
357
|
+
attributes: [],
|
|
358
|
+
children: [
|
|
359
|
+
{
|
|
360
|
+
type: 'mdxJsxFlowElement',
|
|
361
|
+
name: `${componentName}.Head`,
|
|
362
|
+
attributes: [],
|
|
363
|
+
children: [
|
|
364
|
+
{
|
|
365
|
+
type: 'mdxJsxFlowElement',
|
|
366
|
+
name: `${componentName}.Tr`,
|
|
367
|
+
attributes: [],
|
|
368
|
+
children: header.map((cell: string) => ({
|
|
369
|
+
type: 'mdxJsxFlowElement',
|
|
370
|
+
name: `${componentName}.Th`,
|
|
371
|
+
attributes: [],
|
|
372
|
+
children: parseMarkdown(cell)
|
|
373
|
+
}))
|
|
374
|
+
}
|
|
375
|
+
]
|
|
376
|
+
},
|
|
377
|
+
// TODO: Table.Cell ?
|
|
378
|
+
...rows.map((row: string[]) => ({
|
|
379
|
+
type: 'mdxJsxFlowElement',
|
|
380
|
+
name: `${componentName}.Tr`,
|
|
381
|
+
attributes: [],
|
|
382
|
+
children: row.map((cell: string) => ({
|
|
383
|
+
type: 'mdxJsxFlowElement',
|
|
384
|
+
name: `${componentName}.Td`,
|
|
385
|
+
attributes: [],
|
|
386
|
+
children: parseMarkdown(cell)
|
|
387
|
+
}))
|
|
388
|
+
}))
|
|
389
|
+
]
|
|
390
|
+
};
|
|
391
|
+
|
|
392
|
+
Object.assign(node, jsxNode);
|
|
393
|
+
|
|
394
|
+
return;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
function mdCode(node: any, promises: Promise<any>[], directivesMap: MarkdownComponentDirectiveMap, settings?: Settings, attributes: any[]) {
|
|
398
|
+
const componentName = getComponentName(node.name, directivesMap);
|
|
399
|
+
|
|
400
|
+
const description = node.attributes?.title || '';
|
|
401
|
+
const codeblocks: any[] = [];
|
|
402
|
+
|
|
403
|
+
function rewriteNode() {
|
|
404
|
+
const jsxNode = {
|
|
405
|
+
type: 'mdxJsxFlowElement',
|
|
406
|
+
name: componentName,
|
|
407
|
+
attributes: [
|
|
408
|
+
...attributes,
|
|
409
|
+
{
|
|
410
|
+
type: 'mdxJsxAttribute',
|
|
411
|
+
name: 'description',
|
|
412
|
+
value: description
|
|
413
|
+
},
|
|
414
|
+
{
|
|
415
|
+
type: 'mdxJsxAttribute',
|
|
416
|
+
name: 'codeblocks',
|
|
417
|
+
value: JSON.stringify(codeblocks)
|
|
418
|
+
}
|
|
419
|
+
],
|
|
420
|
+
children: []
|
|
421
|
+
};
|
|
422
|
+
|
|
423
|
+
Object.assign(node, jsxNode);
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
for (const child of node.children) {
|
|
427
|
+
if (child.type === 'code') {
|
|
428
|
+
|
|
429
|
+
const meta = child.meta || '';
|
|
430
|
+
const value = child.value || '';
|
|
431
|
+
const lang = child.lang || '';
|
|
432
|
+
|
|
433
|
+
const promise = (async () => {
|
|
434
|
+
const highlighted = await highlight({
|
|
435
|
+
value: value,
|
|
436
|
+
lang,
|
|
437
|
+
meta: meta || lang || ""
|
|
438
|
+
}, settings?.theme?.coder?.syntaxHighlight || "github-dark") // TODO: theme
|
|
439
|
+
|
|
440
|
+
codeblocks.push({ value, lang, meta, highlighted: highlighted });
|
|
441
|
+
rewriteNode()
|
|
442
|
+
})()
|
|
443
|
+
|
|
444
|
+
promises.push(promise)
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
|
|
450
|
+
function componentProps(
|
|
451
|
+
node: any,
|
|
452
|
+
attributes: any[],
|
|
453
|
+
promises: Promise<void>[],
|
|
454
|
+
file: VFile,
|
|
455
|
+
settings?: Settings,
|
|
456
|
+
) {
|
|
457
|
+
|
|
458
|
+
const jsxProps = []
|
|
459
|
+
|
|
460
|
+
for (let [key, value] of Object.entries(node.attributes)) {
|
|
461
|
+
const stringNonJsxProp = isStringNonJsxProp(value as string)
|
|
462
|
+
|
|
463
|
+
if (stringNonJsxProp) {
|
|
464
|
+
if (functionMatch(value as string, FunctionName.Uniform)) {
|
|
465
|
+
const promise = mdUniformAttribute(key, value as string, attributes, file, settings);
|
|
466
|
+
|
|
467
|
+
if (promise) {
|
|
468
|
+
promises.push(promise)
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
continue;
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
attributes.push({
|
|
475
|
+
type: 'mdxJsxAttribute',
|
|
476
|
+
name: key,
|
|
477
|
+
value: value
|
|
478
|
+
});
|
|
479
|
+
} else {
|
|
480
|
+
jsxProps.push(`${key}={${value}}`)
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
if (jsxProps.length > 0) {
|
|
485
|
+
attributes.push(...complexJSXPropsPollyfill(jsxProps))
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
// parses structure like: <Atlas references={@uniform("index.ts")} />
|
|
490
|
+
function mdUniformAttribute(
|
|
491
|
+
attrKey: string, // like `references`
|
|
492
|
+
attrValue: string, // like `@uniform("index.ts")`
|
|
493
|
+
attributes: any,
|
|
494
|
+
file: VFile,
|
|
495
|
+
settings?: Settings
|
|
496
|
+
) {
|
|
497
|
+
|
|
498
|
+
const result = parseFunctionCall({
|
|
499
|
+
children: [
|
|
500
|
+
{
|
|
501
|
+
type: "text",
|
|
502
|
+
value: attrValue
|
|
503
|
+
}
|
|
504
|
+
]
|
|
505
|
+
}, FunctionName.Uniform);
|
|
506
|
+
|
|
507
|
+
if (!result) {
|
|
508
|
+
return
|
|
509
|
+
};
|
|
510
|
+
|
|
511
|
+
const importPath = result[0];
|
|
512
|
+
const importArgs = result[1];
|
|
513
|
+
|
|
514
|
+
const promise = (async () => {
|
|
515
|
+
try {
|
|
516
|
+
// Process the uniform function call
|
|
517
|
+
let references = await processUniformFunctionCall(
|
|
518
|
+
importPath,
|
|
519
|
+
file,
|
|
520
|
+
"",
|
|
521
|
+
settings,
|
|
522
|
+
);
|
|
523
|
+
|
|
524
|
+
if (importArgs?.mini && references) { // TODO: move to `processUniformFunctionCall`
|
|
525
|
+
references = uniformToMiniUniform(importArgs.mini, references as Reference<TypeDocReferenceContext>[]);
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
if (references && references.length > 0) {
|
|
529
|
+
attributes.push({
|
|
530
|
+
type: 'mdxJsxAttribute',
|
|
531
|
+
name: attrKey,
|
|
532
|
+
value: JSON.stringify(references, null, 2)
|
|
533
|
+
});
|
|
534
|
+
}
|
|
535
|
+
} catch (error) {
|
|
536
|
+
console.error(`Error processing uniform function call: ${importPath}`, error);
|
|
537
|
+
// Keep the node as is if there's an error
|
|
538
|
+
}
|
|
539
|
+
})();
|
|
540
|
+
|
|
541
|
+
return promise
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
// TODO: FIND BETTER SOLUTION TO CONVERT MORE COMPLEX JSX PROPS?
|
|
545
|
+
|
|
546
|
+
//jsxProps = ["key=value", "key2=value2"]
|
|
547
|
+
function complexJSXPropsPollyfill(jsxProps: string[]) {
|
|
548
|
+
const attributes = [];
|
|
549
|
+
|
|
550
|
+
const mdxString = `<Fragment ${jsxProps.join(" ")}></Fragment>`
|
|
551
|
+
|
|
552
|
+
const ast = unified()
|
|
553
|
+
.use(remarkParse)
|
|
554
|
+
.use(remarkMdx)
|
|
555
|
+
.parse(mdxString);
|
|
556
|
+
|
|
557
|
+
// Check if the first child is an MDX JSX element with attributes
|
|
558
|
+
if (ast &&
|
|
559
|
+
ast.children[0] &&
|
|
560
|
+
'type' in ast.children[0] &&
|
|
561
|
+
ast.children[0].type === 'mdxJsxFlowElement' &&
|
|
562
|
+
'attributes' in ast.children[0] &&
|
|
563
|
+
ast.children[0].attributes) {
|
|
564
|
+
for (const attr of ast.children[0].attributes) {
|
|
565
|
+
// TODO: support markdown also e.g Hello `World` - currently it mus be: Hello <code>World</code>
|
|
566
|
+
|
|
567
|
+
attributes.push(attr);
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
return attributes
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
// TODO: better matching
|
|
575
|
+
function isStringNonJsxProp(value: string): boolean {
|
|
576
|
+
return typeof value === "string" && !value.startsWith("<");
|
|
577
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type MarkdownComponentDirectiveMap = { [key: string]: boolean | string }
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { MarkdownComponentDirectiveMap } from "./types"
|
|
2
|
+
|
|
3
|
+
export function getComponentName(
|
|
4
|
+
name: string,
|
|
5
|
+
supportedDirectives: MarkdownComponentDirectiveMap
|
|
6
|
+
) {
|
|
7
|
+
let componentName = ""
|
|
8
|
+
|
|
9
|
+
const directive = supportedDirectives[name]
|
|
10
|
+
|
|
11
|
+
if (typeof directive === "string") {
|
|
12
|
+
componentName = directive
|
|
13
|
+
} else {
|
|
14
|
+
componentName = toPascalCase(name)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return componentName
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function toPascalCase(str: string) {
|
|
21
|
+
return str
|
|
22
|
+
.replace(/([a-z])([A-Z])/g, "$1 $2") // Add space before capital letters
|
|
23
|
+
.replace(/[^a-zA-Z0-9]/g, " ") // Replace special characters with space
|
|
24
|
+
.split(" ") // Split by space
|
|
25
|
+
.map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()) // Capitalize first letter
|
|
26
|
+
.join("");
|
|
27
|
+
}
|