@xyd-js/content 0.1.0-xyd.13 → 0.1.0-xyd.16

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