@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.
- package/CHANGELOG.md +34 -0
- package/ISSUES.md +1 -0
- package/TODO.md +2 -0
- package/dist/index.d.ts +24 -5
- package/dist/index.js +1411 -21776
- package/dist/index.js.map +1 -1
- package/dist/md.d.ts +62 -7
- package/dist/md.js +18071 -15085
- package/dist/md.js.map +1 -1
- package/dist/{mdToc-CYxzibVZ.d.ts → mdToc-NBBxMJ4l.d.ts} +1 -0
- package/dist/vite.d.ts +81 -2
- package/dist/vite.js +9716 -10090
- package/dist/vite.js.map +1 -1
- package/example.txt +0 -0
- package/package.json +24 -6
- package/packages/md/index.ts +17 -8
- package/packages/md/plugins/component-directives/index.ts +3 -0
- package/packages/md/plugins/component-directives/mdComponentDirective.ts +524 -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 +78 -0
- package/packages/md/plugins/functions/__fixtures__/external.ts +4 -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 +295 -0
- package/packages/md/plugins/functions/__tests__/parseFunctionCall.test.ts +47 -0
- package/packages/md/plugins/functions/__tests__/testHelpers.ts +71 -0
- package/packages/md/plugins/functions/index.ts +11 -0
- package/packages/md/plugins/functions/mdFunctionChangelog.ts +124 -0
- package/packages/md/plugins/functions/mdFunctionImportCode.ts +83 -0
- package/packages/md/plugins/functions/mdFunctionUniform.ts +79 -0
- package/packages/md/plugins/functions/types.ts +6 -0
- package/packages/md/plugins/functions/uniformProcessor.ts +349 -0
- package/packages/md/plugins/functions/utils.ts +423 -0
- package/packages/md/plugins/index.ts +56 -11
- package/packages/md/plugins/mdCode.ts +52 -4
- package/packages/md/plugins/mdHeadingId.ts +47 -0
- package/packages/md/plugins/mdPage.ts +3 -0
- package/packages/md/plugins/mdThemeSettings.ts +4 -0
- package/packages/md/plugins/mdToc.ts +108 -17
- package/packages/md/plugins/meta/index.ts +1 -0
- package/packages/md/plugins/meta/mdMeta.ts +189 -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/rehypeHeading.ts +50 -0
- package/packages/md/plugins/types.ts +15 -0
- package/packages/md/plugins/utils/componentLike.ts +72 -0
- package/packages/md/plugins/utils/index.ts +2 -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 +251 -0
- package/packages/md/search/types.ts +36 -0
- package/packages/vite/index.ts +8 -2
- package/src/fs.ts +51 -36
- package/src/index.ts +4 -4
- package/src/navigation.ts +50 -38
- package/src/types.ts +8 -0
- package/tsconfig.json +31 -8
- package/vitest.config.ts +17 -0
- package/packages/md/plugins/mdCodeGroup.ts +0 -40
- package/packages/md/plugins/mdComponentDirective.ts +0 -141
|
@@ -0,0 +1,124 @@
|
|
|
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 { FunctionName } from './types';
|
|
8
|
+
import { FunctionOptions, parseFunctionCall, downloadContent } from './utils';
|
|
9
|
+
|
|
10
|
+
interface ChangelogEntry {
|
|
11
|
+
version: string;
|
|
12
|
+
date?: string;
|
|
13
|
+
content: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function mdFunctionChangelog() {
|
|
17
|
+
return function (options: FunctionOptions = {}) {
|
|
18
|
+
return async function transformer(tree: any, file: VFile) {
|
|
19
|
+
const promises: Promise<void>[] = [];
|
|
20
|
+
|
|
21
|
+
visit(tree, 'paragraph', (node: any) => {
|
|
22
|
+
const result = parseFunctionCall(node, FunctionName.Changelog);
|
|
23
|
+
if (!result) return;
|
|
24
|
+
|
|
25
|
+
const importPath = result[0];
|
|
26
|
+
|
|
27
|
+
const promise = (async () => {
|
|
28
|
+
try {
|
|
29
|
+
const content = await downloadContent(importPath, file, options.resolveFrom);
|
|
30
|
+
const entries = parseChangelog(content);
|
|
31
|
+
|
|
32
|
+
// Replace the node with the generated content
|
|
33
|
+
node.type = 'mdxJsxFlowElement';
|
|
34
|
+
node.attributes = [];
|
|
35
|
+
node.children = entries.map(entry => {
|
|
36
|
+
// Parse the markdown content
|
|
37
|
+
const parsedContent = unified()
|
|
38
|
+
.use(remarkParse)
|
|
39
|
+
.use(remarkMdx)
|
|
40
|
+
.parse(entry.content);
|
|
41
|
+
|
|
42
|
+
return {
|
|
43
|
+
type: 'mdxJsxFlowElement',
|
|
44
|
+
name: 'Update',
|
|
45
|
+
attributes: [
|
|
46
|
+
{
|
|
47
|
+
type: 'mdxJsxAttribute',
|
|
48
|
+
name: 'version',
|
|
49
|
+
value: entry.version
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
type: 'mdxJsxAttribute',
|
|
53
|
+
name: 'date',
|
|
54
|
+
value: entry.date || ''
|
|
55
|
+
}
|
|
56
|
+
],
|
|
57
|
+
children: parsedContent.children
|
|
58
|
+
};
|
|
59
|
+
});
|
|
60
|
+
} catch (error) {
|
|
61
|
+
console.error(`Error processing changelog: ${importPath}`, error);
|
|
62
|
+
}
|
|
63
|
+
})();
|
|
64
|
+
|
|
65
|
+
promises.push(promise);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
await Promise.all(promises);
|
|
69
|
+
};
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function parseChangelog(content: string): ChangelogEntry[] {
|
|
74
|
+
const entries: ChangelogEntry[] = [];
|
|
75
|
+
const lines = content.split('\n');
|
|
76
|
+
let currentEntry: ChangelogEntry | null = null;
|
|
77
|
+
let currentContent: string[] = [];
|
|
78
|
+
|
|
79
|
+
for (let i = 0; i < lines.length; i++) {
|
|
80
|
+
const line = lines[i];
|
|
81
|
+
|
|
82
|
+
// Match different version header formats:
|
|
83
|
+
// 1. ## [X.Y.Z] - any date format
|
|
84
|
+
// 2. ## [X.Y.Z]
|
|
85
|
+
// 3. ## X.Y.Z
|
|
86
|
+
const versionMatch = line.match(/^##\s+(?:\[?([\d.]+)\]?(?:\s*-\s*([^\n]+))?)/);
|
|
87
|
+
if (versionMatch) {
|
|
88
|
+
// Save previous entry if exists
|
|
89
|
+
if (currentEntry) {
|
|
90
|
+
currentEntry.content = currentContent.join('\n').trim();
|
|
91
|
+
entries.push(currentEntry);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Start new entry
|
|
95
|
+
currentEntry = {
|
|
96
|
+
version: versionMatch[1],
|
|
97
|
+
date: versionMatch[2]?.trim() || '',
|
|
98
|
+
content: ''
|
|
99
|
+
};
|
|
100
|
+
currentContent = [];
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Skip the main title (# xyd-js)
|
|
105
|
+
if (line.startsWith('# ')) {
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Add content to current entry
|
|
110
|
+
if (currentEntry) {
|
|
111
|
+
currentContent.push(line);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Add last entry
|
|
116
|
+
if (currentEntry) {
|
|
117
|
+
currentEntry.content = currentContent.join('\n').trim();
|
|
118
|
+
entries.push(currentEntry);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return entries;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
|
|
@@ -0,0 +1,83 @@
|
|
|
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
|
+
|
|
18
|
+
export function mdFunctionImportCode(settings?: Settings) {
|
|
19
|
+
return function (options: FunctionOptions = {}) {
|
|
20
|
+
return async function transformer(tree: any, file: VFile) {
|
|
21
|
+
// Collect promises for async operations
|
|
22
|
+
const promises: Promise<void>[] = [];
|
|
23
|
+
|
|
24
|
+
console.time('plugin:mdFunctionImportCode');
|
|
25
|
+
|
|
26
|
+
visit(tree, 'paragraph', (node: any) => {
|
|
27
|
+
// Try to parse the function call
|
|
28
|
+
const result = parseFunctionCall(node, FunctionName.ImportCode);
|
|
29
|
+
if (!result) return;
|
|
30
|
+
|
|
31
|
+
const importPath = result[0];
|
|
32
|
+
|
|
33
|
+
// Parse the import path to extract file path, regions, and line ranges
|
|
34
|
+
const { filePath, regions, lineRanges } = parseImportPath(
|
|
35
|
+
resolvePathAlias(importPath, settings, process.cwd()) || importPath
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
// Determine if this is a local or external file
|
|
39
|
+
const isExternal = filePath.startsWith('http://') || filePath.startsWith('https://');
|
|
40
|
+
|
|
41
|
+
// Create a promise for this node
|
|
42
|
+
const promise = (async () => {
|
|
43
|
+
try {
|
|
44
|
+
// Get the file content
|
|
45
|
+
let content: string;
|
|
46
|
+
|
|
47
|
+
if (isExternal) {
|
|
48
|
+
// Fetch external content
|
|
49
|
+
content = await fetchFileContent(filePath);
|
|
50
|
+
} else {
|
|
51
|
+
const baseDir = options.resolveFrom || (file.dirname || process.cwd());
|
|
52
|
+
content = readLocalFile(filePath, baseDir);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Process the content based on regions and line ranges
|
|
56
|
+
let processedContent = processContent(content, regions, lineRanges);
|
|
57
|
+
|
|
58
|
+
// Detect language from file extension
|
|
59
|
+
const language = detectLanguage(filePath);
|
|
60
|
+
|
|
61
|
+
// Replace the paragraph with a code block
|
|
62
|
+
node.type = 'code';
|
|
63
|
+
node.lang = language;
|
|
64
|
+
node.value = processedContent;
|
|
65
|
+
node.children = undefined;
|
|
66
|
+
|
|
67
|
+
} catch (error) {
|
|
68
|
+
console.error(`Error importing file: ${filePath}`, error);
|
|
69
|
+
// Keep the node as is if there's an error
|
|
70
|
+
}
|
|
71
|
+
})();
|
|
72
|
+
|
|
73
|
+
// Add the promise to our collection
|
|
74
|
+
promises.push(promise);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
// Wait for all promises to resolve
|
|
78
|
+
await Promise.all(promises);
|
|
79
|
+
console.timeEnd('plugin:mdFunctionImportCode');
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
@@ -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,349 @@
|
|
|
1
|
+
import * as path from 'node:path';
|
|
2
|
+
import * as fs from 'node:fs';
|
|
3
|
+
import * as os from 'node:os';
|
|
4
|
+
import { VFile } from 'vfile';
|
|
5
|
+
|
|
6
|
+
import { Metadata, Settings } from '@xyd-js/core';
|
|
7
|
+
import { sourcesToUniform, sourcesToUniformV2, type TypeDocReferenceContext } from '@xyd-js/sources/ts';
|
|
8
|
+
import { reactDocgenToUniform, uniformToReactUniform } from '@xyd-js/sources/react';
|
|
9
|
+
import { gqlSchemaToReferences } from "@xyd-js/gql"
|
|
10
|
+
import {oapSchemaToReferences, deferencedOpenAPI, uniformPluginXDocsSidebar} from "@xyd-js/openapi"
|
|
11
|
+
|
|
12
|
+
import { downloadContent, LineRange, parseImportPath, Region, resolvePathAlias } from './utils';
|
|
13
|
+
import uniform, { Reference, ReferenceContext } from '@xyd-js/uniform';
|
|
14
|
+
// TODO: rewrite to async
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Process a uniform function call and return the references
|
|
18
|
+
*
|
|
19
|
+
* @param settings The settings object
|
|
20
|
+
* @param value The value containing the uniform function call
|
|
21
|
+
* @param file The VFile object
|
|
22
|
+
* @param resolveFrom Optional base directory to resolve relative paths from
|
|
23
|
+
* @returns A promise that resolves to the references or null if processing failed
|
|
24
|
+
*/
|
|
25
|
+
export async function processUniformFunctionCall(
|
|
26
|
+
value: string,
|
|
27
|
+
file: VFile,
|
|
28
|
+
resolveFrom?: string,
|
|
29
|
+
settings?: Settings,
|
|
30
|
+
): Promise<Reference[] | null> {
|
|
31
|
+
// Parse the import path to extract file path
|
|
32
|
+
const { filePath, regions, lineRanges } = parseImportPath(value);
|
|
33
|
+
|
|
34
|
+
// Resolve path aliases and get the base directory
|
|
35
|
+
let resolvedFilePath = resolvePathAlias(filePath, settings, process.cwd());
|
|
36
|
+
|
|
37
|
+
if (resolvedFilePath.startsWith("~/")) {
|
|
38
|
+
resolvedFilePath = path.join(process.cwd(), resolvedFilePath.slice(2));
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Process the uniform file
|
|
42
|
+
const references = await processUniformFile(resolvedFilePath, regions, lineRanges, file, resolveFrom);
|
|
43
|
+
|
|
44
|
+
if (!references) {
|
|
45
|
+
return null
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const plugins = globalThis.__xydUserUniformVitePlugins || []
|
|
49
|
+
const matter = file.data?.matter as Metadata
|
|
50
|
+
if (matter?.openapi) {
|
|
51
|
+
plugins.push(uniformPluginXDocsSidebar)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const uniformRefs = uniform(references, {
|
|
55
|
+
plugins: [
|
|
56
|
+
...plugins,
|
|
57
|
+
]
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
return uniformRefs.references
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
async function processUniformFile(
|
|
64
|
+
filePath: string,
|
|
65
|
+
regions: Region[],
|
|
66
|
+
lineRanges: LineRange[],
|
|
67
|
+
file: VFile,
|
|
68
|
+
resolveFrom?: string
|
|
69
|
+
): Promise<any[] | null> {
|
|
70
|
+
try {
|
|
71
|
+
if (!isSupportedProgrammingSource(filePath)) {
|
|
72
|
+
// TODO: openapi + graphql
|
|
73
|
+
throw new Error(`Unsupported file type: ${filePath}`);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
let ext = extension(filePath);
|
|
77
|
+
|
|
78
|
+
const matter = file.data?.matter as Metadata
|
|
79
|
+
if (matter?.openapi) {
|
|
80
|
+
ext = "openapi"
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (isLocalPath(filePath)) {
|
|
84
|
+
const baseDir = resolveFrom || (file.dirname || process.cwd());
|
|
85
|
+
const resolvedFilePath = path.resolve(baseDir, filePath);
|
|
86
|
+
|
|
87
|
+
switch (ext) {
|
|
88
|
+
case 'ts':
|
|
89
|
+
case 'tsx': {
|
|
90
|
+
const packageDir = findClosestPackageJsonDir(
|
|
91
|
+
baseDir,
|
|
92
|
+
filePath,
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
if (packageDir) {
|
|
96
|
+
// Extract the relative file path from the package directory
|
|
97
|
+
const relativeFilePath = path.relative(packageDir, resolvedFilePath);
|
|
98
|
+
|
|
99
|
+
try {
|
|
100
|
+
let references: Reference[] = []
|
|
101
|
+
|
|
102
|
+
switch (ext) {
|
|
103
|
+
case 'ts': {
|
|
104
|
+
const typedocRefs = await sourcesToUniformV2(
|
|
105
|
+
packageDir,
|
|
106
|
+
[relativeFilePath]
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
if (!typedocRefs || !typedocRefs.references) {
|
|
110
|
+
console.error("Failed to process uniform file", filePath)
|
|
111
|
+
break
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
references = typedocRefs.references.filter(ref => {
|
|
115
|
+
const ctx = ref?.context as TypeDocReferenceContext
|
|
116
|
+
|
|
117
|
+
const pathMatch = ctx?.fileFullPath === relativeFilePath
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
if (regions.length > 0) {
|
|
121
|
+
const regionMatch = regions.some(region => {
|
|
122
|
+
return region.name === ctx?.symbolName // TODO: BETTER REGION API FOR TYPEDOC
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
return pathMatch && regionMatch
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return pathMatch
|
|
129
|
+
})
|
|
130
|
+
|
|
131
|
+
break
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
case 'tsx': {
|
|
135
|
+
const resp = await sourcesToUniformV2(
|
|
136
|
+
packageDir,
|
|
137
|
+
[relativeFilePath]
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
if (!resp || !resp.references || !resp.projectJson) {
|
|
141
|
+
console.error("Failed to process uniform file", filePath)
|
|
142
|
+
return null
|
|
143
|
+
}
|
|
144
|
+
const typedocRefs = resp.references as Reference<TypeDocReferenceContext>[]
|
|
145
|
+
|
|
146
|
+
references = uniformToReactUniform(typedocRefs, resp.projectJson)
|
|
147
|
+
|
|
148
|
+
break
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return references
|
|
153
|
+
} finally {
|
|
154
|
+
// Clean up the temporary directory when done
|
|
155
|
+
// cleanupTempFolder(tempDir);
|
|
156
|
+
}
|
|
157
|
+
} else {
|
|
158
|
+
console.error("package.json not found", filePath)
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
case 'graphql': {
|
|
163
|
+
const references = await gqlSchemaToReferences(resolvedFilePath, {
|
|
164
|
+
regions: regions.map(region => region.name),
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
return references;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
case 'openapi': {
|
|
171
|
+
const schema = await deferencedOpenAPI(resolvedFilePath);
|
|
172
|
+
const references = oapSchemaToReferences(schema, {
|
|
173
|
+
regions: regions.map(region => region.name)
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
return references;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
default: {
|
|
180
|
+
throw new Error(`Unsupported file extension: ${ext}`);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
throw new Error("current implementation does not support remote files")
|
|
187
|
+
|
|
188
|
+
// For remote files, download the content
|
|
189
|
+
const content = await downloadContent(
|
|
190
|
+
filePath,
|
|
191
|
+
file,
|
|
192
|
+
resolveFrom,
|
|
193
|
+
);
|
|
194
|
+
|
|
195
|
+
// Fallback to creating temporary folder structure if no package.json found
|
|
196
|
+
const tempDir = await createTempFolderStructure(content);
|
|
197
|
+
|
|
198
|
+
try {
|
|
199
|
+
// Get the path to the package directory
|
|
200
|
+
const tempPackageDir = path.join(tempDir, 'packages', 'package');
|
|
201
|
+
|
|
202
|
+
// Process the content using sourcesToUniform
|
|
203
|
+
const references = await sourcesToUniformV2(
|
|
204
|
+
tempDir,
|
|
205
|
+
[tempPackageDir]
|
|
206
|
+
);
|
|
207
|
+
|
|
208
|
+
return references || null;
|
|
209
|
+
} finally {
|
|
210
|
+
// Clean up the temporary directory when done
|
|
211
|
+
cleanupTempFolder(tempDir);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
} catch (error) {
|
|
215
|
+
console.error(`Error processing uniform file: ${filePath}`, error);
|
|
216
|
+
return null;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Creates a temporary folder structure with package.json, tsconfig.json, and src/index.ts
|
|
223
|
+
* @param content The content to be placed in src/index.ts
|
|
224
|
+
* @returns The path to the temporary directory
|
|
225
|
+
*/
|
|
226
|
+
async function createTempFolderStructure(content: string): Promise<string> {
|
|
227
|
+
// Create a temporary directory
|
|
228
|
+
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'xyd-uniform-'));
|
|
229
|
+
|
|
230
|
+
// Create the package directory
|
|
231
|
+
const packageDir = path.join(tempDir, 'packages', 'package');
|
|
232
|
+
fs.mkdirSync(packageDir, { recursive: true });
|
|
233
|
+
|
|
234
|
+
// Create the src directory
|
|
235
|
+
const srcDir = path.join(packageDir, 'src');
|
|
236
|
+
fs.mkdirSync(srcDir, { recursive: true });
|
|
237
|
+
|
|
238
|
+
// Create package.json
|
|
239
|
+
const packageJson = {
|
|
240
|
+
"name": "@xyd-sources-examples/package-a",
|
|
241
|
+
"main": "dist/index.js"
|
|
242
|
+
};
|
|
243
|
+
fs.writeFileSync(
|
|
244
|
+
path.join(packageDir, 'package.json'),
|
|
245
|
+
JSON.stringify(packageJson, null, 2)
|
|
246
|
+
);
|
|
247
|
+
|
|
248
|
+
// Create tsconfig.json
|
|
249
|
+
const tsconfigJson = {
|
|
250
|
+
"compilerOptions": {
|
|
251
|
+
"outDir": "./dist"
|
|
252
|
+
}
|
|
253
|
+
};
|
|
254
|
+
fs.writeFileSync(
|
|
255
|
+
path.join(packageDir, 'tsconfig.json'),
|
|
256
|
+
JSON.stringify(tsconfigJson, null, 2)
|
|
257
|
+
);
|
|
258
|
+
|
|
259
|
+
// Create src/index.ts with the provided content
|
|
260
|
+
fs.writeFileSync(path.join(srcDir, 'index.ts'), content);
|
|
261
|
+
|
|
262
|
+
return tempDir;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Cleans up the temporary folder structure
|
|
267
|
+
* @param tempDir The path to the temporary directory
|
|
268
|
+
*/
|
|
269
|
+
function cleanupTempFolder(tempDir: string): void {
|
|
270
|
+
try {
|
|
271
|
+
// Recursively delete the temporary directory
|
|
272
|
+
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
273
|
+
} catch (error) {
|
|
274
|
+
console.error(`Error cleaning up temporary directory: ${tempDir}`, error);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
const supportedProgrammingExtensions: Record<string, boolean> = {
|
|
279
|
+
'ts': true,
|
|
280
|
+
'tsx': true,
|
|
281
|
+
'graphql': true,
|
|
282
|
+
'yaml': true,
|
|
283
|
+
'yml': true,
|
|
284
|
+
'json': true,
|
|
285
|
+
|
|
286
|
+
// TODO
|
|
287
|
+
// 'py': true,
|
|
288
|
+
// 'go': true,
|
|
289
|
+
// TODO: AND OTHER PROGRAMMING LANGUAGES IN THE FUTEURE
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Check if a file is a programming source file based on its extension
|
|
294
|
+
* @param filePath The path to the file
|
|
295
|
+
* @returns True if the file is a programming source file
|
|
296
|
+
*/
|
|
297
|
+
function isSupportedProgrammingSource(filePath: string) {
|
|
298
|
+
const ext = extension(filePath);
|
|
299
|
+
|
|
300
|
+
if (supportedProgrammingExtensions[ext]) {
|
|
301
|
+
return true;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
return false;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
function extension(filePath: string) {
|
|
308
|
+
return path.extname(filePath).toLowerCase().replace('.', '');
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* Find the closest package.json directory for a given file path
|
|
313
|
+
* @param baseDir The base directory to start searching from (used as cwd for resolving relative paths)
|
|
314
|
+
* @param filePath The path to the file (can be relative)
|
|
315
|
+
* @returns The path to the directory containing package.json, or null if not found
|
|
316
|
+
*/
|
|
317
|
+
function findClosestPackageJsonDir(
|
|
318
|
+
baseDir: string,
|
|
319
|
+
filePath: string
|
|
320
|
+
): string | null {
|
|
321
|
+
// Resolve the filePath relative to baseDir
|
|
322
|
+
const resolvedFilePath = path.resolve(baseDir, filePath);
|
|
323
|
+
let currentDir = path.dirname(resolvedFilePath);
|
|
324
|
+
const root = path.parse(currentDir).root;
|
|
325
|
+
|
|
326
|
+
while (currentDir !== root) {
|
|
327
|
+
try {
|
|
328
|
+
const files = fs.readdirSync(currentDir);
|
|
329
|
+
if (files.includes('package.json')) {
|
|
330
|
+
return currentDir;
|
|
331
|
+
}
|
|
332
|
+
} catch (error) {
|
|
333
|
+
// If we can't read the directory, move up
|
|
334
|
+
console.warn(`Cannot read directory ${currentDir}:`, error);
|
|
335
|
+
}
|
|
336
|
+
currentDir = path.dirname(currentDir);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
return null;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* Check if a path is a local file path (not a URL)
|
|
344
|
+
* @param filePath The path to check
|
|
345
|
+
* @returns True if the path is local
|
|
346
|
+
*/
|
|
347
|
+
function isLocalPath(filePath: string): boolean {
|
|
348
|
+
return !filePath.startsWith('http://') && !filePath.startsWith('https://');
|
|
349
|
+
}
|