dumi 2.3.0-alpha.8 → 2.3.0-beta.0
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/compiled/crates/swc_plugin_react_demo.wasm +0 -0
- package/dist/assetParsers/block.d.ts +7 -1
- package/dist/assetParsers/block.js +14 -6
- package/dist/client/pages/Demo/index.js +19 -5
- package/dist/client/pages/Loading.d.ts +1 -0
- package/dist/client/pages/Loading.js +2 -0
- package/dist/client/theme-api/DumiDemo/index.js +4 -4
- package/dist/client/theme-api/{context/index.d.ts → context.d.ts} +4 -12
- package/dist/client/theme-api/context.js +16 -0
- package/dist/client/theme-api/index.d.ts +2 -3
- package/dist/client/theme-api/index.js +2 -3
- package/dist/client/theme-api/types.d.ts +6 -4
- package/dist/client/theme-api/useLiveDemo.d.ts +6 -0
- package/dist/client/theme-api/useLiveDemo.js +70 -0
- package/dist/client/theme-api/useRouteMeta.js +73 -20
- package/dist/client/theme-api/useSiteSearch/index.d.ts +1 -1
- package/dist/client/theme-api/useSiteSearch/index.js +20 -48
- package/dist/client/theme-api/useSiteSearch/useSearchData.d.ts +9 -6
- package/dist/client/theme-api/useSiteSearch/useSearchData.js +55 -60
- package/dist/client/theme-api/useTabMeta.js +1 -1
- package/dist/client/theme-api/utils.d.ts +10 -0
- package/dist/client/theme-api/utils.js +25 -0
- package/dist/constants.d.ts +0 -1
- package/dist/constants.js +0 -4
- package/dist/features/compile/index.js +11 -18
- package/dist/features/exports.js +3 -3
- package/dist/features/meta.js +12 -31
- package/dist/features/theme/index.js +8 -5
- package/dist/loaders/markdown/index.d.ts +1 -7
- package/dist/loaders/markdown/index.js +39 -113
- package/dist/loaders/markdown/transformer/index.d.ts +1 -1
- package/dist/loaders/markdown/transformer/rehypeDemo.js +8 -2
- package/dist/loaders/page/index.js +1 -3
- package/dist/preset.js +1 -2
- package/dist/templates/ContextWrapper.ts.tpl +2 -10
- package/dist/templates/meta/exports.ts.tpl +160 -0
- package/dist/templates/meta/index.ts.tpl +26 -0
- package/dist/templates/{meta-runtime.ts.tpl → meta/runtime.ts.tpl} +11 -22
- package/dist/types.d.ts +2 -2
- package/index.d.ts +1 -4
- package/package.json +2 -1
- package/theme-default/builtins/Previewer/index.d.ts +1 -1
- package/theme-default/builtins/Previewer/index.js +35 -33
- package/theme-default/builtins/Previewer/index.less +34 -0
- package/theme-default/builtins/SourceCode/index.d.ts +2 -1
- package/theme-default/builtins/SourceCode/index.js +3 -3
- package/theme-default/builtins/SourceCode/index.less +1 -0
- package/theme-default/locales/en-US.json +2 -0
- package/theme-default/locales/zh-CN.json +2 -0
- package/theme-default/slots/Loading/index.d.ts +5 -0
- package/theme-default/slots/Loading/index.js +18 -0
- package/theme-default/slots/Loading/index.less +20 -0
- package/theme-default/slots/PreviewerActions/index.d.ts +7 -1
- package/theme-default/slots/PreviewerActions/index.js +49 -6
- package/theme-default/slots/PreviewerActions/index.less +58 -14
- package/theme-default/slots/SearchBar/Mask.js +1 -1
- package/theme-default/slots/SearchBar/index.js +1 -1
- package/theme-default/slots/SearchResult/index.js +1 -10
- package/theme-default/slots/SourceCodeEditor/index.d.ts +18 -0
- package/theme-default/slots/SourceCodeEditor/index.js +106 -0
- package/theme-default/slots/SourceCodeEditor/index.less +45 -0
- package/dist/client/theme-api/context/index.js +0 -50
- package/dist/client/theme-api/context/use.d.ts +0 -10
- package/dist/client/theme-api/context/use.js +0 -25
- package/dist/client/theme-api/evalCode.d.ts +0 -2
- package/dist/client/theme-api/evalCode.js +0 -17
- package/dist/client/theme-api/live/LiveProvider.d.ts +0 -16
- package/dist/client/theme-api/live/LiveProvider.js +0 -74
- package/dist/client/theme-api/live/index.d.ts +0 -3
- package/dist/client/theme-api/live/index.js +0 -3
- package/dist/client/theme-api/live/useDemoScopes.d.ts +0 -2
- package/dist/client/theme-api/live/useDemoScopes.js +0 -15
- package/dist/features/live.d.ts +0 -3
- package/dist/features/live.js +0 -74
- package/dist/templates/live/demo-scopes.ts.tpl +0 -22
- package/dist/templates/live/disabled.ts.tpl +0 -1
- package/dist/templates/meta-demos.ts.tpl +0 -34
- package/dist/templates/meta-frontmatter.ts.tpl +0 -9
- package/dist/templates/meta-route.ts.tpl +0 -43
- package/dist/templates/meta-search.ts.tpl +0 -41
- package/theme-default/slots/LiveDemo/index.d.ts +0 -3
- package/theme-default/slots/LiveDemo/index.js +0 -8
- package/theme-default/slots/LiveEditor/index.d.ts +0 -4
- package/theme-default/slots/LiveEditor/index.js +0 -20
- package/theme-default/slots/LiveError/index.d.ts +0 -4
- package/theme-default/slots/LiveError/index.js +0 -15
- package/theme-default/slots/LiveError/index.less +0 -22
|
@@ -40,8 +40,8 @@ var import_transformer = __toESM(require("./transformer"));
|
|
|
40
40
|
var import_rehypeText = require("./transformer/rehypeText");
|
|
41
41
|
function getDemoSourceFiles(demos = []) {
|
|
42
42
|
return demos.reduce((ret, demo) => {
|
|
43
|
-
if ("
|
|
44
|
-
ret.push(...Object.values(demo.
|
|
43
|
+
if ("resolveMap" in demo) {
|
|
44
|
+
ret.push(...Object.values(demo.resolveMap));
|
|
45
45
|
}
|
|
46
46
|
return ret;
|
|
47
47
|
}, []);
|
|
@@ -49,6 +49,7 @@ function getDemoSourceFiles(demos = []) {
|
|
|
49
49
|
function emitDefault(opts, ret) {
|
|
50
50
|
const { frontmatter, demos } = ret.meta;
|
|
51
51
|
const isTabContent = (0, import_tabs.isTabRouteFile)(this.resourcePath);
|
|
52
|
+
const wrapper = isTabContent ? "" : "DumiPage";
|
|
52
53
|
if (demos && opts.onResolveDemos) {
|
|
53
54
|
opts.onResolveDemos(demos);
|
|
54
55
|
}
|
|
@@ -56,14 +57,21 @@ function emitDefault(opts, ret) {
|
|
|
56
57
|
opts.onResolveAtomMeta(frontmatter.atomId, frontmatter);
|
|
57
58
|
}
|
|
58
59
|
return `${Object.values(opts.builtins).map((item) => `import ${item.specifier} from '${item.source}';`).join("\n")}
|
|
59
|
-
import
|
|
60
|
-
|
|
60
|
+
import LoadingComponent from '@@/dumi/theme/loading';
|
|
61
|
+
import React, { Suspense } from 'react';
|
|
62
|
+
import { DumiPage, useTabMeta, useRouteMeta } from 'dumi';
|
|
63
|
+
|
|
64
|
+
function DumiMarkdownInner() {
|
|
65
|
+
const { texts: ${import_rehypeText.CONTENT_TEXTS_OBJ_NAME} } = use${isTabContent ? "TabMeta" : "RouteMeta"}();
|
|
66
|
+
|
|
67
|
+
return ${ret.content};
|
|
68
|
+
}
|
|
61
69
|
|
|
62
70
|
// export named function for fastRefresh
|
|
63
71
|
// ref: https://github.com/pmmmwh/react-refresh-webpack-plugin/blob/main/docs/TROUBLESHOOTING.md#edits-always-lead-to-full-reload
|
|
64
72
|
function DumiMarkdownContent() {
|
|
65
|
-
|
|
66
|
-
return
|
|
73
|
+
// wrap suspense for catch async meta data
|
|
74
|
+
return <${wrapper}><Suspense fallback={<LoadingComponent />}><DumiMarkdownInner /></Suspense></${wrapper}>;
|
|
67
75
|
}
|
|
68
76
|
|
|
69
77
|
export default DumiMarkdownContent;`;
|
|
@@ -77,7 +85,8 @@ export const demos = {
|
|
|
77
85
|
{{#demos}}
|
|
78
86
|
'{{{id}}}': {
|
|
79
87
|
component: {{{component}}},
|
|
80
|
-
asset: {{{renderAsset}}}
|
|
88
|
+
asset: {{{renderAsset}}},
|
|
89
|
+
context: {{{renderContext}}}
|
|
81
90
|
},
|
|
82
91
|
{{/demos}}
|
|
83
92
|
};`,
|
|
@@ -87,14 +96,26 @@ export const demos = {
|
|
|
87
96
|
if (!("asset" in this))
|
|
88
97
|
return "null";
|
|
89
98
|
let { asset } = this;
|
|
90
|
-
const {
|
|
91
|
-
Object.keys(this.
|
|
99
|
+
const { resolveMap } = this;
|
|
100
|
+
Object.keys(this.resolveMap).forEach((file) => {
|
|
92
101
|
if (!asset.dependencies[file])
|
|
93
102
|
return;
|
|
94
103
|
asset = import_plugin_utils.lodash.cloneDeep(asset);
|
|
95
|
-
asset.dependencies[file].value = `{{{require('-!${
|
|
104
|
+
asset.dependencies[file].value = `{{{require('-!${resolveMap[file]}?dumi-raw').default}}}`;
|
|
96
105
|
});
|
|
97
106
|
return JSON.stringify(asset, null, 2).replace(/"{{{|}}}"/g, "");
|
|
107
|
+
},
|
|
108
|
+
renderContext: function renderContext() {
|
|
109
|
+
if (!("resolveMap" in this))
|
|
110
|
+
return "undefined";
|
|
111
|
+
const context = Object.entries(this.resolveMap).reduce(
|
|
112
|
+
(acc, [key, path]) => ({
|
|
113
|
+
...acc,
|
|
114
|
+
[key]: `{{{require('${path}')}}}`
|
|
115
|
+
}),
|
|
116
|
+
{}
|
|
117
|
+
);
|
|
118
|
+
return JSON.stringify(context, null, 2).replace(/"{{{|}}}"/g, "");
|
|
98
119
|
}
|
|
99
120
|
}
|
|
100
121
|
);
|
|
@@ -117,112 +138,21 @@ function emitDemoIndex(opts, ret) {
|
|
|
117
138
|
);
|
|
118
139
|
}
|
|
119
140
|
function emitFrontmatter(opts, ret) {
|
|
120
|
-
const { frontmatter } = ret.meta;
|
|
121
|
-
return import_plugin_utils.Mustache.render(`export const frontmatter = {{{frontmatter}}};`, {
|
|
122
|
-
frontmatter: JSON.stringify(frontmatter)
|
|
123
|
-
});
|
|
124
|
-
}
|
|
125
|
-
function emitText(opts, ret) {
|
|
126
|
-
const { texts, toc } = ret.meta;
|
|
141
|
+
const { frontmatter, toc } = ret.meta;
|
|
127
142
|
return import_plugin_utils.Mustache.render(
|
|
128
143
|
`export const toc = {{{toc}}};
|
|
129
|
-
export const
|
|
144
|
+
export const frontmatter = {{{frontmatter}}};`,
|
|
130
145
|
{
|
|
131
146
|
toc: JSON.stringify(toc),
|
|
132
|
-
|
|
133
|
-
}
|
|
134
|
-
);
|
|
135
|
-
}
|
|
136
|
-
function emitScope(opts, ret) {
|
|
137
|
-
const { demos } = ret.meta;
|
|
138
|
-
const importReg = /import(?!(\stype)).*from.*;/g;
|
|
139
|
-
return import_plugin_utils.Mustache.render(
|
|
140
|
-
`{{#renderImport}}
|
|
141
|
-
{{{.}}}
|
|
142
|
-
{{/renderImport}}
|
|
143
|
-
|
|
144
|
-
export const scopes = {
|
|
145
|
-
{{#demos}}
|
|
146
|
-
'{{{id}}}': { {{{renderScope}}} },
|
|
147
|
-
{{/demos}}
|
|
148
|
-
}`,
|
|
149
|
-
{
|
|
150
|
-
demos,
|
|
151
|
-
renderImport: function renderImport() {
|
|
152
|
-
if (!demos)
|
|
153
|
-
return [];
|
|
154
|
-
const imports = {};
|
|
155
|
-
for (const demo of demos) {
|
|
156
|
-
if ("asset" in demo) {
|
|
157
|
-
const { asset } = demo;
|
|
158
|
-
Object.entries(asset.dependencies).forEach(([filename, file]) => {
|
|
159
|
-
if (filename.endsWith(".tsx")) {
|
|
160
|
-
const fileImports = file.value.match(importReg) || [];
|
|
161
|
-
fileImports.forEach((item) => {
|
|
162
|
-
var _a;
|
|
163
|
-
const scope = item.replace(/import(.*)from.*;/, "$1").trim();
|
|
164
|
-
const dep = item.replace(/import.*from(.*);/, "$1").trim();
|
|
165
|
-
const namedReg = /.*\{(.*)}/g;
|
|
166
|
-
const namedScope = namedReg.test(scope) ? scope.replace(namedReg, "$1").split(",").map((item2) => item2.trim()).filter(Boolean) : [];
|
|
167
|
-
const defaultReg = /(?:(?![,{]).)*/;
|
|
168
|
-
const defaultScope = (_a = scope.match(defaultReg)) == null ? void 0 : _a[0].trim();
|
|
169
|
-
imports[dep] ?? (imports[dep] = []);
|
|
170
|
-
if (defaultScope) {
|
|
171
|
-
const defaultImport = `default as ${defaultScope}`;
|
|
172
|
-
if (!imports[dep].includes(defaultImport)) {
|
|
173
|
-
imports[dep].push(defaultImport);
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
if (namedScope.length) {
|
|
177
|
-
for (const item2 of namedScope) {
|
|
178
|
-
if (!imports[dep].includes(item2)) {
|
|
179
|
-
imports[dep].push(item2);
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
});
|
|
184
|
-
}
|
|
185
|
-
});
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
return Object.entries(imports).map(([key, value]) => {
|
|
189
|
-
return value.length ? `import { ${value.join(", ")} } from ${key};` : "";
|
|
190
|
-
}).filter(Boolean);
|
|
191
|
-
},
|
|
192
|
-
renderScope: function renderScope() {
|
|
193
|
-
if (!("asset" in this))
|
|
194
|
-
return "";
|
|
195
|
-
const { asset } = this;
|
|
196
|
-
const demoScopes = [];
|
|
197
|
-
Object.entries(asset.dependencies).forEach(([filename, file]) => {
|
|
198
|
-
if (filename.endsWith(".tsx")) {
|
|
199
|
-
const imports = file.value.match(importReg) || [];
|
|
200
|
-
const scopes = imports.reduce((acc, item) => {
|
|
201
|
-
const scope = item.replace(/import(.*)from.*;/, "$1").trim();
|
|
202
|
-
const scopeList = scope.replace(/[{}]/g, "").trim();
|
|
203
|
-
return [...acc, scopeList];
|
|
204
|
-
}, []);
|
|
205
|
-
demoScopes.push(...scopes);
|
|
206
|
-
}
|
|
207
|
-
});
|
|
208
|
-
return demoScopes.join(", ");
|
|
209
|
-
}
|
|
147
|
+
frontmatter: JSON.stringify(frontmatter)
|
|
210
148
|
}
|
|
211
149
|
);
|
|
212
150
|
}
|
|
213
|
-
function
|
|
214
|
-
const {
|
|
215
|
-
return import_plugin_utils.Mustache.render(
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
'{{{id}}}': {{{getter}}},
|
|
219
|
-
{{/demos}}
|
|
220
|
-
};`,
|
|
221
|
-
{
|
|
222
|
-
demos,
|
|
223
|
-
getter: `() => import('${(0, import_plugin_utils.winPath)(this.resourcePath)}?type=scope')`
|
|
224
|
-
}
|
|
225
|
-
);
|
|
151
|
+
function emitText(opts, ret) {
|
|
152
|
+
const { texts } = ret.meta;
|
|
153
|
+
return import_plugin_utils.Mustache.render(`export const texts = {{{texts}}};`, {
|
|
154
|
+
texts: JSON.stringify(texts)
|
|
155
|
+
});
|
|
226
156
|
}
|
|
227
157
|
function emit(opts, ret) {
|
|
228
158
|
const { demos, embeds } = ret.meta;
|
|
@@ -237,10 +167,6 @@ function emit(opts, ret) {
|
|
|
237
167
|
return emitFrontmatter.call(this, opts, ret);
|
|
238
168
|
case "text":
|
|
239
169
|
return emitText.call(this, opts, ret);
|
|
240
|
-
case "scope":
|
|
241
|
-
return emitScope.call(this, opts, ret);
|
|
242
|
-
case "scope-index":
|
|
243
|
-
return emitScopeIndex.call(this, opts, ret);
|
|
244
170
|
default:
|
|
245
171
|
return emitDefault.call(this, opts, ret);
|
|
246
172
|
}
|
|
@@ -225,7 +225,7 @@ function rehypeDemo(opts) {
|
|
|
225
225
|
demoIds.push(parseOpts.id);
|
|
226
226
|
deferrers.push(
|
|
227
227
|
(0, import_block.default)(parseOpts).then(
|
|
228
|
-
async ({ asset,
|
|
228
|
+
async ({ asset, resolveMap, frontmatter }) => {
|
|
229
229
|
var _a2, _b2, _c2;
|
|
230
230
|
if (demoIds.indexOf(parseOpts.id) !== demoIds.lastIndexOf(parseOpts.id)) {
|
|
231
231
|
const startLine = (_a2 = node.position) == null ? void 0 : _a2.start.line;
|
|
@@ -293,7 +293,13 @@ function rehypeDemo(opts) {
|
|
|
293
293
|
id: asset.id,
|
|
294
294
|
component,
|
|
295
295
|
asset: techStack.generateMetadata ? await techStack.generateMetadata(asset, techStackOpts) : asset,
|
|
296
|
-
|
|
296
|
+
/**
|
|
297
|
+
* keep `generateSources` rather than `generateResolveMap` for compatibility
|
|
298
|
+
*/
|
|
299
|
+
resolveMap: techStack.generateSources ? await techStack.generateSources(
|
|
300
|
+
resolveMap,
|
|
301
|
+
techStackOpts
|
|
302
|
+
) : resolveMap
|
|
297
303
|
};
|
|
298
304
|
}
|
|
299
305
|
)
|
|
@@ -44,7 +44,5 @@ function pageMetaLoader(raw) {
|
|
|
44
44
|
frontmatter || (frontmatter = {});
|
|
45
45
|
frontmatter.title ?? (frontmatter.title = import_plugin_utils.lodash.startCase(import_path.default.basename(pathWithoutIndex)));
|
|
46
46
|
return `export const frontmatter = ${JSON.stringify(frontmatter)};
|
|
47
|
-
export const toc = []
|
|
48
|
-
export const texts = [];
|
|
49
|
-
export const demos = {};`;
|
|
47
|
+
export const toc = [];`;
|
|
50
48
|
}
|
package/dist/preset.js
CHANGED
|
@@ -52,8 +52,7 @@ var preset_default = (api) => {
|
|
|
52
52
|
require.resolve("./features/assets"),
|
|
53
53
|
require.resolve("./features/exportStatic"),
|
|
54
54
|
require.resolve("./features/sitemap"),
|
|
55
|
-
require.resolve("./features/html2sketch")
|
|
56
|
-
require.resolve("./features/live")
|
|
55
|
+
require.resolve("./features/html2sketch")
|
|
57
56
|
]
|
|
58
57
|
};
|
|
59
58
|
};
|
|
@@ -3,8 +3,6 @@ import { useOutlet, history } from 'dumi';
|
|
|
3
3
|
import { warning } from 'rc-util';
|
|
4
4
|
import { SiteContext, type ISiteContext } from '{{{contextPath}}}';
|
|
5
5
|
import { components } from '../meta/atoms';
|
|
6
|
-
import { tabs } from '../meta/tabs';
|
|
7
|
-
import { getDemoById } from '../meta/demos';
|
|
8
6
|
import { locales } from '../locales/config';
|
|
9
7
|
{{{defaultExport}}}
|
|
10
8
|
{{{namedExport}}}
|
|
@@ -48,20 +46,18 @@ export default function DumiContextWrapper() {
|
|
|
48
46
|
entryExports,
|
|
49
47
|
demos: null,
|
|
50
48
|
components,
|
|
51
|
-
tabs,
|
|
52
49
|
locales,
|
|
53
50
|
loading,
|
|
54
51
|
setLoading,
|
|
55
52
|
hostname,
|
|
56
53
|
themeConfig,
|
|
57
54
|
_2_level_nav_available,
|
|
58
|
-
getDemoById,
|
|
59
55
|
};
|
|
60
56
|
|
|
61
57
|
// Proxy do not warning since `Object.keys` will get nothing to loop
|
|
62
58
|
Object.defineProperty(ctx, 'demos', {
|
|
63
59
|
get: () => {
|
|
64
|
-
warning(false, '`demos` return empty in latest version.');
|
|
60
|
+
warning(false, '`demos` return empty in latest version, please use `useDemo` instead.');
|
|
65
61
|
return {};
|
|
66
62
|
},
|
|
67
63
|
});
|
|
@@ -72,21 +68,17 @@ export default function DumiContextWrapper() {
|
|
|
72
68
|
historyType,
|
|
73
69
|
entryExports,
|
|
74
70
|
components,
|
|
75
|
-
tabs,
|
|
76
71
|
locales,
|
|
77
72
|
loading,
|
|
78
73
|
setLoading,
|
|
79
74
|
hostname,
|
|
80
75
|
themeConfig,
|
|
81
76
|
_2_level_nav_available,
|
|
82
|
-
getDemoById,
|
|
83
77
|
]);
|
|
84
78
|
|
|
85
|
-
|
|
86
|
-
|
|
87
79
|
return (
|
|
88
80
|
<SiteContext.Provider value={context}>
|
|
89
81
|
{outlet}
|
|
90
82
|
</SiteContext.Provider>
|
|
91
83
|
);
|
|
92
|
-
}
|
|
84
|
+
}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { filesMeta, tabsMeta } from '.';
|
|
2
|
+
import type { IDemoData, IRouteMeta } from 'dumi/dist/client/theme-api/types';
|
|
3
|
+
import { use } from 'dumi/dist/client/theme-api/utils';
|
|
4
|
+
|
|
5
|
+
const demoIdMap = Object.keys(filesMeta).reduce((total, current) => {
|
|
6
|
+
if (filesMeta[current].demoIndex) {
|
|
7
|
+
const { ids, getter } = filesMeta[current].demoIndex;
|
|
8
|
+
|
|
9
|
+
ids.forEach((id) => {
|
|
10
|
+
total[id] = getter;
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
return total;
|
|
15
|
+
}, {});
|
|
16
|
+
|
|
17
|
+
const demosCache = new Map<string, Promise<IDemoData | undefined>>();
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* expand context for source omit extension
|
|
21
|
+
* why not do this in compile-time?
|
|
22
|
+
* asset metadata also has extension and for reduce bundle size
|
|
23
|
+
*/
|
|
24
|
+
function expandDemoContext(context?: IDemoData['context']) {
|
|
25
|
+
if (context) {
|
|
26
|
+
Object.keys(context).forEach((src) => {
|
|
27
|
+
const withoutExt = src.match(/^(.+)\.(js|jsx|ts|tsx|json)$/)?.[1];
|
|
28
|
+
|
|
29
|
+
if (withoutExt && !context[withoutExt]) {
|
|
30
|
+
context[withoutExt] = context[src];
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* use demo data by id
|
|
38
|
+
*/
|
|
39
|
+
export function useDemo(id: string): IDemoData | undefined {
|
|
40
|
+
if (!demosCache.get(id)) {
|
|
41
|
+
demosCache.set(
|
|
42
|
+
id,
|
|
43
|
+
demoIdMap[id]?.().then(({ demos }) => {
|
|
44
|
+
// expand context for omit ext
|
|
45
|
+
expandDemoContext(demos[id].context);
|
|
46
|
+
|
|
47
|
+
return demos[id];
|
|
48
|
+
}),
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return use(demosCache.get(id)!);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* get all demos
|
|
57
|
+
*/
|
|
58
|
+
export async function getFullDemos() {
|
|
59
|
+
const demoFilesMeta = Object.entries(filesMeta).filter(
|
|
60
|
+
([_id, meta]) => meta.demoIndex,
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
return Promise.all(
|
|
64
|
+
demoFilesMeta.map(async ([id, meta]) => ({
|
|
65
|
+
id,
|
|
66
|
+
demos: (await meta.demoIndex.getter()).demos as Record<string, IDemoData>,
|
|
67
|
+
})),
|
|
68
|
+
).then((ret) =>
|
|
69
|
+
ret.reduce<Record<string, IDemoData>>((total, { id, demos }) => {
|
|
70
|
+
Object.values(demos).forEach((demo) => {
|
|
71
|
+
// set route id in runtime for reduce bundle size
|
|
72
|
+
demo.routeId = id;
|
|
73
|
+
|
|
74
|
+
// expand context for omit ext
|
|
75
|
+
expandDemoContext(demo.context);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
return {
|
|
79
|
+
...total,
|
|
80
|
+
...demos,
|
|
81
|
+
};
|
|
82
|
+
}, {}),
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
type ITab = NonNullable<IRouteMeta['tabs']>[0];
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* generate final data for tab
|
|
90
|
+
*/
|
|
91
|
+
function genTab(id: string, meta?: ITab['meta']): ITab {
|
|
92
|
+
return {
|
|
93
|
+
...tabsMeta[id],
|
|
94
|
+
meta: meta ?? {
|
|
95
|
+
frontmatter: { title: tabsMeta[id].title },
|
|
96
|
+
toc: [],
|
|
97
|
+
texts: [],
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* get route meta by id
|
|
104
|
+
*/
|
|
105
|
+
export function getRouteMetaById<T extends { syncOnly?: boolean }>(
|
|
106
|
+
id: string,
|
|
107
|
+
opts?: T,
|
|
108
|
+
): T extends { syncOnly: true }
|
|
109
|
+
? undefined | IRouteMeta
|
|
110
|
+
: Promise<undefined | IRouteMeta> | undefined {
|
|
111
|
+
if (filesMeta[id]) {
|
|
112
|
+
const { frontmatter, toc, textGetter, tabs = [] } = filesMeta[id];
|
|
113
|
+
const routeMeta: IRouteMeta = {
|
|
114
|
+
frontmatter,
|
|
115
|
+
toc: toc,
|
|
116
|
+
texts: [],
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
if (opts?.syncOnly) {
|
|
120
|
+
routeMeta.tabs = tabs.map((tabId) =>
|
|
121
|
+
genTab(tabId, getRouteMetaById(tabId, opts)),
|
|
122
|
+
);
|
|
123
|
+
} else {
|
|
124
|
+
return new Promise(async (resolve) => {
|
|
125
|
+
if (textGetter) {
|
|
126
|
+
({ texts: routeMeta.texts } = await textGetter());
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
routeMeta.tabs = await Promise.all(
|
|
130
|
+
tabs.map(async (tabId) =>
|
|
131
|
+
genTab(tabId, await getRouteMetaById(tabId, opts)),
|
|
132
|
+
),
|
|
133
|
+
);
|
|
134
|
+
resolve(routeMeta);
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return routeMeta;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* get all routes meta
|
|
144
|
+
*/
|
|
145
|
+
export async function getFullRoutesMeta(): Promise<Record<string, IRouteMeta>> {
|
|
146
|
+
return await Promise.all(
|
|
147
|
+
Object.keys(filesMeta).map(async (id) => ({
|
|
148
|
+
id,
|
|
149
|
+
meta: await getRouteMetaById(id),
|
|
150
|
+
})),
|
|
151
|
+
).then((ret) =>
|
|
152
|
+
ret.reduce(
|
|
153
|
+
(total, { id, meta }) => ({
|
|
154
|
+
...total,
|
|
155
|
+
[id]: meta,
|
|
156
|
+
}),
|
|
157
|
+
{},
|
|
158
|
+
),
|
|
159
|
+
);
|
|
160
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{{#metaFiles}}
|
|
2
|
+
import { frontmatter as fm{{{index}}}, toc as t{{{index}}} } from '{{{file}}}?type=frontmatter';
|
|
3
|
+
{{#isMarkdown}}
|
|
4
|
+
import { demoIndex as dmi{{{index}}} } from '{{{file}}}?type=demo-index';
|
|
5
|
+
{{/isMarkdown}}
|
|
6
|
+
{{/metaFiles}}
|
|
7
|
+
|
|
8
|
+
export const filesMeta = {
|
|
9
|
+
{{#metaFiles}}
|
|
10
|
+
'{{{id}}}': {
|
|
11
|
+
frontmatter: fm{{{index}}},
|
|
12
|
+
toc: t{{{index}}},
|
|
13
|
+
{{#isMarkdown}}
|
|
14
|
+
demoIndex: dmi{{{index}}},
|
|
15
|
+
{{/isMarkdown}}
|
|
16
|
+
{{#tabs}}
|
|
17
|
+
tabs: {{{tabs}}},
|
|
18
|
+
{{/tabs}}
|
|
19
|
+
{{#isMarkdown}}
|
|
20
|
+
textGetter: () => import({{{chunkName}}}'{{{file}}}?type=text'),
|
|
21
|
+
{{/isMarkdown}}
|
|
22
|
+
},
|
|
23
|
+
{{/metaFiles}}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export { tabs as tabsMeta } from './tabs';
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import { warning } from 'rc-util';
|
|
2
|
-
import { tabs } from './tabs';
|
|
3
|
-
import { filesFrontmatter } from './frontmatter';
|
|
4
2
|
import deepmerge from '{{{deepmerge}}}';
|
|
3
|
+
import { getRouteMetaById } from './exports';
|
|
5
4
|
|
|
6
5
|
// Proxy do not warning since `Object.keys` will get nothing to loop
|
|
7
6
|
function wrapEmpty(meta, fieldName, defaultValue) {
|
|
8
7
|
Object.defineProperty(meta, fieldName, {
|
|
9
8
|
get: () => {
|
|
10
|
-
warning(false, `'${fieldName}' return empty in latest version.`);
|
|
9
|
+
warning(false, `'${fieldName}' return empty in latest version, please use \`useRouteMeta\` instead.`);
|
|
11
10
|
return defaultValue;
|
|
12
11
|
},
|
|
13
12
|
});
|
|
@@ -15,32 +14,22 @@ function wrapEmpty(meta, fieldName, defaultValue) {
|
|
|
15
14
|
|
|
16
15
|
export const patchRoutes = ({ routes }) => {
|
|
17
16
|
Object.values(routes).forEach((route) => {
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
const routeMeta = getRouteMetaById(route.id, { syncOnly: true });
|
|
18
|
+
|
|
19
|
+
if (routeMeta) {
|
|
20
|
+
if (process.env.NODE_ENV === 'production' && (route.meta?.frontmatter?.debug || routeMeta.debug)) {
|
|
20
21
|
// hide route in production which set hide frontmatter
|
|
21
22
|
delete routes[route.id];
|
|
22
23
|
} else {
|
|
23
24
|
// merge meta to route object
|
|
24
|
-
route.meta = deepmerge(route.meta,
|
|
25
|
+
route.meta = deepmerge(route.meta, routeMeta);
|
|
25
26
|
|
|
26
|
-
wrapEmpty(route.meta, '
|
|
27
|
+
wrapEmpty(route.meta, 'toc', []);
|
|
27
28
|
wrapEmpty(route.meta, 'texts', []);
|
|
28
29
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
frontmatter: filesFrontmatter[id] || { title: tabs[id].title },
|
|
33
|
-
toc: [],
|
|
34
|
-
texts: [],
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
wrapEmpty(meta, 'demos', {});
|
|
38
|
-
wrapEmpty(meta, 'texts', []);
|
|
39
|
-
|
|
40
|
-
return {
|
|
41
|
-
...tabs[id],
|
|
42
|
-
meta,
|
|
43
|
-
}
|
|
30
|
+
route.meta.tabs?.forEach((tab) => {
|
|
31
|
+
wrapEmpty(tab, 'toc', []);
|
|
32
|
+
wrapEmpty(tab, 'texts', []);
|
|
44
33
|
});
|
|
45
34
|
}
|
|
46
35
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ import type { IThemeLoadResult } from "./features/theme/loader";
|
|
|
7
7
|
import type { IModify } from '@umijs/core';
|
|
8
8
|
import type { AssetsPackage, ExampleBlockAsset } from 'dumi-assets-types';
|
|
9
9
|
import type { Element } from 'hast';
|
|
10
|
-
import type {
|
|
10
|
+
import type { IApi as IUmiApi, defineConfig as defineUmiConfig } from 'umi';
|
|
11
11
|
type Subset<K> = {
|
|
12
12
|
[attr in keyof K]?: K[attr] extends Array<any> ? K[attr] : K[attr] extends Function | undefined ? K[attr] : K[attr] extends object ? Subset<K[attr]> : K[attr] extends object | null ? Subset<K[attr]> | null : K[attr] extends object | null | undefined ? Subset<K[attr]> | null | undefined : K[attr];
|
|
13
13
|
};
|
|
@@ -80,7 +80,7 @@ export declare abstract class IDumiTechStack {
|
|
|
80
80
|
/**
|
|
81
81
|
* generator for return file path of demo sources
|
|
82
82
|
*/
|
|
83
|
-
abstract generateSources?(sources: IParsedBlockAsset['
|
|
83
|
+
abstract generateSources?(sources: IParsedBlockAsset['resolveMap'], opts: Parameters<NonNullable<IDumiTechStack['generateMetadata']>>[1]): Promise<IParsedBlockAsset['resolveMap']> | IParsedBlockAsset['resolveMap'];
|
|
84
84
|
}
|
|
85
85
|
export type IApi = IUmiApi & {
|
|
86
86
|
config: IDumiConfig & {
|
package/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export * from '@@/dumi/exports';
|
|
1
2
|
export { Root as HastRoot } from 'hast';
|
|
2
3
|
export * from 'umi';
|
|
3
4
|
export {
|
|
@@ -7,8 +8,4 @@ export {
|
|
|
7
8
|
export * from './dist';
|
|
8
9
|
// override umi exported defineConfig
|
|
9
10
|
export { defineConfig } from './dist';
|
|
10
|
-
export * from './dist/client/theme-api';
|
|
11
11
|
export { IApi } from './dist/types';
|
|
12
|
-
export function getRouteMetaById(id: string): Promise<any>;
|
|
13
|
-
/** @private Internal usage. Safe to remove */
|
|
14
|
-
export function loadFilesMeta(): Promise<any>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dumi",
|
|
3
|
-
"version": "2.3.0-
|
|
3
|
+
"version": "2.3.0-beta.0",
|
|
4
4
|
"description": "📖 Documentation Generator of React Component",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"generator",
|
|
@@ -122,6 +122,7 @@
|
|
|
122
122
|
"react-copy-to-clipboard": "^5.1.0",
|
|
123
123
|
"react-error-boundary": "^4.0.10",
|
|
124
124
|
"react-intl": "^6.4.4",
|
|
125
|
+
"react-loading-skeleton": "^3.1.1",
|
|
125
126
|
"react-simple-code-editor": "^0.13.1",
|
|
126
127
|
"rehype-autolink-headings": "^6.1.1",
|
|
127
128
|
"rehype-remove-comments": "^5.0.0",
|