@rspress/plugin-typedoc 0.0.0-nightly-20241127160234 → 0.0.0-nightly-20241128160245
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/dist/es/index.mjs +64 -129
- package/dist/lib/index.js +64 -129
- package/package.json +5 -5
- package/src/constants.ts +0 -1
- package/src/index.ts +39 -33
- package/src/patch.ts +72 -0
- package/src/sidebar.ts +0 -179
package/dist/es/index.mjs
CHANGED
|
@@ -3,134 +3,69 @@ import * as __WEBPACK_EXTERNAL_MODULE_typedoc__ from "typedoc";
|
|
|
3
3
|
import * as __WEBPACK_EXTERNAL_MODULE_typedoc_plugin_markdown__ from "typedoc-plugin-markdown";
|
|
4
4
|
import * as __WEBPACK_EXTERNAL_MODULE__rspress_shared_fs_extra__ from "@rspress/shared/fs-extra";
|
|
5
5
|
const API_DIR = 'api';
|
|
6
|
-
const ROUTE_PREFIX = `/${API_DIR}`;
|
|
7
|
-
function transformModuleName(name) {
|
|
8
|
-
return name.replace(/\//g, '_').replace(/-/g, '_');
|
|
9
|
-
}
|
|
10
6
|
async function patchLinks(outputDir) {
|
|
11
7
|
// Patch links in markdown files
|
|
12
8
|
// Scan all the markdown files in the output directory
|
|
13
|
-
// replace
|
|
9
|
+
// replace
|
|
10
|
+
// 1. [foo](bar) -> [foo](./bar)
|
|
11
|
+
// 2. [foo](./bar) -> [foo](./bar) no change
|
|
14
12
|
const normlizeLinksInFile = async (filePath)=>{
|
|
15
13
|
const content = await __WEBPACK_EXTERNAL_MODULE__rspress_shared_fs_extra__["default"].readFile(filePath, 'utf-8');
|
|
16
|
-
//
|
|
17
|
-
const newContent = content.replace(/\[([^\]]+)\]\(([^)]+)\)/g, (_match, p1, p2)
|
|
14
|
+
// 1. [foo](bar) -> [foo](./bar)
|
|
15
|
+
const newContent = content.replace(/\[([^\]]+)\]\(([^)]+)\)/g, (_match, p1, p2)=>{
|
|
16
|
+
// 2. [foo](./bar) -> [foo](./bar) no change
|
|
17
|
+
if ([
|
|
18
|
+
'/',
|
|
19
|
+
'.'
|
|
20
|
+
].includes(p2[0])) return `[${p1}](${p2})`;
|
|
21
|
+
return `[${p1}](./${p2})`;
|
|
22
|
+
});
|
|
18
23
|
await __WEBPACK_EXTERNAL_MODULE__rspress_shared_fs_extra__["default"].writeFile(filePath, newContent);
|
|
19
24
|
};
|
|
20
25
|
const traverse = async (dir)=>{
|
|
21
26
|
const files = await __WEBPACK_EXTERNAL_MODULE__rspress_shared_fs_extra__["default"].readdir(dir);
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
27
|
+
const filePaths = files.map((file)=>__WEBPACK_EXTERNAL_MODULE_node_path__["default"].join(dir, file));
|
|
28
|
+
const stats = await Promise.all(filePaths.map((fp)=>__WEBPACK_EXTERNAL_MODULE__rspress_shared_fs_extra__["default"].stat(fp)));
|
|
29
|
+
await Promise.all(stats.map((stat, index)=>{
|
|
30
|
+
const file = files[index];
|
|
31
|
+
const filePath = filePaths[index];
|
|
32
|
+
if (stat.isDirectory()) return traverse(filePath);
|
|
33
|
+
if (stat.isFile() && /\.mdx?/.test(file)) return normlizeLinksInFile(filePath);
|
|
34
|
+
}));
|
|
28
35
|
};
|
|
29
36
|
await traverse(outputDir);
|
|
30
37
|
}
|
|
31
|
-
async function
|
|
32
|
-
const
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
// The final output file name should be `classes/Env.md` and `variables/env-1.md`
|
|
47
|
-
let fileName = dataItem.name;
|
|
48
|
-
if (symbolMap.has(dataItem.name)) {
|
|
49
|
-
const count = symbolMap.get(dataItem.name) + 1;
|
|
50
|
-
symbolMap.set(dataItem.name, count);
|
|
51
|
-
fileName = `${dataItem.name}-${count}`;
|
|
52
|
-
} else symbolMap.set(dataItem.name.toLocaleLowerCase(), 0);
|
|
53
|
-
groupItem.items.push({
|
|
54
|
-
text: dataItem.name,
|
|
55
|
-
link: `${ROUTE_PREFIX}/${group.title.toLocaleLowerCase()}/${fileName}`
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
});
|
|
59
|
-
result.push(groupItem);
|
|
60
|
-
});
|
|
61
|
-
await patchLinks(__WEBPACK_EXTERNAL_MODULE_node_path__["default"].dirname(jsonFile));
|
|
62
|
-
return result;
|
|
38
|
+
async function generateMetaJson(absoluteApiDir) {
|
|
39
|
+
const metaJsonPath = __WEBPACK_EXTERNAL_MODULE_node_path__["default"].join(absoluteApiDir, '_meta.json');
|
|
40
|
+
const files = await __WEBPACK_EXTERNAL_MODULE__rspress_shared_fs_extra__["default"].readdir(absoluteApiDir);
|
|
41
|
+
const filePaths = files.map((file)=>__WEBPACK_EXTERNAL_MODULE_node_path__["default"].join(absoluteApiDir, file));
|
|
42
|
+
const stats = await Promise.all(filePaths.map((fp)=>__WEBPACK_EXTERNAL_MODULE__rspress_shared_fs_extra__["default"].stat(fp)));
|
|
43
|
+
const dirs = stats.map((stat, index)=>stat.isDirectory() ? files[index] : null).filter(Boolean);
|
|
44
|
+
const meta = dirs.map((dir)=>({
|
|
45
|
+
type: 'dir',
|
|
46
|
+
label: dir.slice(0, 1).toUpperCase() + dir.slice(1),
|
|
47
|
+
name: dir
|
|
48
|
+
}));
|
|
49
|
+
await __WEBPACK_EXTERNAL_MODULE__rspress_shared_fs_extra__["default"].writeFile(metaJsonPath, JSON.stringify([
|
|
50
|
+
'index',
|
|
51
|
+
...meta
|
|
52
|
+
]));
|
|
63
53
|
}
|
|
64
|
-
async function
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
function getModulePath(name) {
|
|
69
|
-
return __WEBPACK_EXTERNAL_MODULE_node_path__["default"].join(`${ROUTE_PREFIX}/modules`, `${transformModuleName(name)}`).replace(/\\/g, '/');
|
|
70
|
-
}
|
|
71
|
-
function getClassPath(moduleName, className) {
|
|
72
|
-
return __WEBPACK_EXTERNAL_MODULE_node_path__["default"].join(`${ROUTE_PREFIX}/classes`, `${transformModuleName(moduleName)}.${className}`).replace(/\\/g, '/');
|
|
73
|
-
}
|
|
74
|
-
function getInterfacePath(moduleName, interfaceName) {
|
|
75
|
-
return __WEBPACK_EXTERNAL_MODULE_node_path__["default"].join(`${ROUTE_PREFIX}/interfaces`, `${transformModuleName(moduleName)}.${interfaceName}`).replace(/\\/g, '/');
|
|
76
|
-
}
|
|
77
|
-
function getFunctionPath(moduleName, functionName) {
|
|
78
|
-
return __WEBPACK_EXTERNAL_MODULE_node_path__["default"].join(`${ROUTE_PREFIX}/functions`, `${transformModuleName(moduleName)}.${functionName}`).replace(/\\/g, '/');
|
|
79
|
-
}
|
|
80
|
-
data.children.forEach((module)=>{
|
|
81
|
-
const moduleNames = module.name.split('/');
|
|
82
|
-
const name = moduleNames[moduleNames.length - 1];
|
|
83
|
-
const moduleConfig = {
|
|
84
|
-
text: `Module:${name}`,
|
|
85
|
-
items: [
|
|
86
|
-
{
|
|
87
|
-
text: 'Overview',
|
|
88
|
-
link: getModulePath(module.name)
|
|
89
|
-
}
|
|
90
|
-
]
|
|
91
|
-
};
|
|
92
|
-
if (!module.children || module.children.length <= 0) return;
|
|
93
|
-
module.children.forEach((sub)=>{
|
|
94
|
-
var _module_groups_find;
|
|
95
|
-
const kindString = null === (_module_groups_find = module.groups.find((item)=>item.children.includes(sub.id))) || void 0 === _module_groups_find ? void 0 : _module_groups_find.title.slice(0, -1);
|
|
96
|
-
if (!kindString) return;
|
|
97
|
-
switch(kindString){
|
|
98
|
-
case 'Class':
|
|
99
|
-
moduleConfig.items.push({
|
|
100
|
-
text: `Class:${sub.name}`,
|
|
101
|
-
link: getClassPath(module.name, sub.name)
|
|
102
|
-
});
|
|
103
|
-
break;
|
|
104
|
-
case 'Interface':
|
|
105
|
-
moduleConfig.items.push({
|
|
106
|
-
text: `Interface:${sub.name}`,
|
|
107
|
-
link: getInterfacePath(module.name, sub.name)
|
|
108
|
-
});
|
|
109
|
-
break;
|
|
110
|
-
case 'Function':
|
|
111
|
-
moduleConfig.items.push({
|
|
112
|
-
text: `Function:${sub.name}`,
|
|
113
|
-
link: getFunctionPath(module.name, sub.name)
|
|
114
|
-
});
|
|
115
|
-
break;
|
|
116
|
-
default:
|
|
117
|
-
break;
|
|
118
|
-
}
|
|
119
|
-
});
|
|
120
|
-
result.push(moduleConfig);
|
|
121
|
-
});
|
|
122
|
-
await patchLinks(__WEBPACK_EXTERNAL_MODULE_node_path__["default"].dirname(jsonFile));
|
|
123
|
-
return result;
|
|
54
|
+
async function patchGeneratedApiDocs(absoluteApiDir) {
|
|
55
|
+
await patchLinks(absoluteApiDir);
|
|
56
|
+
await __WEBPACK_EXTERNAL_MODULE__rspress_shared_fs_extra__["default"].rename(__WEBPACK_EXTERNAL_MODULE_node_path__["default"].join(absoluteApiDir, 'README.md'), __WEBPACK_EXTERNAL_MODULE_node_path__["default"].join(absoluteApiDir, 'index.md'));
|
|
57
|
+
await generateMetaJson(absoluteApiDir);
|
|
124
58
|
}
|
|
125
59
|
function pluginTypeDoc(options) {
|
|
126
60
|
let docRoot;
|
|
127
61
|
const { entryPoints = [], outDir = API_DIR } = options;
|
|
62
|
+
const apiPageRoute = `/${outDir.replace(/(^\/)|(\/$)/, '')}/`; // e.g: /api/
|
|
128
63
|
return {
|
|
129
64
|
name: '@rspress/plugin-typedoc',
|
|
130
65
|
async addPages () {
|
|
131
66
|
return [
|
|
132
67
|
{
|
|
133
|
-
routePath:
|
|
68
|
+
routePath: apiPageRoute,
|
|
134
69
|
filepath: __WEBPACK_EXTERNAL_MODULE_node_path__["default"].join(docRoot, outDir, 'README.md')
|
|
135
70
|
}
|
|
136
71
|
];
|
|
@@ -162,34 +97,34 @@ function pluginTypeDoc(options) {
|
|
|
162
97
|
});
|
|
163
98
|
const project = app.convert();
|
|
164
99
|
if (project) {
|
|
165
|
-
// 1. Generate
|
|
166
|
-
const
|
|
167
|
-
await app.generateDocs(project,
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
// 2. Generate sidebar
|
|
100
|
+
// 1. Generate doc/api, doc/api/_meta.json by typedoc
|
|
101
|
+
const absoluteApiDir = __WEBPACK_EXTERNAL_MODULE_node_path__["default"].join(docRoot, outDir);
|
|
102
|
+
await app.generateDocs(project, absoluteApiDir);
|
|
103
|
+
await patchGeneratedApiDocs(absoluteApiDir);
|
|
104
|
+
// 2. Generate "api" nav bar
|
|
171
105
|
config.themeConfig = config.themeConfig || {};
|
|
172
106
|
config.themeConfig.nav = config.themeConfig.nav || [];
|
|
173
|
-
const apiIndexLink = `/${outDir.replace(/(^\/)|(\/$)/, '')}/`;
|
|
174
107
|
const { nav } = config.themeConfig;
|
|
108
|
+
// avoid that user config "api" in doc/_meta.json
|
|
109
|
+
function isApiAlreadyInNav(navList) {
|
|
110
|
+
return navList.some((item)=>{
|
|
111
|
+
if ('link' in item && 'string' == typeof item.link && item.link.startsWith(apiPageRoute.slice(0, apiPageRoute.length - 1))) return true;
|
|
112
|
+
return false;
|
|
113
|
+
});
|
|
114
|
+
}
|
|
175
115
|
// Note: TypeDoc does not support i18n
|
|
176
|
-
if (Array.isArray(nav))
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
text: 'Overview',
|
|
188
|
-
link: `${apiIndexLink}README`
|
|
189
|
-
});
|
|
116
|
+
if (Array.isArray(nav)) {
|
|
117
|
+
if (!isApiAlreadyInNav(nav)) nav.push({
|
|
118
|
+
text: 'API',
|
|
119
|
+
link: apiPageRoute
|
|
120
|
+
});
|
|
121
|
+
} else if ('default' in nav) {
|
|
122
|
+
if (!isApiAlreadyInNav(nav.default)) nav.default.push({
|
|
123
|
+
text: 'API',
|
|
124
|
+
link: apiPageRoute
|
|
125
|
+
});
|
|
126
|
+
}
|
|
190
127
|
}
|
|
191
|
-
config.route = config.route || {};
|
|
192
|
-
config.route.exclude = config.route.exclude || [];
|
|
193
128
|
return config;
|
|
194
129
|
}
|
|
195
130
|
};
|
package/dist/lib/index.js
CHANGED
|
@@ -55,136 +55,71 @@ var external_node_path_default = /*#__PURE__*/ __webpack_require__.n(external_no
|
|
|
55
55
|
const external_typedoc_namespaceObject = require("typedoc");
|
|
56
56
|
const external_typedoc_plugin_markdown_namespaceObject = require("typedoc-plugin-markdown");
|
|
57
57
|
const API_DIR = 'api';
|
|
58
|
-
const ROUTE_PREFIX = `/${API_DIR}`;
|
|
59
58
|
const fs_extra_namespaceObject = require("@rspress/shared/fs-extra");
|
|
60
59
|
var fs_extra_default = /*#__PURE__*/ __webpack_require__.n(fs_extra_namespaceObject);
|
|
61
|
-
function transformModuleName(name) {
|
|
62
|
-
return name.replace(/\//g, '_').replace(/-/g, '_');
|
|
63
|
-
}
|
|
64
60
|
async function patchLinks(outputDir) {
|
|
65
61
|
// Patch links in markdown files
|
|
66
62
|
// Scan all the markdown files in the output directory
|
|
67
|
-
// replace
|
|
63
|
+
// replace
|
|
64
|
+
// 1. [foo](bar) -> [foo](./bar)
|
|
65
|
+
// 2. [foo](./bar) -> [foo](./bar) no change
|
|
68
66
|
const normlizeLinksInFile = async (filePath)=>{
|
|
69
67
|
const content = await fs_extra_default().readFile(filePath, 'utf-8');
|
|
70
|
-
//
|
|
71
|
-
const newContent = content.replace(/\[([^\]]+)\]\(([^)]+)\)/g, (_match, p1, p2)
|
|
68
|
+
// 1. [foo](bar) -> [foo](./bar)
|
|
69
|
+
const newContent = content.replace(/\[([^\]]+)\]\(([^)]+)\)/g, (_match, p1, p2)=>{
|
|
70
|
+
// 2. [foo](./bar) -> [foo](./bar) no change
|
|
71
|
+
if ([
|
|
72
|
+
'/',
|
|
73
|
+
'.'
|
|
74
|
+
].includes(p2[0])) return `[${p1}](${p2})`;
|
|
75
|
+
return `[${p1}](./${p2})`;
|
|
76
|
+
});
|
|
72
77
|
await fs_extra_default().writeFile(filePath, newContent);
|
|
73
78
|
};
|
|
74
79
|
const traverse = async (dir)=>{
|
|
75
80
|
const files = await fs_extra_default().readdir(dir);
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
81
|
+
const filePaths = files.map((file)=>external_node_path_default().join(dir, file));
|
|
82
|
+
const stats = await Promise.all(filePaths.map((fp)=>fs_extra_default().stat(fp)));
|
|
83
|
+
await Promise.all(stats.map((stat, index)=>{
|
|
84
|
+
const file = files[index];
|
|
85
|
+
const filePath = filePaths[index];
|
|
86
|
+
if (stat.isDirectory()) return traverse(filePath);
|
|
87
|
+
if (stat.isFile() && /\.mdx?/.test(file)) return normlizeLinksInFile(filePath);
|
|
88
|
+
}));
|
|
82
89
|
};
|
|
83
90
|
await traverse(outputDir);
|
|
84
91
|
}
|
|
85
|
-
async function
|
|
86
|
-
const
|
|
87
|
-
const
|
|
88
|
-
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
// The final output file name should be `classes/Env.md` and `variables/env-1.md`
|
|
101
|
-
let fileName = dataItem.name;
|
|
102
|
-
if (symbolMap.has(dataItem.name)) {
|
|
103
|
-
const count = symbolMap.get(dataItem.name) + 1;
|
|
104
|
-
symbolMap.set(dataItem.name, count);
|
|
105
|
-
fileName = `${dataItem.name}-${count}`;
|
|
106
|
-
} else symbolMap.set(dataItem.name.toLocaleLowerCase(), 0);
|
|
107
|
-
groupItem.items.push({
|
|
108
|
-
text: dataItem.name,
|
|
109
|
-
link: `${ROUTE_PREFIX}/${group.title.toLocaleLowerCase()}/${fileName}`
|
|
110
|
-
});
|
|
111
|
-
}
|
|
112
|
-
});
|
|
113
|
-
result.push(groupItem);
|
|
114
|
-
});
|
|
115
|
-
await patchLinks(external_node_path_default().dirname(jsonFile));
|
|
116
|
-
return result;
|
|
92
|
+
async function generateMetaJson(absoluteApiDir) {
|
|
93
|
+
const metaJsonPath = external_node_path_default().join(absoluteApiDir, '_meta.json');
|
|
94
|
+
const files = await fs_extra_default().readdir(absoluteApiDir);
|
|
95
|
+
const filePaths = files.map((file)=>external_node_path_default().join(absoluteApiDir, file));
|
|
96
|
+
const stats = await Promise.all(filePaths.map((fp)=>fs_extra_default().stat(fp)));
|
|
97
|
+
const dirs = stats.map((stat, index)=>stat.isDirectory() ? files[index] : null).filter(Boolean);
|
|
98
|
+
const meta = dirs.map((dir)=>({
|
|
99
|
+
type: 'dir',
|
|
100
|
+
label: dir.slice(0, 1).toUpperCase() + dir.slice(1),
|
|
101
|
+
name: dir
|
|
102
|
+
}));
|
|
103
|
+
await fs_extra_default().writeFile(metaJsonPath, JSON.stringify([
|
|
104
|
+
'index',
|
|
105
|
+
...meta
|
|
106
|
+
]));
|
|
117
107
|
}
|
|
118
|
-
async function
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
function getModulePath(name) {
|
|
123
|
-
return external_node_path_default().join(`${ROUTE_PREFIX}/modules`, `${transformModuleName(name)}`).replace(/\\/g, '/');
|
|
124
|
-
}
|
|
125
|
-
function getClassPath(moduleName, className) {
|
|
126
|
-
return external_node_path_default().join(`${ROUTE_PREFIX}/classes`, `${transformModuleName(moduleName)}.${className}`).replace(/\\/g, '/');
|
|
127
|
-
}
|
|
128
|
-
function getInterfacePath(moduleName, interfaceName) {
|
|
129
|
-
return external_node_path_default().join(`${ROUTE_PREFIX}/interfaces`, `${transformModuleName(moduleName)}.${interfaceName}`).replace(/\\/g, '/');
|
|
130
|
-
}
|
|
131
|
-
function getFunctionPath(moduleName, functionName) {
|
|
132
|
-
return external_node_path_default().join(`${ROUTE_PREFIX}/functions`, `${transformModuleName(moduleName)}.${functionName}`).replace(/\\/g, '/');
|
|
133
|
-
}
|
|
134
|
-
data.children.forEach((module)=>{
|
|
135
|
-
const moduleNames = module.name.split('/');
|
|
136
|
-
const name = moduleNames[moduleNames.length - 1];
|
|
137
|
-
const moduleConfig = {
|
|
138
|
-
text: `Module:${name}`,
|
|
139
|
-
items: [
|
|
140
|
-
{
|
|
141
|
-
text: 'Overview',
|
|
142
|
-
link: getModulePath(module.name)
|
|
143
|
-
}
|
|
144
|
-
]
|
|
145
|
-
};
|
|
146
|
-
if (!module.children || module.children.length <= 0) return;
|
|
147
|
-
module.children.forEach((sub)=>{
|
|
148
|
-
var _module_groups_find;
|
|
149
|
-
const kindString = null === (_module_groups_find = module.groups.find((item)=>item.children.includes(sub.id))) || void 0 === _module_groups_find ? void 0 : _module_groups_find.title.slice(0, -1);
|
|
150
|
-
if (!kindString) return;
|
|
151
|
-
switch(kindString){
|
|
152
|
-
case 'Class':
|
|
153
|
-
moduleConfig.items.push({
|
|
154
|
-
text: `Class:${sub.name}`,
|
|
155
|
-
link: getClassPath(module.name, sub.name)
|
|
156
|
-
});
|
|
157
|
-
break;
|
|
158
|
-
case 'Interface':
|
|
159
|
-
moduleConfig.items.push({
|
|
160
|
-
text: `Interface:${sub.name}`,
|
|
161
|
-
link: getInterfacePath(module.name, sub.name)
|
|
162
|
-
});
|
|
163
|
-
break;
|
|
164
|
-
case 'Function':
|
|
165
|
-
moduleConfig.items.push({
|
|
166
|
-
text: `Function:${sub.name}`,
|
|
167
|
-
link: getFunctionPath(module.name, sub.name)
|
|
168
|
-
});
|
|
169
|
-
break;
|
|
170
|
-
default:
|
|
171
|
-
break;
|
|
172
|
-
}
|
|
173
|
-
});
|
|
174
|
-
result.push(moduleConfig);
|
|
175
|
-
});
|
|
176
|
-
await patchLinks(external_node_path_default().dirname(jsonFile));
|
|
177
|
-
return result;
|
|
108
|
+
async function patchGeneratedApiDocs(absoluteApiDir) {
|
|
109
|
+
await patchLinks(absoluteApiDir);
|
|
110
|
+
await fs_extra_default().rename(external_node_path_default().join(absoluteApiDir, 'README.md'), external_node_path_default().join(absoluteApiDir, 'index.md'));
|
|
111
|
+
await generateMetaJson(absoluteApiDir);
|
|
178
112
|
}
|
|
179
113
|
function pluginTypeDoc(options) {
|
|
180
114
|
let docRoot;
|
|
181
115
|
const { entryPoints = [], outDir = API_DIR } = options;
|
|
116
|
+
const apiPageRoute = `/${outDir.replace(/(^\/)|(\/$)/, '')}/`; // e.g: /api/
|
|
182
117
|
return {
|
|
183
118
|
name: '@rspress/plugin-typedoc',
|
|
184
119
|
async addPages () {
|
|
185
120
|
return [
|
|
186
121
|
{
|
|
187
|
-
routePath:
|
|
122
|
+
routePath: apiPageRoute,
|
|
188
123
|
filepath: external_node_path_default().join(docRoot, outDir, 'README.md')
|
|
189
124
|
}
|
|
190
125
|
];
|
|
@@ -216,34 +151,34 @@ function pluginTypeDoc(options) {
|
|
|
216
151
|
});
|
|
217
152
|
const project = app.convert();
|
|
218
153
|
if (project) {
|
|
219
|
-
// 1. Generate
|
|
220
|
-
const
|
|
221
|
-
await app.generateDocs(project,
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
// 2. Generate sidebar
|
|
154
|
+
// 1. Generate doc/api, doc/api/_meta.json by typedoc
|
|
155
|
+
const absoluteApiDir = external_node_path_default().join(docRoot, outDir);
|
|
156
|
+
await app.generateDocs(project, absoluteApiDir);
|
|
157
|
+
await patchGeneratedApiDocs(absoluteApiDir);
|
|
158
|
+
// 2. Generate "api" nav bar
|
|
225
159
|
config.themeConfig = config.themeConfig || {};
|
|
226
160
|
config.themeConfig.nav = config.themeConfig.nav || [];
|
|
227
|
-
const apiIndexLink = `/${outDir.replace(/(^\/)|(\/$)/, '')}/`;
|
|
228
161
|
const { nav } = config.themeConfig;
|
|
162
|
+
// avoid that user config "api" in doc/_meta.json
|
|
163
|
+
function isApiAlreadyInNav(navList) {
|
|
164
|
+
return navList.some((item)=>{
|
|
165
|
+
if ('link' in item && 'string' == typeof item.link && item.link.startsWith(apiPageRoute.slice(0, apiPageRoute.length - 1))) return true;
|
|
166
|
+
return false;
|
|
167
|
+
});
|
|
168
|
+
}
|
|
229
169
|
// Note: TypeDoc does not support i18n
|
|
230
|
-
if (Array.isArray(nav))
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
text: 'Overview',
|
|
242
|
-
link: `${apiIndexLink}README`
|
|
243
|
-
});
|
|
170
|
+
if (Array.isArray(nav)) {
|
|
171
|
+
if (!isApiAlreadyInNav(nav)) nav.push({
|
|
172
|
+
text: 'API',
|
|
173
|
+
link: apiPageRoute
|
|
174
|
+
});
|
|
175
|
+
} else if ('default' in nav) {
|
|
176
|
+
if (!isApiAlreadyInNav(nav.default)) nav.default.push({
|
|
177
|
+
text: 'API',
|
|
178
|
+
link: apiPageRoute
|
|
179
|
+
});
|
|
180
|
+
}
|
|
244
181
|
}
|
|
245
|
-
config.route = config.route || {};
|
|
246
|
-
config.route.exclude = config.route.exclude || [];
|
|
247
182
|
return config;
|
|
248
183
|
}
|
|
249
184
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rspress/plugin-typedoc",
|
|
3
|
-
"version": "0.0.0-nightly-
|
|
3
|
+
"version": "0.0.0-nightly-20241128160245",
|
|
4
4
|
"description": "A plugin for rspress to integrate typedoc",
|
|
5
5
|
"bugs": "https://github.com/web-infra-dev/rspress/issues",
|
|
6
6
|
"repository": {
|
|
@@ -17,9 +17,9 @@
|
|
|
17
17
|
"node": ">=14.17.6"
|
|
18
18
|
},
|
|
19
19
|
"devDependencies": {
|
|
20
|
-
"@modern-js/tsconfig": "2.62.1",
|
|
21
|
-
"@rslib/core": "0.1.0",
|
|
22
20
|
"@microsoft/api-extractor": "^7.48.0",
|
|
21
|
+
"@modern-js/tsconfig": "2.63.0",
|
|
22
|
+
"@rslib/core": "0.1.0",
|
|
23
23
|
"@types/node": "^18.11.17",
|
|
24
24
|
"@types/react": "^18.3.12",
|
|
25
25
|
"@types/react-dom": "^18.3.1",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"vitest": "2.1.5"
|
|
29
29
|
},
|
|
30
30
|
"peerDependencies": {
|
|
31
|
-
"rspress": "0.0.0-nightly-
|
|
31
|
+
"rspress": "0.0.0-nightly-20241128160245"
|
|
32
32
|
},
|
|
33
33
|
"sideEffects": [
|
|
34
34
|
"*.css",
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
"dependencies": {
|
|
49
49
|
"typedoc": "0.24.8",
|
|
50
50
|
"typedoc-plugin-markdown": "3.17.1",
|
|
51
|
-
"@rspress/shared": "0.0.0-nightly-
|
|
51
|
+
"@rspress/shared": "0.0.0-nightly-20241128160245"
|
|
52
52
|
},
|
|
53
53
|
"scripts": {
|
|
54
54
|
"dev": "rslib build -w",
|
package/src/constants.ts
CHANGED
package/src/index.ts
CHANGED
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
import { Application, TSConfigReader } from 'typedoc';
|
|
3
|
-
import type { RspressPlugin } from '@rspress/shared';
|
|
3
|
+
import type { NavItem, RspressPlugin } from '@rspress/shared';
|
|
4
4
|
import { load } from 'typedoc-plugin-markdown';
|
|
5
5
|
import { API_DIR } from './constants';
|
|
6
|
-
import {
|
|
7
|
-
resolveSidebarForMultiEntry,
|
|
8
|
-
resolveSidebarForSingleEntry,
|
|
9
|
-
} from './sidebar';
|
|
6
|
+
import { patchGeneratedApiDocs } from './patch';
|
|
10
7
|
|
|
11
8
|
export interface PluginTypeDocOptions {
|
|
12
9
|
/**
|
|
@@ -24,12 +21,13 @@ export interface PluginTypeDocOptions {
|
|
|
24
21
|
export function pluginTypeDoc(options: PluginTypeDocOptions): RspressPlugin {
|
|
25
22
|
let docRoot: string | undefined;
|
|
26
23
|
const { entryPoints = [], outDir = API_DIR } = options;
|
|
24
|
+
const apiPageRoute = `/${outDir.replace(/(^\/)|(\/$)/, '')}/`; // e.g: /api/
|
|
27
25
|
return {
|
|
28
26
|
name: '@rspress/plugin-typedoc',
|
|
29
27
|
async addPages() {
|
|
30
28
|
return [
|
|
31
29
|
{
|
|
32
|
-
routePath:
|
|
30
|
+
routePath: apiPageRoute,
|
|
33
31
|
filepath: path.join(docRoot!, outDir, 'README.md'),
|
|
34
32
|
},
|
|
35
33
|
];
|
|
@@ -56,41 +54,49 @@ export function pluginTypeDoc(options: PluginTypeDocOptions): RspressPlugin {
|
|
|
56
54
|
const project = app.convert();
|
|
57
55
|
|
|
58
56
|
if (project) {
|
|
59
|
-
// 1. Generate
|
|
60
|
-
const
|
|
61
|
-
await app.generateDocs(project,
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
// 2. Generate
|
|
57
|
+
// 1. Generate doc/api, doc/api/_meta.json by typedoc
|
|
58
|
+
const absoluteApiDir = path.join(docRoot!, outDir);
|
|
59
|
+
await app.generateDocs(project, absoluteApiDir);
|
|
60
|
+
await patchGeneratedApiDocs(absoluteApiDir);
|
|
61
|
+
|
|
62
|
+
// 2. Generate "api" nav bar
|
|
65
63
|
config.themeConfig = config.themeConfig || {};
|
|
66
64
|
config.themeConfig.nav = config.themeConfig.nav || [];
|
|
67
|
-
const apiIndexLink = `/${outDir.replace(/(^\/)|(\/$)/, '')}/`;
|
|
68
65
|
const { nav } = config.themeConfig;
|
|
66
|
+
|
|
67
|
+
// avoid that user config "api" in doc/_meta.json
|
|
68
|
+
function isApiAlreadyInNav(navList: NavItem[]) {
|
|
69
|
+
return navList.some(item => {
|
|
70
|
+
if (
|
|
71
|
+
'link' in item &&
|
|
72
|
+
typeof item.link === 'string' &&
|
|
73
|
+
item.link.startsWith(
|
|
74
|
+
apiPageRoute.slice(0, apiPageRoute.length - 1), // /api
|
|
75
|
+
)
|
|
76
|
+
) {
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
return false;
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
|
|
69
83
|
// Note: TypeDoc does not support i18n
|
|
70
84
|
if (Array.isArray(nav)) {
|
|
71
|
-
nav
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
85
|
+
if (!isApiAlreadyInNav(nav)) {
|
|
86
|
+
nav.push({
|
|
87
|
+
text: 'API',
|
|
88
|
+
link: apiPageRoute,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
75
91
|
} else if ('default' in nav) {
|
|
76
|
-
nav.default
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
92
|
+
if (!isApiAlreadyInNav(nav.default)) {
|
|
93
|
+
nav.default.push({
|
|
94
|
+
text: 'API',
|
|
95
|
+
link: apiPageRoute,
|
|
96
|
+
});
|
|
97
|
+
}
|
|
80
98
|
}
|
|
81
|
-
|
|
82
|
-
config.themeConfig.sidebar = config.themeConfig.sidebar || {};
|
|
83
|
-
config.themeConfig.sidebar[apiIndexLink] =
|
|
84
|
-
entryPoints.length > 1
|
|
85
|
-
? await resolveSidebarForMultiEntry(jsonDir)
|
|
86
|
-
: await resolveSidebarForSingleEntry(jsonDir);
|
|
87
|
-
config.themeConfig.sidebar[apiIndexLink].unshift({
|
|
88
|
-
text: 'Overview',
|
|
89
|
-
link: `${apiIndexLink}README`,
|
|
90
|
-
});
|
|
91
99
|
}
|
|
92
|
-
config.route = config.route || {};
|
|
93
|
-
config.route.exclude = config.route.exclude || [];
|
|
94
100
|
return config;
|
|
95
101
|
},
|
|
96
102
|
};
|
package/src/patch.ts
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import fs from '@rspress/shared/fs-extra';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
|
|
4
|
+
async function patchLinks(outputDir: string) {
|
|
5
|
+
// Patch links in markdown files
|
|
6
|
+
// Scan all the markdown files in the output directory
|
|
7
|
+
// replace
|
|
8
|
+
// 1. [foo](bar) -> [foo](./bar)
|
|
9
|
+
// 2. [foo](./bar) -> [foo](./bar) no change
|
|
10
|
+
const normlizeLinksInFile = async (filePath: string) => {
|
|
11
|
+
const content = await fs.readFile(filePath, 'utf-8');
|
|
12
|
+
// 1. [foo](bar) -> [foo](./bar)
|
|
13
|
+
const newContent = content.replace(
|
|
14
|
+
/\[([^\]]+)\]\(([^)]+)\)/g,
|
|
15
|
+
(_match, p1, p2) => {
|
|
16
|
+
// 2. [foo](./bar) -> [foo](./bar) no change
|
|
17
|
+
if (['/', '.'].includes(p2[0])) {
|
|
18
|
+
return `[${p1}](${p2})`;
|
|
19
|
+
}
|
|
20
|
+
return `[${p1}](./${p2})`;
|
|
21
|
+
},
|
|
22
|
+
);
|
|
23
|
+
await fs.writeFile(filePath, newContent);
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const traverse = async (dir: string) => {
|
|
27
|
+
const files = await fs.readdir(dir);
|
|
28
|
+
const filePaths = files.map(file => path.join(dir, file));
|
|
29
|
+
const stats = await Promise.all(filePaths.map(fp => fs.stat(fp)));
|
|
30
|
+
|
|
31
|
+
await Promise.all(
|
|
32
|
+
stats.map((stat, index) => {
|
|
33
|
+
const file = files[index];
|
|
34
|
+
const filePath = filePaths[index];
|
|
35
|
+
if (stat.isDirectory()) {
|
|
36
|
+
return traverse(filePath);
|
|
37
|
+
}
|
|
38
|
+
if (stat.isFile() && /\.mdx?/.test(file)) {
|
|
39
|
+
return normlizeLinksInFile(filePath);
|
|
40
|
+
}
|
|
41
|
+
}),
|
|
42
|
+
);
|
|
43
|
+
};
|
|
44
|
+
await traverse(outputDir);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async function generateMetaJson(absoluteApiDir: string) {
|
|
48
|
+
const metaJsonPath = path.join(absoluteApiDir, '_meta.json');
|
|
49
|
+
|
|
50
|
+
const files = await fs.readdir(absoluteApiDir);
|
|
51
|
+
const filePaths = files.map(file => path.join(absoluteApiDir, file));
|
|
52
|
+
const stats = await Promise.all(filePaths.map(fp => fs.stat(fp)));
|
|
53
|
+
const dirs = stats
|
|
54
|
+
.map((stat, index) => (stat.isDirectory() ? files[index] : null))
|
|
55
|
+
.filter(Boolean) as string[];
|
|
56
|
+
|
|
57
|
+
const meta = dirs.map(dir => ({
|
|
58
|
+
type: 'dir',
|
|
59
|
+
label: dir.slice(0, 1).toUpperCase() + dir.slice(1),
|
|
60
|
+
name: dir,
|
|
61
|
+
}));
|
|
62
|
+
await fs.writeFile(metaJsonPath, JSON.stringify(['index', ...meta]));
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export async function patchGeneratedApiDocs(absoluteApiDir: string) {
|
|
66
|
+
await patchLinks(absoluteApiDir);
|
|
67
|
+
await fs.rename(
|
|
68
|
+
path.join(absoluteApiDir, 'README.md'),
|
|
69
|
+
path.join(absoluteApiDir, 'index.md'),
|
|
70
|
+
);
|
|
71
|
+
await generateMetaJson(absoluteApiDir);
|
|
72
|
+
}
|
package/src/sidebar.ts
DELETED
|
@@ -1,179 +0,0 @@
|
|
|
1
|
-
import path from 'node:path';
|
|
2
|
-
import fs from '@rspress/shared/fs-extra';
|
|
3
|
-
import type { SidebarGroup } from '@rspress/shared';
|
|
4
|
-
import { transformModuleName } from './utils';
|
|
5
|
-
import { ROUTE_PREFIX } from './constants';
|
|
6
|
-
|
|
7
|
-
interface ModuleItem {
|
|
8
|
-
id: number;
|
|
9
|
-
name: string;
|
|
10
|
-
children: {
|
|
11
|
-
id: number;
|
|
12
|
-
name: string;
|
|
13
|
-
}[];
|
|
14
|
-
groups: {
|
|
15
|
-
title: string;
|
|
16
|
-
children: number[];
|
|
17
|
-
}[];
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
async function patchLinks(outputDir: string) {
|
|
21
|
-
// Patch links in markdown files
|
|
22
|
-
// Scan all the markdown files in the output directory
|
|
23
|
-
// replace [foo](bar) -> [foo](./bar)
|
|
24
|
-
const normlizeLinksInFile = async (filePath: string) => {
|
|
25
|
-
const content = await fs.readFile(filePath, 'utf-8');
|
|
26
|
-
// replace: [foo](bar) -> [foo](./bar)
|
|
27
|
-
const newContent = content.replace(
|
|
28
|
-
/\[([^\]]+)\]\(([^)]+)\)/g,
|
|
29
|
-
(_match, p1, p2) => {
|
|
30
|
-
return `[${p1}](./${p2})`;
|
|
31
|
-
},
|
|
32
|
-
);
|
|
33
|
-
await fs.writeFile(filePath, newContent);
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
const traverse = async (dir: string) => {
|
|
37
|
-
const files = await fs.readdir(dir);
|
|
38
|
-
for (const file of files) {
|
|
39
|
-
const filePath = path.join(dir, file);
|
|
40
|
-
const stat = await fs.stat(filePath);
|
|
41
|
-
if (stat.isDirectory()) {
|
|
42
|
-
await traverse(filePath);
|
|
43
|
-
} else if (stat.isFile() && /\.mdx?/.test(file)) {
|
|
44
|
-
await normlizeLinksInFile(filePath);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
};
|
|
48
|
-
await traverse(outputDir);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export async function resolveSidebarForSingleEntry(
|
|
52
|
-
jsonFile: string,
|
|
53
|
-
): Promise<SidebarGroup[]> {
|
|
54
|
-
const result: SidebarGroup[] = [];
|
|
55
|
-
const data = JSON.parse(await fs.readFile(jsonFile, 'utf-8'));
|
|
56
|
-
if (!data.children || data.children.length <= 0) {
|
|
57
|
-
return [];
|
|
58
|
-
}
|
|
59
|
-
const symbolMap = new Map<string, number>();
|
|
60
|
-
data.groups.forEach((group: { title: string; children: number[] }) => {
|
|
61
|
-
const groupItem: SidebarGroup = {
|
|
62
|
-
text: group.title,
|
|
63
|
-
items: [],
|
|
64
|
-
};
|
|
65
|
-
group.children.forEach((id: number) => {
|
|
66
|
-
const dataItem = data.children.find((item: ModuleItem) => item.id === id);
|
|
67
|
-
if (dataItem) {
|
|
68
|
-
// Note: we should handle the case that classes and interfaces have the same name
|
|
69
|
-
// Such as class `Env` and variable `env`
|
|
70
|
-
// The final output file name should be `classes/Env.md` and `variables/env-1.md`
|
|
71
|
-
let fileName = dataItem.name;
|
|
72
|
-
if (symbolMap.has(dataItem.name)) {
|
|
73
|
-
const count = symbolMap.get(dataItem.name)! + 1;
|
|
74
|
-
symbolMap.set(dataItem.name, count);
|
|
75
|
-
fileName = `${dataItem.name}-${count}`;
|
|
76
|
-
} else {
|
|
77
|
-
symbolMap.set(dataItem.name.toLocaleLowerCase(), 0);
|
|
78
|
-
}
|
|
79
|
-
groupItem.items.push({
|
|
80
|
-
text: dataItem.name,
|
|
81
|
-
link: `${ROUTE_PREFIX}/${group.title.toLocaleLowerCase()}/${fileName}`,
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
});
|
|
85
|
-
result.push(groupItem);
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
await patchLinks(path.dirname(jsonFile));
|
|
89
|
-
|
|
90
|
-
return result;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
export async function resolveSidebarForMultiEntry(
|
|
94
|
-
jsonFile: string,
|
|
95
|
-
): Promise<SidebarGroup[]> {
|
|
96
|
-
const result: SidebarGroup[] = [];
|
|
97
|
-
const data = JSON.parse(await fs.readFile(jsonFile, 'utf-8'));
|
|
98
|
-
if (!data.children || data.children.length <= 0) {
|
|
99
|
-
return result;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
function getModulePath(name: string) {
|
|
103
|
-
return path
|
|
104
|
-
.join(`${ROUTE_PREFIX}/modules`, `${transformModuleName(name)}`)
|
|
105
|
-
.replace(/\\/g, '/');
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
function getClassPath(moduleName: string, className: string) {
|
|
109
|
-
return path
|
|
110
|
-
.join(
|
|
111
|
-
`${ROUTE_PREFIX}/classes`,
|
|
112
|
-
`${transformModuleName(moduleName)}.${className}`,
|
|
113
|
-
)
|
|
114
|
-
.replace(/\\/g, '/');
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
function getInterfacePath(moduleName: string, interfaceName: string) {
|
|
118
|
-
return path
|
|
119
|
-
.join(
|
|
120
|
-
`${ROUTE_PREFIX}/interfaces`,
|
|
121
|
-
`${transformModuleName(moduleName)}.${interfaceName}`,
|
|
122
|
-
)
|
|
123
|
-
.replace(/\\/g, '/');
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
function getFunctionPath(moduleName: string, functionName: string) {
|
|
127
|
-
return path
|
|
128
|
-
.join(
|
|
129
|
-
`${ROUTE_PREFIX}/functions`,
|
|
130
|
-
`${transformModuleName(moduleName)}.${functionName}`,
|
|
131
|
-
)
|
|
132
|
-
.replace(/\\/g, '/');
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
data.children.forEach((module: ModuleItem) => {
|
|
136
|
-
const moduleNames = module.name.split('/');
|
|
137
|
-
const name = moduleNames[moduleNames.length - 1];
|
|
138
|
-
const moduleConfig = {
|
|
139
|
-
text: `Module:${name}`,
|
|
140
|
-
items: [{ text: 'Overview', link: getModulePath(module.name) }],
|
|
141
|
-
};
|
|
142
|
-
if (!module.children || module.children.length <= 0) {
|
|
143
|
-
return;
|
|
144
|
-
}
|
|
145
|
-
module.children.forEach(sub => {
|
|
146
|
-
const kindString = module.groups
|
|
147
|
-
.find(item => item.children.includes(sub.id))
|
|
148
|
-
?.title.slice(0, -1);
|
|
149
|
-
if (!kindString) {
|
|
150
|
-
return;
|
|
151
|
-
}
|
|
152
|
-
switch (kindString) {
|
|
153
|
-
case 'Class':
|
|
154
|
-
moduleConfig.items.push({
|
|
155
|
-
text: `Class:${sub.name}`,
|
|
156
|
-
link: getClassPath(module.name, sub.name),
|
|
157
|
-
});
|
|
158
|
-
break;
|
|
159
|
-
case 'Interface':
|
|
160
|
-
moduleConfig.items.push({
|
|
161
|
-
text: `Interface:${sub.name}`,
|
|
162
|
-
link: getInterfacePath(module.name, sub.name),
|
|
163
|
-
});
|
|
164
|
-
break;
|
|
165
|
-
case 'Function':
|
|
166
|
-
moduleConfig.items.push({
|
|
167
|
-
text: `Function:${sub.name}`,
|
|
168
|
-
link: getFunctionPath(module.name, sub.name),
|
|
169
|
-
});
|
|
170
|
-
break;
|
|
171
|
-
default:
|
|
172
|
-
break;
|
|
173
|
-
}
|
|
174
|
-
});
|
|
175
|
-
result.push(moduleConfig);
|
|
176
|
-
});
|
|
177
|
-
await patchLinks(path.dirname(jsonFile));
|
|
178
|
-
return result;
|
|
179
|
-
}
|