@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.
Files changed (97) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/ISSUES.md +1 -0
  3. package/LICENSE +21 -0
  4. package/README.md +3 -0
  5. package/TODO.md +2 -0
  6. package/dist/index.d.ts +28 -0
  7. package/dist/index.js +1625 -0
  8. package/dist/index.js.map +1 -0
  9. package/dist/md.d.ts +72 -0
  10. package/dist/md.js +23508 -0
  11. package/dist/md.js.map +1 -0
  12. package/dist/mdToc-NBBxMJ4l.d.ts +12 -0
  13. package/dist/vite.d.ts +1066 -0
  14. package/dist/vite.js +20156 -0
  15. package/dist/vite.js.map +1 -0
  16. package/package.json +67 -0
  17. package/packages/md/index.ts +25 -0
  18. package/packages/md/plugins/component-directives/index.ts +3 -0
  19. package/packages/md/plugins/component-directives/mdComponentDirective.ts +577 -0
  20. package/packages/md/plugins/component-directives/types.ts +1 -0
  21. package/packages/md/plugins/component-directives/utils.ts +27 -0
  22. package/packages/md/plugins/composer/__fixtures__/1.single-example/input.md +7 -0
  23. package/packages/md/plugins/composer/__fixtures__/1.single-example/output.json +63 -0
  24. package/packages/md/plugins/composer/__fixtures__/2.single-example-with-name/input.md +7 -0
  25. package/packages/md/plugins/composer/__fixtures__/2.single-example-with-name/output.json +63 -0
  26. package/packages/md/plugins/composer/__fixtures__/3.multiple-examples/input.md +15 -0
  27. package/packages/md/plugins/composer/__fixtures__/3.multiple-examples/output.json +122 -0
  28. package/packages/md/plugins/composer/__fixtures__/4.example-groups/input.md +23 -0
  29. package/packages/md/plugins/composer/__fixtures__/4.example-groups/output.json +184 -0
  30. package/packages/md/plugins/composer/__tests__/mdComposer.test.ts +41 -0
  31. package/packages/md/plugins/composer/__tests__/testHelpers.ts +48 -0
  32. package/packages/md/plugins/composer/index.ts +1 -0
  33. package/packages/md/plugins/composer/mdComposer.ts +146 -0
  34. package/packages/md/plugins/developer-writing/index.ts +3 -0
  35. package/packages/md/plugins/developer-writing/mdCodeRehype.ts +81 -0
  36. package/packages/md/plugins/functions/__fixtures__/external.ts +4 -0
  37. package/packages/md/plugins/functions/__fixtures__/test-include.md +31 -0
  38. package/packages/md/plugins/functions/__fixtures__/test.js +11 -0
  39. package/packages/md/plugins/functions/__fixtures__/test.py +9 -0
  40. package/packages/md/plugins/functions/__fixtures__/test.ts +18 -0
  41. package/packages/md/plugins/functions/__tests__/mdFunctionImportCode.test.ts +314 -0
  42. package/packages/md/plugins/functions/__tests__/mdFunctionInclude.test.ts +44 -0
  43. package/packages/md/plugins/functions/__tests__/parseFunctionCall.test.ts +70 -0
  44. package/packages/md/plugins/functions/__tests__/testHelpers.ts +95 -0
  45. package/packages/md/plugins/functions/index.ts +15 -0
  46. package/packages/md/plugins/functions/mdFunctionChangelog.ts +135 -0
  47. package/packages/md/plugins/functions/mdFunctionImportCode.ts +92 -0
  48. package/packages/md/plugins/functions/mdFunctionInclude.ts +119 -0
  49. package/packages/md/plugins/functions/mdFunctionUniform.ts +79 -0
  50. package/packages/md/plugins/functions/types.ts +9 -0
  51. package/packages/md/plugins/functions/uniformProcessor.ts +349 -0
  52. package/packages/md/plugins/functions/utils.ts +457 -0
  53. package/packages/md/plugins/index.ts +125 -0
  54. package/packages/md/plugins/mdCode.ts +16 -0
  55. package/packages/md/plugins/mdHeadingId.ts +47 -0
  56. package/packages/md/plugins/mdImage.test.ts +59 -0
  57. package/packages/md/plugins/mdImage.ts +55 -0
  58. package/packages/md/plugins/mdImageRehype.ts +13 -0
  59. package/packages/md/plugins/mdPage.ts +35 -0
  60. package/packages/md/plugins/mdThemeSettings.ts +34 -0
  61. package/packages/md/plugins/mdToc.ts +229 -0
  62. package/packages/md/plugins/meta/index.ts +1 -0
  63. package/packages/md/plugins/meta/mdMeta.ts +198 -0
  64. package/packages/md/plugins/output-variables/__fixtures__/1.simple/input.md +22 -0
  65. package/packages/md/plugins/output-variables/__fixtures__/1.simple/output.json +191 -0
  66. package/packages/md/plugins/output-variables/__fixtures__/2.multiple-vars/input.md +21 -0
  67. package/packages/md/plugins/output-variables/__fixtures__/2.multiple-vars/output.json +127 -0
  68. package/packages/md/plugins/output-variables/__tests__/index.test.ts +28 -0
  69. package/packages/md/plugins/output-variables/__tests__/testHelpers.ts +36 -0
  70. package/packages/md/plugins/output-variables/index.ts +1 -0
  71. package/packages/md/plugins/output-variables/lib/const.ts +4 -0
  72. package/packages/md/plugins/output-variables/lib/factoryAttributes.ts +350 -0
  73. package/packages/md/plugins/output-variables/lib/factoryLabel.ts +135 -0
  74. package/packages/md/plugins/output-variables/lib/factoryName.ts +59 -0
  75. package/packages/md/plugins/output-variables/lib/index.ts +21 -0
  76. package/packages/md/plugins/output-variables/lib/outputVarsContainer.ts +328 -0
  77. package/packages/md/plugins/output-variables/lib/util.ts +494 -0
  78. package/packages/md/plugins/output-variables/remarkOutputVars.ts +22 -0
  79. package/packages/md/plugins/recmaOverrideComponents.ts +74 -0
  80. package/packages/md/plugins/rehypeHeading.ts +58 -0
  81. package/packages/md/plugins/types.ts +15 -0
  82. package/packages/md/plugins/utils/componentLike.ts +76 -0
  83. package/packages/md/plugins/utils/index.ts +2 -0
  84. package/packages/md/plugins/utils/injectCodeMeta.ts +59 -0
  85. package/packages/md/plugins/utils/mdParameters.test.ts +114 -0
  86. package/packages/md/plugins/utils/mdParameters.ts +249 -0
  87. package/packages/md/plugins/utils/mdastTypes.ts +42 -0
  88. package/packages/md/search/index.ts +257 -0
  89. package/packages/md/search/types.ts +36 -0
  90. package/packages/vite/index.ts +20 -0
  91. package/src/fs.ts +81 -0
  92. package/src/index.ts +7 -0
  93. package/src/navigation.ts +147 -0
  94. package/src/types.ts +8 -0
  95. package/tsconfig.json +49 -0
  96. package/tsup.config.ts +32 -0
  97. package/vitest.config.ts +17 -0
@@ -0,0 +1,70 @@
1
+ import {describe, it, expect} from 'vitest';
2
+
3
+ import {parseFunctionCall} from '../utils';
4
+ import {FunctionName} from "../types";
5
+
6
+ describe('parseFunctionCall', () => {
7
+ const testCases = [
8
+ {
9
+ name: '1a. should parse uniform with file path and options',
10
+ function: FunctionName.Uniform,
11
+ input: `@uniform('~/path/to/resource.ts', {"mini": "Settings"})`,
12
+ expected: ['~/path/to/resource.ts', {mini: 'Settings'}]
13
+ },
14
+ {
15
+ name: '1b. should parse uniform with file path and options',
16
+ function: FunctionName.Uniform,
17
+ input: `@uniform('~/path/to/resource.ts', {mini: 'Settings'})`,
18
+ expected: ['~/path/to/resource.ts', {mini: 'Settings'}]
19
+ },
20
+ {
21
+ name: '2. should parse uniform with file path only',
22
+ function: FunctionName.Uniform,
23
+ input: '@uniform(~/path/to/resource.ts)',
24
+ expected: ['~/path/to/resource.ts']
25
+ },
26
+ {
27
+ name: '3a. should handle malformed uniform call',
28
+ function: FunctionName.Uniform,
29
+ input: '@uniform_invalid()',
30
+ expected: null
31
+ },
32
+ {
33
+ name: '3b. should handle malformed uniform call',
34
+ function: FunctionName.Uniform,
35
+ input: 'uniform()',
36
+ expected: null
37
+ },
38
+ {
39
+ name: '4. should parse function with md attributes',
40
+ function: FunctionName.ImportCode,
41
+ input: `@importCode[descHead="Tip" desc="It's a nice code"] ~/path/to/resource.ts`,
42
+ expected: ['~/path/to/resource.ts', {__mdAttrs: {descHead: 'Tip', desc: "It's a nice code"}}]
43
+ },
44
+ {
45
+ name: '4. should parse function with md attributes + quotes',
46
+ function: FunctionName.ImportCode,
47
+ input: `@importCode[descHead="Tip" desc="You can use md attributes!"] "~/path/to/resource.ts"`,
48
+ expected: ['~/path/to/resource.ts', {__mdAttrs: {descHead: 'Tip', desc: "You can use md attributes!"}}]
49
+ },
50
+ {
51
+ name: '4. should parse function with md attributes + shortand attrs',
52
+ function: FunctionName.ImportCode,
53
+ input: `@importCode[!scroll lines descHead="Tip" desc="You can use md attributes!"] "~/path/to/resource.ts"`,
54
+ expected: ['~/path/to/resource.ts', {__mdAttrs: {scroll: "false", lines: "true", descHead: 'Tip', desc: "You can use md attributes!"}}]
55
+ }
56
+ ];
57
+
58
+ testCases.forEach(({name, function: functionName, input, expected}) => {
59
+ it(name, () => {
60
+ const node = {
61
+ children: [{
62
+ type: 'text',
63
+ value: input
64
+ }]
65
+ };
66
+ const result = parseFunctionCall(node, functionName);
67
+ expect(result).toEqual(expected);
68
+ });
69
+ });
70
+ });
@@ -0,0 +1,95 @@
1
+ import path from 'node:path';
2
+ import {VFile} from 'vfile';
3
+
4
+ export function importCodeMockTree(importPath: string) {
5
+ return {
6
+ type: 'root',
7
+ children: [
8
+ {
9
+ type: 'paragraph',
10
+ children: [
11
+ {
12
+ type: 'text',
13
+ value: `@importCode "${importPath}"`
14
+ }
15
+ ]
16
+ }
17
+ ]
18
+ };
19
+ }
20
+
21
+ export function importCodeMdAttributesMockTree(
22
+ importPath: string,
23
+ attributes: Record<string, string>
24
+ ) {
25
+ // Convert attributes object to md attribute string
26
+ const attrsString = Object.entries(attributes)
27
+ .map(([key, value]) => `${key}="${value}"`)
28
+ .join(' ');
29
+
30
+ return {
31
+ type: 'root',
32
+ children: [
33
+ {
34
+ type: 'paragraph',
35
+ children: [
36
+ {
37
+ type: 'text',
38
+ value: `@importCode[${attrsString}] "${importPath}"`
39
+ }
40
+ ]
41
+ }
42
+ ]
43
+ };
44
+ }
45
+
46
+ export function importCodeMockTreeAlternative(importPath: string) {
47
+ return {
48
+ type: 'root',
49
+ children: [
50
+ {
51
+ type: 'paragraph',
52
+ children: [
53
+ {
54
+ type: 'text',
55
+ value: `@importCode("${importPath}")`
56
+ }
57
+ ]
58
+ }
59
+ ]
60
+ };
61
+ }
62
+
63
+
64
+ export function createMockFile(dirname?: string) {
65
+ return new VFile({
66
+ path: 'test.md',
67
+ value: '',
68
+ dirname: dirname || path.resolve(__dirname, '../__fixtures__')
69
+ });
70
+ }
71
+
72
+
73
+ export function createMockFetch(mockResponses: Record<string, string>) {
74
+ const originalFetch = global.fetch;
75
+
76
+ global.fetch = (async (input: RequestInfo | URL, init?: RequestInit): Promise<Response> => {
77
+ const url = input.toString();
78
+
79
+ if (mockResponses[url]) {
80
+ return {
81
+ ok: true,
82
+ text: async () => mockResponses[url]
83
+ } as Response;
84
+ }
85
+
86
+ throw new Error(`Unexpected URL: ${url}`);
87
+ }) as typeof fetch;
88
+
89
+ return originalFetch;
90
+ }
91
+
92
+
93
+ export function restoreFetch(originalFetch: typeof global.fetch) {
94
+ global.fetch = originalFetch;
95
+ }
@@ -0,0 +1,15 @@
1
+ export {
2
+ mdFunctionImportCode
3
+ } from "./mdFunctionImportCode"
4
+
5
+ export {
6
+ mdFunctionInclude
7
+ } from "./mdFunctionInclude"
8
+
9
+ export {
10
+ mdFunctionUniform
11
+ } from "./mdFunctionUniform"
12
+
13
+ export {
14
+ mdFunctionChangelog
15
+ } from "./mdFunctionChangelog"
@@ -0,0 +1,135 @@
1
+ import { visit } from 'unist-util-visit';
2
+ import { VFile } from 'vfile';
3
+ import { unified } from 'unified';
4
+ import remarkParse from 'remark-parse';
5
+ import remarkMdx from 'remark-mdx';
6
+
7
+ import { Settings } from '@xyd-js/core';
8
+
9
+ import { FunctionName } from './types';
10
+ import { FunctionOptions, parseFunctionCall, downloadContent, resolvePathAlias } from './utils';
11
+ import path from 'node:path';
12
+
13
+ interface ChangelogEntry {
14
+ version: string;
15
+ date?: string;
16
+ content: string;
17
+ }
18
+
19
+ export function mdFunctionChangelog(settings?: Settings) {
20
+ return function (options: FunctionOptions = {}) {
21
+ return async function transformer(tree: any, file: VFile) {
22
+ const promises: Promise<void>[] = [];
23
+
24
+ visit(tree, 'paragraph', (node: any) => {
25
+ if (!file?.dirname) {
26
+ return;
27
+ }
28
+ const result = parseFunctionCall(node, FunctionName.Changelog);
29
+ if (!result || !result.length) return;
30
+
31
+ const importPath = result[0];
32
+ // let fullDirPath = path.join(process.cwd(), file.dirname || "")
33
+ // fullDirPath = process.cwd()
34
+ const resolvedPath = resolvePathAlias(importPath, settings, file) || importPath;
35
+
36
+ const promise = (async () => {
37
+ try {
38
+ const content = await downloadContent(resolvedPath, file, options.resolveFrom);
39
+ const entries = parseChangelog(content);
40
+
41
+ // Replace the node with the generated content
42
+ node.type = 'mdxJsxFlowElement';
43
+ node.attributes = [];
44
+ node.children = entries.map(entry => {
45
+ // Parse the markdown content
46
+ const parsedContent = unified()
47
+ .use(remarkParse)
48
+ .use(remarkMdx)
49
+ .parse(entry.content);
50
+
51
+ return {
52
+ type: 'mdxJsxFlowElement',
53
+ name: 'Update',
54
+ attributes: [
55
+ {
56
+ type: 'mdxJsxAttribute',
57
+ name: 'version',
58
+ value: entry.version
59
+ },
60
+ {
61
+ type: 'mdxJsxAttribute',
62
+ name: 'date',
63
+ value: entry.date || ''
64
+ }
65
+ ],
66
+ children: parsedContent.children
67
+ };
68
+ });
69
+ } catch (error) {
70
+ console.error(`Error processing changelog: ${resolvedPath}`, error);
71
+ }
72
+ })();
73
+
74
+ promises.push(promise);
75
+ });
76
+
77
+ await Promise.all(promises);
78
+ };
79
+ };
80
+ }
81
+
82
+ function parseChangelog(content: string): ChangelogEntry[] {
83
+ const entries: ChangelogEntry[] = [];
84
+ const lines = content.split('\n');
85
+ let currentEntry: ChangelogEntry | null = null;
86
+ let currentContent: string[] = [];
87
+
88
+ for (let i = 0; i < lines.length; i++) {
89
+ const line = lines[i];
90
+
91
+ // Match different version header formats:
92
+ // 1. ## [X.Y.Z] - any date format
93
+ // 2. ## [X.Y.Z]
94
+ // 3. ## X.Y.Z
95
+ // 4. ## [unreleased] - any date format
96
+ // 5. ## [0.0.1-alpha.0] - any date format
97
+ const versionMatch = line.match(/^##\s+(?:\[?([^\]]+)\]?(?:\s*-\s*([^\n]+))?)/);
98
+ if (versionMatch) {
99
+ // Save previous entry if exists
100
+ if (currentEntry) {
101
+ currentEntry.content = currentContent.join('\n').trim();
102
+ entries.push(currentEntry);
103
+ }
104
+
105
+ // Start new entry
106
+ currentEntry = {
107
+ version: versionMatch[1],
108
+ date: versionMatch[2]?.trim() || '',
109
+ content: ''
110
+ };
111
+ currentContent = [];
112
+ continue;
113
+ }
114
+
115
+ // Skip the main title (# xyd-js)
116
+ if (line.startsWith('# ')) {
117
+ continue;
118
+ }
119
+
120
+ // Add content to current entry
121
+ if (currentEntry) {
122
+ currentContent.push(line);
123
+ }
124
+ }
125
+
126
+ // Add last entry
127
+ if (currentEntry) {
128
+ currentEntry.content = currentContent.join('\n').trim();
129
+ entries.push(currentEntry);
130
+ }
131
+
132
+ return entries;
133
+ }
134
+
135
+
@@ -0,0 +1,92 @@
1
+ import { visit } from 'unist-util-visit';
2
+ import { VFile } from 'vfile';
3
+
4
+ import { Settings } from '@xyd-js/core';
5
+
6
+ import { FunctionName } from "./types";
7
+ import {
8
+ FunctionOptions,
9
+ parseFunctionCall,
10
+ parseImportPath,
11
+ processContent,
12
+ detectLanguage,
13
+ readLocalFile,
14
+ fetchFileContent,
15
+ resolvePathAlias
16
+ } from './utils';
17
+ import { injectCodeMeta } from '../utils/injectCodeMeta';
18
+ import path from 'node:path';
19
+
20
+ export function mdFunctionImportCode(settings?: Settings) {
21
+ return function (options: FunctionOptions = {}) {
22
+ return async function transformer(tree: any, file: VFile) {
23
+ // Collect promises for async operations
24
+ const promises: Promise<void>[] = [];
25
+
26
+ console.time('plugin:mdFunctionImportCode');
27
+
28
+ visit(tree, 'paragraph', (node: any) => {
29
+ // Try to parse the function call
30
+ const result = parseFunctionCall(node, FunctionName.ImportCode);
31
+ if (!result) return;
32
+
33
+ const importPath = result[0];
34
+ const args = result[1];
35
+ const mdAttrs = args?.__mdAttrs || {};
36
+
37
+ // let fullDirPath = path.join(process.cwd(), file.dirname || "")
38
+ // fullDirPath = process.cwd()
39
+ // Parse the import path to extract file path, regions, and line ranges
40
+ const { filePath, regions, lineRanges } = parseImportPath(
41
+ resolvePathAlias(importPath, settings, file) || importPath
42
+ );
43
+
44
+ // Determine if this is a local or external file
45
+ const isExternal = filePath.startsWith('http://') || filePath.startsWith('https://');
46
+
47
+ // Create a promise for this node
48
+ const promise = (async () => {
49
+ try {
50
+ // Get the file content
51
+ let content: string;
52
+
53
+ if (isExternal) {
54
+ // Fetch external content
55
+ content = await fetchFileContent(filePath);
56
+ } else {
57
+ const baseDir = options.resolveFrom || (file.dirname || process.cwd());
58
+ content = readLocalFile(filePath, baseDir);
59
+ }
60
+
61
+ // Process the content based on regions and line ranges
62
+ let processedContent = processContent(content, regions, lineRanges);
63
+
64
+ // Detect language from file extension
65
+ const language = detectLanguage(filePath);
66
+
67
+ // Replace the paragraph with a code block
68
+ node.type = 'code';
69
+ node.lang = language;
70
+ node.value = processedContent;
71
+ node.children = undefined;
72
+
73
+ // Inject code meta and props
74
+ const attrsString = args?.__mdAttrs ? Object.entries(args.__mdAttrs).map(([k,v]) => `${k}="${v}"`).join(' ') : undefined;
75
+ const metaString = attrsString ? `[${attrsString}]` : undefined;
76
+ injectCodeMeta(node, metaString);
77
+ } catch (error) {
78
+ console.error(`Error importing file: ${filePath}`, error);
79
+ // Keep the node as is if there's an error
80
+ }
81
+ })();
82
+
83
+ // Add the promise to our collection
84
+ promises.push(promise);
85
+ });
86
+
87
+ // Wait for all promises to resolve
88
+ await Promise.all(promises);
89
+ console.timeEnd('plugin:mdFunctionImportCode');
90
+ };
91
+ }
92
+ }
@@ -0,0 +1,119 @@
1
+ import { visit } from 'unist-util-visit';
2
+ import { VFile } from 'vfile';
3
+ import { unified } from 'unified';
4
+ import remarkParse from 'remark-parse';
5
+ import { fromMarkdown } from 'mdast-util-from-markdown';
6
+ import { mdxjs } from 'micromark-extension-mdxjs';
7
+ import { mdxFromMarkdown } from 'mdast-util-mdx';
8
+
9
+ import { Settings } from '@xyd-js/core';
10
+
11
+ import { FunctionName } from './types';
12
+ import {
13
+ FunctionOptions,
14
+ parseFunctionCall,
15
+ downloadContent,
16
+ resolvePathAlias,
17
+ } from './utils';
18
+ import { defaultRemarkPlugins } from '..';
19
+ import remarkFrontmatter from 'remark-frontmatter';
20
+ import remarkMdxFrontmatter from 'remark-mdx-frontmatter';
21
+ import { remarkMdxToc } from '../mdToc';
22
+ import path from 'path';
23
+
24
+ export function mdFunctionInclude(settings?: Settings) {
25
+ return function (options: FunctionOptions = {}) {
26
+ return async function transformer(tree: any, file: VFile) {
27
+ console.time('plugin:mdFunctionInclude');
28
+
29
+ // Collect all replacements to avoid index shifting issues
30
+ const replacements: Array<{
31
+ parent: any;
32
+ index: number;
33
+ children: any[];
34
+ }> = [];
35
+
36
+ // First pass: collect all @include nodes and their replacements
37
+ const promises: Promise<void>[] = [];
38
+
39
+ visit(tree, 'paragraph', (node: any, index: number | undefined, parent: any) => {
40
+ const result = parseFunctionCall(node, FunctionName.Include);
41
+ if (!result || index === undefined) return;
42
+
43
+ const importPath = result[0];
44
+ const resolvedPath =
45
+ resolvePathAlias(importPath, settings, file) || importPath;
46
+
47
+ const resolvedIncludeBasePath =
48
+ resolvePathAlias(resolvedPath, settings, file) || importPath;
49
+
50
+ const promise = (async () => {
51
+ try {
52
+ const ext = resolvedPath.split('.').pop();
53
+ const content = await downloadContent(
54
+ resolvedPath,
55
+ file,
56
+ options.resolveFrom,
57
+ );
58
+
59
+ const includeFilePath = path.join(file.dirname || "", resolvedIncludeBasePath)
60
+ const includedFile = new VFile({
61
+ path: includeFilePath,
62
+ dirname: path.dirname(includeFilePath),
63
+ value: content
64
+ });
65
+
66
+ let parsedTree;
67
+
68
+ const remarkPlugins = defaultRemarkPlugins({} as any, settings)
69
+ .filter(plugin => plugin !== remarkFrontmatter)
70
+ .filter(plugin => plugin !== remarkMdxFrontmatter)
71
+ .filter(plugin => !(typeof plugin === 'function' && (plugin.name === 'remarkMdxToc' || plugin.name === 'remarkMdxToc2')))
72
+
73
+ if (ext === 'mdx') {
74
+ // Parse MDX into MDAST using micromark + mdast-util-mdx
75
+ parsedTree = fromMarkdown(content, {
76
+ extensions: [mdxjs()],
77
+ mdastExtensions: [mdxFromMarkdown()],
78
+ });
79
+
80
+ // Apply remark plugins to the parsed MDX tree with the correct file context
81
+ const mdxProcessor = unified().use(remarkPlugins);
82
+ parsedTree = await mdxProcessor.run(parsedTree, includedFile);
83
+ } else {
84
+ // Regular Markdown file using remarkParse
85
+ const processor = unified()
86
+ .use(remarkParse)
87
+ .use(remarkPlugins);
88
+
89
+ parsedTree = await processor.run(processor.parse(content), includedFile);
90
+ }
91
+
92
+ // Store the replacement instead of applying it immediately
93
+ replacements.push({
94
+ parent,
95
+ index,
96
+ children: parsedTree.children,
97
+ });
98
+ } catch (error) {
99
+ console.error(`Error including file: ${resolvedPath}`, error);
100
+ }
101
+ })();
102
+
103
+ promises.push(promise);
104
+ });
105
+
106
+ // Wait for all content to be downloaded and parsed
107
+ await Promise.all(promises);
108
+
109
+ // Second pass: apply replacements in reverse order to avoid index shifting
110
+ replacements
111
+ .sort((a, b) => b.index - a.index) // Sort by index in descending order
112
+ .forEach(({ parent, index, children }) => {
113
+ parent.children.splice(index, 1, ...children);
114
+ });
115
+
116
+ console.timeEnd('plugin:mdFunctionInclude');
117
+ };
118
+ };
119
+ }
@@ -0,0 +1,79 @@
1
+ import { visit } from 'unist-util-visit';
2
+ import { VFile } from 'vfile';
3
+
4
+ import { Settings } from '@xyd-js/core'
5
+ import uniform, { pluginJsonView, Reference, TypeDocReferenceContext } from "@xyd-js/uniform"
6
+
7
+ import { FunctionName } from "./types";
8
+ import {
9
+ FunctionOptions,
10
+ parseFunctionCall,
11
+ } from './utils';
12
+
13
+ // Import the processUniformFunctionCall function
14
+ import { processUniformFunctionCall } from './uniformProcessor';
15
+ import { uniformToMiniUniform } from '@xyd-js/sources/ts';
16
+
17
+ export function mdFunctionUniform(settings?: Settings) {
18
+ return function (options: FunctionOptions = {}) {
19
+ return async function transformer(tree: any, file: VFile) {
20
+ // Collect promises for async operations
21
+ const promises: Promise<void>[] = [];
22
+
23
+ console.time('plugin:mdFunctionUniform');
24
+
25
+ visit(tree, 'paragraph', (node: any) => {
26
+ // Try to parse the function call
27
+ const result = parseFunctionCall(node, FunctionName.Uniform);
28
+ if (!result) return;
29
+
30
+ const importPath = result[0];
31
+ const importArgs = result[1];
32
+
33
+ // Create a promise for this node
34
+ const promise = (async () => {
35
+ try {
36
+ // Process the uniform function call
37
+ let references = await processUniformFunctionCall(
38
+ importPath,
39
+ file,
40
+ options.resolveFrom,
41
+ settings,
42
+ );
43
+
44
+ if (importArgs?.mini && references) { // TODO: move to `processUniformFunctionCall`
45
+ references = uniformToMiniUniform(importArgs.mini, references as Reference<TypeDocReferenceContext>[]);
46
+ }
47
+
48
+ if (references) {
49
+ node.type = 'code';
50
+ node.lang = 'json';
51
+ const jsonViewRefs = uniform(references, {
52
+ plugins: [
53
+ pluginJsonView()
54
+ ]
55
+ })
56
+
57
+ // TODO: support multiple json views
58
+ node.value = jsonViewRefs.out.jsonViews[0]
59
+ node.children = undefined;
60
+ }
61
+ } catch (error) {
62
+ console.error(`Error processing uniform function call: ${importPath}`, error);
63
+ // Keep the node as is if there's an error
64
+ }
65
+ })();
66
+
67
+ // Add the promise to our collection
68
+ promises.push(promise);
69
+ });
70
+
71
+ // Wait for all promises to resolve
72
+ await Promise.all(promises);
73
+ console.timeEnd('plugin:mdFunctionUniform');
74
+ };
75
+ }
76
+
77
+ }
78
+
79
+
@@ -0,0 +1,9 @@
1
+ export enum FunctionName {
2
+ ImportCode = '@importCode',
3
+
4
+ Include = '@include',
5
+
6
+ Uniform = '@uniform',
7
+
8
+ Changelog = '@changelog',
9
+ }