dumi 2.2.6 → 2.3.0-alpha.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.
Files changed (38) hide show
  1. package/dist/client/pages/Demo/index.js +3 -4
  2. package/dist/client/theme-api/DumiDemo/DemoErrorBoundary.d.ts +5 -0
  3. package/dist/client/theme-api/DumiDemo/DemoErrorBoundary.js +16 -0
  4. package/dist/client/theme-api/{DumiDemo.d.ts → DumiDemo/index.d.ts} +1 -1
  5. package/dist/client/theme-api/DumiDemo/index.js +37 -0
  6. package/dist/client/theme-api/DumiDemoGrid.js +4 -1
  7. package/dist/client/theme-api/{context.d.ts → context/index.d.ts} +10 -7
  8. package/dist/client/theme-api/context/index.js +49 -0
  9. package/dist/client/theme-api/context/use.d.ts +7 -0
  10. package/dist/client/theme-api/context/use.js +22 -0
  11. package/dist/client/theme-api/index.d.ts +2 -2
  12. package/dist/client/theme-api/index.js +2 -2
  13. package/dist/client/theme-api/useNavData.js +2 -1
  14. package/dist/client/theme-api/useRouteMeta.js +27 -26
  15. package/dist/client/theme-api/useSidebarData.d.ts +2 -1
  16. package/dist/client/theme-api/useSidebarData.js +1 -1
  17. package/dist/constants.d.ts +1 -0
  18. package/dist/constants.js +4 -0
  19. package/dist/features/compile/index.js +13 -1
  20. package/dist/features/exports.js +2 -1
  21. package/dist/features/meta.js +33 -76
  22. package/dist/features/theme/index.js +19 -55
  23. package/dist/loaders/markdown/index.d.ts +15 -3
  24. package/dist/loaders/markdown/index.js +117 -38
  25. package/dist/templates/ContextWrapper.ts.tpl +89 -0
  26. package/dist/templates/meta-demos.ts.tpl +34 -0
  27. package/dist/templates/meta-frontmatter.ts.tpl +9 -0
  28. package/dist/templates/meta-route.ts.tpl +43 -0
  29. package/dist/templates/meta-runtime.ts.tpl +48 -0
  30. package/dist/templates/meta.ts.tpl +23 -0
  31. package/package.json +2 -1
  32. package/theme-default/builtins/API/index.js +2 -0
  33. package/theme-default/layouts/DocLayout/index.js +1 -1
  34. package/theme-default/slots/ColorSwitch/index.less +5 -4
  35. package/theme-default/slots/ContentTabs/index.js +0 -1
  36. package/theme-default/slots/Toc/index.js +1 -1
  37. package/dist/client/theme-api/DumiDemo.js +0 -46
  38. package/dist/client/theme-api/context.js +0 -16
@@ -279,63 +279,27 @@ export default DumiLoading;
279
279
  api.writeTmpFile({
280
280
  noPluginDir: true,
281
281
  path: "dumi/theme/ContextWrapper.tsx",
282
- content: `import React, { useState, useEffect, useRef } from 'react';
283
- import { useOutlet, history } from 'dumi';
284
- import { SiteContext } from '${(0, import_plugin_utils.winPath)(
285
- require.resolve("../../client/theme-api/context")
286
- )}';
287
- import { demos, components } from '../meta';
288
- import { locales } from '../locales/config';${hasDefaultExport ? `
289
- import entryDefaultExport from '${(0, import_plugin_utils.winPath)(entryFile)}';` : ""}${hasNamedExport ? `
290
- import * as entryMemberExports from '${(0, import_plugin_utils.winPath)(entryFile)}';` : ""}
291
-
292
- const entryExports = {
293
- ${hasDefaultExport ? "default: entryDefaultExport," : ""}
294
- ${hasNamedExport ? "...entryMemberExports," : ""}
295
- };
296
-
297
- export default function DumiContextWrapper() {
298
- const outlet = useOutlet();
299
- const [loading, setLoading] = useState(false);
300
- const prev = useRef(history.location.pathname);
301
-
302
- useEffect(() => {
303
- return history.listen((next) => {
304
- if (next.location.pathname !== prev.current) {
305
- prev.current = next.location.pathname;
306
-
307
- // scroll to top when route changed
308
- document.documentElement.scrollTo(0, 0);
282
+ tplPath: (0, import_plugin_utils.winPath)((0, import_path.join)(import_constants.TEMPLATES_DIR, "ContextWrapper.ts.tpl")),
283
+ context: {
284
+ contextPath: (0, import_plugin_utils.winPath)(require.resolve("../../client/theme-api/context")),
285
+ defaultExport: hasDefaultExport ? `import entryDefaultExport from '${(0, import_plugin_utils.winPath)(entryFile)}';` : "",
286
+ namedExport: hasNamedExport ? `import * as entryMemberExports from '${(0, import_plugin_utils.winPath)(entryFile)}';` : "",
287
+ hasDefaultExport,
288
+ hasNamedExport,
289
+ pkg: JSON.stringify(
290
+ import_plugin_utils.lodash.pick(api.pkg, ...Object.keys(import_constants.PICKED_PKG_FIELDS))
291
+ ),
292
+ historyType: ((_a = api.config.history) == null ? void 0 : _a.type) || "browser",
293
+ hostname: String(JSON.stringify((_b = api.config.sitemap) == null ? void 0 : _b.hostname)),
294
+ themeConfig: JSON.stringify(
295
+ Object.assign(
296
+ import_plugin_utils.lodash.pick(api.config, "logo", "description", "title"),
297
+ api.config.themeConfig
298
+ )
299
+ ),
300
+ _2_level_nav_available: api.appData._2LevelNavAvailable
309
301
  }
310
302
  });
311
- }, []);
312
-
313
- return (
314
- <SiteContext.Provider value={{
315
- pkg: ${JSON.stringify(
316
- import_plugin_utils.lodash.pick(api.pkg, ...Object.keys(import_constants.PICKED_PKG_FIELDS))
317
- )},
318
- historyType: "${((_a = api.config.history) == null ? void 0 : _a.type) || "browser"}",
319
- entryExports,
320
- demos,
321
- components,
322
- locales,
323
- loading,
324
- setLoading,
325
- hostname: ${JSON.stringify((_b = api.config.sitemap) == null ? void 0 : _b.hostname)},
326
- themeConfig: ${JSON.stringify(
327
- Object.assign(
328
- import_plugin_utils.lodash.pick(api.config, "logo", "description", "title"),
329
- api.config.themeConfig
330
- )
331
- )},
332
- _2_level_nav_available: ${api.appData._2LevelNavAvailable},
333
- }}>
334
- {outlet}
335
- </SiteContext.Provider>
336
- );
337
- }`
338
- });
339
303
  const primaryColor = typeof ((_c = api.config) == null ? void 0 : _c.theme) === "object" ? (_e = (_d = api.config) == null ? void 0 : _d.theme) == null ? void 0 : _e["@c-primary"] : "#1677ff";
340
304
  api.writeTmpFile({
341
305
  noPluginDir: true,
@@ -3,12 +3,24 @@ import { type IMdTransformerOptions, type IMdTransformerResult } from './transfo
3
3
  interface IMdLoaderDefaultModeOptions extends Omit<IMdTransformerOptions, 'fileAbsPath'> {
4
4
  mode?: 'markdown';
5
5
  builtins: IThemeLoadResult['builtins'];
6
+ onResolveDemos?: (demos: NonNullable<IMdTransformerResult['meta']['demos']>) => void;
7
+ onResolveAtomMeta?: (atomId: string, meta: IMdTransformerResult['meta']['frontmatter']) => void;
6
8
  }
7
9
  interface IMdLoaderDemosModeOptions extends Omit<IMdLoaderDefaultModeOptions, 'builtins' | 'mode'> {
8
10
  mode: 'meta';
9
- onResolveDemos?: (demos: NonNullable<IMdTransformerResult['meta']['demos']>) => void;
10
- onResolveAtomMeta?: (atomId: string, meta: IMdTransformerResult['meta']['frontmatter']) => void;
11
11
  }
12
- export type IMdLoaderOptions = IMdLoaderDefaultModeOptions | IMdLoaderDemosModeOptions;
12
+ interface IMdLoaderDemoModeOptions extends Omit<IMdLoaderDefaultModeOptions, 'builtins' | 'mode'> {
13
+ mode: 'demo';
14
+ }
15
+ interface IMdLoaderDemoIndexModeOptions extends Omit<IMdLoaderDefaultModeOptions, 'builtins' | 'mode'> {
16
+ mode: 'demo-index';
17
+ }
18
+ interface IMdLoaderFrontmatterModeOptions extends Omit<IMdLoaderDefaultModeOptions, 'builtins' | 'mode'> {
19
+ mode: 'frontmatter';
20
+ }
21
+ interface IMdLoaderTextModeOptions extends Omit<IMdLoaderDefaultModeOptions, 'builtins' | 'mode'> {
22
+ mode: 'text';
23
+ }
24
+ export type IMdLoaderOptions = IMdLoaderDefaultModeOptions | IMdLoaderDemosModeOptions | IMdLoaderDemoModeOptions | IMdLoaderFrontmatterModeOptions | IMdLoaderTextModeOptions | IMdLoaderDemoIndexModeOptions;
13
25
  export default function mdLoader(this: any, content: string): void;
14
26
  export {};
@@ -46,20 +46,10 @@ function getDemoSourceFiles(demos = []) {
46
46
  return ret;
47
47
  }, []);
48
48
  }
49
- function emit(opts, ret) {
50
- const { demos, embeds } = ret.meta;
51
- embeds.forEach((file) => this.addDependency(file));
52
- getDemoSourceFiles(demos).forEach((file) => this.addDependency(file));
53
- if (opts.mode === "meta") {
54
- const { frontmatter, toc, texts } = ret.meta;
55
- if (demos && opts.onResolveDemos) {
56
- opts.onResolveDemos(demos);
57
- }
58
- if (frontmatter.atomId && opts.onResolveAtomMeta) {
59
- opts.onResolveAtomMeta(frontmatter.atomId, frontmatter);
60
- }
61
- return import_plugin_utils.Mustache.render(
62
- `import React from 'react';
49
+ function emitMeta(opts, ret) {
50
+ const { frontmatter, toc, texts, demos } = ret.meta;
51
+ return import_plugin_utils.Mustache.render(
52
+ `import React from 'react';
63
53
 
64
54
  export const demos = {
65
55
  {{#demos}}
@@ -73,40 +63,129 @@ export const frontmatter = {{{frontmatter}}};
73
63
  export const toc = {{{toc}}};
74
64
  export const texts = {{{texts}}};
75
65
  `,
76
- {
77
- demos,
78
- frontmatter: JSON.stringify(frontmatter),
79
- toc: JSON.stringify(toc),
80
- texts: JSON.stringify(texts),
81
- renderAsset: function renderAsset() {
82
- if (!("asset" in this))
83
- return "null";
84
- let { asset } = this;
85
- const { sources } = this;
86
- Object.keys(this.sources).forEach((file) => {
87
- if (!asset.dependencies[file])
88
- return;
89
- asset = import_plugin_utils.lodash.cloneDeep(asset);
90
- asset.dependencies[file].value = `{{{require('-!${sources[file]}?dumi-raw').default}}}`;
91
- });
92
- return JSON.stringify(asset, null, 2).replace(/"{{{|}}}"/g, "");
93
- }
66
+ {
67
+ demos,
68
+ frontmatter: JSON.stringify(frontmatter),
69
+ toc: JSON.stringify(toc),
70
+ texts: JSON.stringify(texts),
71
+ renderAsset: function renderAsset() {
72
+ if (!("asset" in this))
73
+ return "null";
74
+ let { asset } = this;
75
+ const { sources } = this;
76
+ Object.keys(this.sources).forEach((file) => {
77
+ if (!asset.dependencies[file])
78
+ return;
79
+ asset = import_plugin_utils.lodash.cloneDeep(asset);
80
+ asset.dependencies[file].value = `{{{require('-!${sources[file]}?dumi-raw').default}}}`;
81
+ });
82
+ return JSON.stringify(asset, null, 2).replace(/"{{{|}}}"/g, "");
94
83
  }
95
- );
96
- } else {
97
- const isTabContent = (0, import_tabs.isTabRouteFile)(this.resourcePath);
98
- return `${Object.values(opts.builtins).map((item) => `import ${item.specifier} from '${item.source}';`).join("\n")}
84
+ }
85
+ );
86
+ }
87
+ function emitDefault(opts, ret) {
88
+ const { frontmatter, demos } = ret.meta;
89
+ const isTabContent = (0, import_tabs.isTabRouteFile)(this.resourcePath);
90
+ if (demos && opts.onResolveDemos) {
91
+ opts.onResolveDemos(demos);
92
+ }
93
+ if (frontmatter.atomId && opts.onResolveAtomMeta) {
94
+ opts.onResolveAtomMeta(frontmatter.atomId, frontmatter);
95
+ }
96
+ return `${Object.values(opts.builtins).map((item) => `import ${item.specifier} from '${item.source}';`).join("\n")}
99
97
  import React from 'react';
100
- ${isTabContent ? `import { useTabMeta } from 'dumi';` : `import { DumiPage, useRouteMeta } from 'dumi';`}
98
+ ${isTabContent ? `` : `import { DumiPage } from 'dumi';`}
99
+ import { texts as ${import_rehypeText.CONTENT_TEXTS_OBJ_NAME} } from '${(0, import_plugin_utils.winPath)(
100
+ this.resourcePath
101
+ )}?type=text';
101
102
 
102
103
  // export named function for fastRefresh
103
104
  // ref: https://github.com/pmmmwh/react-refresh-webpack-plugin/blob/main/docs/TROUBLESHOOTING.md#edits-always-lead-to-full-reload
104
105
  function DumiMarkdownContent() {
105
- const { texts: ${import_rehypeText.CONTENT_TEXTS_OBJ_NAME} } = use${isTabContent ? "TabMeta" : "RouteMeta"}();
106
106
  return ${isTabContent ? ret.content : `<DumiPage>${ret.content}</DumiPage>`};
107
107
  }
108
108
 
109
109
  export default DumiMarkdownContent;`;
110
+ }
111
+ function emitDemo(opts, ret) {
112
+ const { demos } = ret.meta;
113
+ return import_plugin_utils.Mustache.render(
114
+ `import React from 'react';
115
+
116
+ export const demos = {
117
+ {{#demos}}
118
+ '{{{id}}}': {
119
+ component: {{{component}}},
120
+ asset: {{{renderAsset}}}
121
+ },
122
+ {{/demos}}
123
+ };`,
124
+ {
125
+ demos,
126
+ renderAsset: function renderAsset() {
127
+ if (!("asset" in this))
128
+ return "null";
129
+ let { asset } = this;
130
+ const { sources } = this;
131
+ Object.keys(this.sources).forEach((file) => {
132
+ if (!asset.dependencies[file])
133
+ return;
134
+ asset = import_plugin_utils.lodash.cloneDeep(asset);
135
+ asset.dependencies[file].value = `{{{require('-!${sources[file]}?dumi-raw').default}}}`;
136
+ });
137
+ return JSON.stringify(asset, null, 2).replace(/"{{{|}}}"/g, "");
138
+ }
139
+ }
140
+ );
141
+ }
142
+ function emitDemoIndex(opts, ret) {
143
+ const { demos } = ret.meta;
144
+ return import_plugin_utils.Mustache.render(
145
+ `export const demoIndex = {
146
+ ids: {{{ids}}},
147
+ getter: {{{getter}}}
148
+ };`,
149
+ {
150
+ ids: JSON.stringify(demos == null ? void 0 : demos.map((demo) => demo.id)),
151
+ getter: `() => import('${(0, import_plugin_utils.winPath)(this.resourcePath)}?type=demo')`
152
+ }
153
+ );
154
+ }
155
+ function emitFrontmatter(opts, ret) {
156
+ const { frontmatter } = ret.meta;
157
+ return import_plugin_utils.Mustache.render(`export const frontmatter = {{{frontmatter}}};`, {
158
+ frontmatter: JSON.stringify(frontmatter)
159
+ });
160
+ }
161
+ function emitText(opts, ret) {
162
+ const { texts, toc } = ret.meta;
163
+ return import_plugin_utils.Mustache.render(
164
+ `export const toc = {{{toc}}};
165
+ export const texts = {{{texts}}};`,
166
+ {
167
+ toc: JSON.stringify(toc),
168
+ texts: JSON.stringify(texts)
169
+ }
170
+ );
171
+ }
172
+ function emit(opts, ret) {
173
+ const { demos, embeds } = ret.meta;
174
+ embeds.forEach((file) => this.addDependency(file));
175
+ getDemoSourceFiles(demos).forEach((file) => this.addDependency(file));
176
+ switch (opts.mode) {
177
+ case "meta":
178
+ return emitMeta.call(this, opts, ret);
179
+ case "demo":
180
+ return emitDemo.call(this, opts, ret);
181
+ case "demo-index":
182
+ return emitDemoIndex.call(this, opts, ret);
183
+ case "frontmatter":
184
+ return emitFrontmatter.call(this, opts, ret);
185
+ case "text":
186
+ return emitText.call(this, opts, ret);
187
+ default:
188
+ return emitDefault.call(this, opts, ret);
110
189
  }
111
190
  }
112
191
  function getDepsCacheKey(deps = []) {
@@ -0,0 +1,89 @@
1
+ import React, { useState, useEffect, useRef } from 'react';
2
+ import { useOutlet, history } from 'dumi';
3
+ import { warning } from 'rc-util';
4
+ import { SiteContext, type ISiteContext } from '{{{contextPath}}}';
5
+ import { components } from '../meta/atoms';
6
+ import { getDemoById } from '../meta/demos';
7
+ import { locales } from '../locales/config';
8
+ {{{defaultExport}}}
9
+ {{{namedExport}}}
10
+
11
+ const entryExports = {
12
+ {{#hasDefaultExport}}
13
+ default: entryDefaultExport,
14
+ {{/hasDefaultExport}}
15
+ {{#hasNamedExport}}
16
+ ...entryMemberExports,
17
+ {{/hasNamedExport}}
18
+ };
19
+
20
+ // Static content
21
+ const pkg = {{{pkg}}};
22
+ const historyType = "{{{historyType}}}";
23
+ const hostname = {{{hostname}}};
24
+ const themeConfig = {{{themeConfig}}};
25
+ const _2_level_nav_available = {{{_2_level_nav_available}}};
26
+
27
+ export default function DumiContextWrapper() {
28
+ const outlet = useOutlet();
29
+ const [loading, setLoading] = useState(false);
30
+ const prev = useRef(history.location.pathname);
31
+
32
+ useEffect(() => {
33
+ return history.listen((next) => {
34
+ if (next.location.pathname !== prev.current) {
35
+ prev.current = next.location.pathname;
36
+
37
+ // scroll to top when route changed
38
+ document.documentElement.scrollTo(0, 0);
39
+ }
40
+ });
41
+ }, []);
42
+
43
+ const context: ISiteContext = React.useMemo(() => {
44
+ const ctx = {
45
+ pkg,
46
+ historyType,
47
+ entryExports,
48
+ demos: null,
49
+ components,
50
+ locales,
51
+ loading,
52
+ setLoading,
53
+ hostname,
54
+ themeConfig,
55
+ _2_level_nav_available,
56
+ getDemoById,
57
+ };
58
+
59
+ // Proxy do not warning since `Object.keys` will get nothing to loop
60
+ Object.defineProperty(ctx, 'demos', {
61
+ get: () => {
62
+ warning(false, '`demos` return empty in latest version.');
63
+ return {};
64
+ },
65
+ });
66
+
67
+ return ctx;
68
+ }, [
69
+ pkg,
70
+ historyType,
71
+ entryExports,
72
+ components,
73
+ locales,
74
+ loading,
75
+ setLoading,
76
+ hostname,
77
+ themeConfig,
78
+ _2_level_nav_available,
79
+ getDemoById,
80
+ ]);
81
+
82
+
83
+
84
+ return (
85
+ <SiteContext.Provider value={context}>
86
+ {outlet}
87
+ </SiteContext.Provider>
88
+ );
89
+ }
@@ -0,0 +1,34 @@
1
+ {{#metaFiles}}
2
+ import { demoIndex as dmi{{{index}}} } from '{{{file}}}?type=demo-index';
3
+ {{/metaFiles}}
4
+
5
+ const demoIndexes: Record<string, { ids: string[], getter: () => Promise<any> }> = {
6
+ {{#metaFiles}}
7
+ '{{{id}}}': dmi{{{index}}},
8
+ {{/metaFiles}}
9
+ };
10
+
11
+ // Convert the demoIndex to a key-value pairs: <demoId, getter>
12
+ const demoIdMap = Object.keys(demoIndexes).reduce((total, current) => {
13
+ const demoIndex = demoIndexes[current];
14
+ const { ids, getter } = demoIndex;
15
+
16
+ ids.forEach((id) => {
17
+ total[id] = getter;
18
+ });
19
+
20
+ return total;
21
+ }, {});
22
+
23
+ /** Async to load demo by id */
24
+ export const getDemoById = async (id: string) => {
25
+ const getter = demoIdMap[id];
26
+
27
+ if (!getter) {
28
+ return null;
29
+ }
30
+
31
+ const { demos }: any = await getter() || {};
32
+
33
+ return demos?.[id];
34
+ };
@@ -0,0 +1,9 @@
1
+ {{#metaFiles}}
2
+ import { frontmatter as fm{{{index}}} } from '{{{file}}}?type=frontmatter';
3
+ {{/metaFiles}}
4
+
5
+ export const filesFrontmatter = {
6
+ {{#metaFiles}}
7
+ '{{{id}}}': fm{{{index}}},
8
+ {{/metaFiles}}
9
+ }
@@ -0,0 +1,43 @@
1
+ import { tabs } from './tabs';
2
+ import { filesFrontmatter } from './frontmatter';
3
+
4
+ const files = {
5
+ {{#metaFiles}}
6
+ '{{{id}}}': {
7
+ textGetter: () => import('{{{file}}}?type=text'),
8
+ {{#tabs}}
9
+ tabs: {{{tabs}}},
10
+ {{/tabs}}
11
+ },
12
+ {{/metaFiles}}
13
+ };
14
+
15
+ export const getRouteMetaById = async (id: string) => {
16
+ const file = files[id];
17
+
18
+ if (!file) {
19
+ return null;
20
+ }
21
+
22
+ const text = await file.textGetter();
23
+ const frontmatter = filesFrontmatter[id];
24
+
25
+ const tabsMeta = file.tabs && await Promise.all(file.tabs.map(async (tab) => {
26
+ const meta = await getRouteMetaById(tab) ?? {
27
+ frontmatter: { title: tabs[tab].title },
28
+ toc: [],
29
+ texts: [],
30
+ };
31
+ return {
32
+ ...tabs[tab],
33
+ meta,
34
+ }
35
+ }));
36
+
37
+ return {
38
+ texts: text?.texts,
39
+ toc: text?.toc,
40
+ frontmatter,
41
+ tabs: tabsMeta,
42
+ };
43
+ }
@@ -0,0 +1,48 @@
1
+ import { warning } from 'rc-util';
2
+ import { tabs } from './tabs';
3
+ import { filesFrontmatter } from './frontmatter';
4
+ import deepmerge from '{{{deepmerge}}}';
5
+
6
+ // Proxy do not warning since `Object.keys` will get nothing to loop
7
+ function wrapEmpty(meta, fieldName, defaultValue) {
8
+ Object.defineProperty(meta, fieldName, {
9
+ get: () => {
10
+ warning(false, `'${fieldName}' return empty in latest version.`);
11
+ return defaultValue;
12
+ },
13
+ });
14
+ }
15
+
16
+ export const patchRoutes = ({ routes }) => {
17
+ Object.values(routes).forEach((route) => {
18
+ if (filesFrontmatter[route.id]) {
19
+ if (process.env.NODE_ENV === 'production' && (route.meta?.frontmatter?.debug || filesFrontmatter[route.id].debug)) {
20
+ // hide route in production which set hide frontmatter
21
+ delete routes[route.id];
22
+ } else {
23
+ // merge meta to route object
24
+ route.meta = deepmerge(route.meta, { frontmatter: filesFrontmatter[route.id] });
25
+
26
+ wrapEmpty(route.meta, 'demos', {});
27
+ wrapEmpty(route.meta, 'texts', []);
28
+
29
+ // apply real tab data from id
30
+ route.meta.tabs = route.meta.tabs?.map((id) => {
31
+ const meta = {
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
+ }
44
+ });
45
+ }
46
+ }
47
+ });
48
+ }
@@ -0,0 +1,23 @@
1
+ {{#metaFiles}}
2
+ import { frontmatter as fm{{{index}}}, toc as toc{{{index}}} } from '{{{file}}}?type=meta';
3
+ {{/metaFiles}}
4
+
5
+ export { components } from './atoms';
6
+ export { tabs } from './tabs';
7
+
8
+ export const filesMeta = {
9
+ {{#metaFiles}}
10
+ '{{{id}}}': {
11
+ frontmatter: fm{{{index}}},
12
+ toc: toc{{{index}}},
13
+ texts: [],
14
+ demos: {},
15
+ {{#tabs}}
16
+ tabs: {{{tabs}}},
17
+ {{/tabs}}
18
+ },
19
+ {{/metaFiles}}
20
+ }
21
+
22
+ // generate demos data in runtime, for reuse route.id to reduce bundle size
23
+ export const demos = {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dumi",
3
- "version": "2.2.6",
3
+ "version": "2.3.0-alpha.0",
4
4
  "description": "📖 Documentation Generator of React Component",
5
5
  "keywords": [
6
6
  "generator",
@@ -117,6 +117,7 @@
117
117
  "rc-motion": "^2.7.3",
118
118
  "rc-tabs": "^12.10.0",
119
119
  "rc-tree": "^5.7.9",
120
+ "rc-util": "^5.37.0",
120
121
  "react-copy-to-clipboard": "^5.1.0",
121
122
  "react-error-boundary": "^4.0.10",
122
123
  "react-intl": "^6.4.4",
@@ -69,6 +69,8 @@ var HANDLERS = {
69
69
  function: function _function(_ref3) {
70
70
  var _this2 = this;
71
71
  var signature = _ref3.signature;
72
+ // handle Function type without signature
73
+ if (!signature) return 'Function';
72
74
  var signatures = 'oneOf' in signature ? signature.oneOf : [signature];
73
75
  return signatures.map(function (signature) {
74
76
  return "".concat(signature.isAsync ? 'async ' : '', "(").concat(signature.arguments.map(function (arg) {
@@ -4,11 +4,11 @@ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o =
4
4
  function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
5
5
  function _iterableToArrayLimit(arr, i) { var _i = null == arr ? null : "undefined" != typeof Symbol && arr[Symbol.iterator] || arr["@@iterator"]; if (null != _i) { var _s, _e, _x, _r, _arr = [], _n = !0, _d = !1; try { if (_x = (_i = _i.call(arr)).next, 0 === i) { if (Object(_i) !== _i) return; _n = !1; } else for (; !(_n = (_s = _x.call(_i)).done) && (_arr.push(_s.value), _arr.length !== i); _n = !0); } catch (err) { _d = !0, _e = err; } finally { try { if (!_n && null != _i.return && (_r = _i.return(), Object(_r) !== _r)) return; } finally { if (_d) throw _e; } } return _arr; } }
6
6
  function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
7
- import ContentFooter from "../../slots/ContentFooter";
8
7
  import { ReactComponent as IconSidebar } from '@ant-design/icons-svg/inline-svg/outlined/align-left.svg';
9
8
  import animateScrollTo from 'animated-scroll-to';
10
9
  import { Helmet, useIntl, useLocation, useOutlet, useRouteMeta, useSidebarData, useSiteData } from 'dumi';
11
10
  import Content from 'dumi/theme/slots/Content';
11
+ import ContentFooter from 'dumi/theme/slots/ContentFooter';
12
12
  import Features from 'dumi/theme/slots/Features';
13
13
  import Footer from 'dumi/theme/slots/Footer';
14
14
  import Header from 'dumi/theme/slots/Header';
@@ -50,11 +50,12 @@
50
50
 
51
51
  select {
52
52
  position: absolute;
53
- top: 0;
54
- left: 0;
53
+ inset: 0 15%;
55
54
  opacity: 0;
56
- max-width: 100%;
57
- max-height: 16px;
55
+ width: 100%;
56
+ min-width: 16px;
57
+ max-width: 70%;
58
+ height: 16px;
58
59
  cursor: pointer;
59
60
  }
60
61
  }
@@ -8,7 +8,6 @@ var ContentTabs = function ContentTabs(_ref) {
8
8
  var intl = useIntl();
9
9
 
10
10
  // TODO: tab.Extra & tab.Action render
11
-
12
11
  return Boolean(tabs === null || tabs === void 0 ? void 0 : tabs.length) ? /*#__PURE__*/React.createElement("ul", {
13
12
  className: "dumi-default-content-tabs"
14
13
  }, /*#__PURE__*/React.createElement("li", {
@@ -46,7 +46,7 @@ var Toc = function Toc() {
46
46
  });
47
47
  setSectionRefs(refs);
48
48
  }
49
- }, [pathname, search, loading]);
49
+ }, [pathname, search, loading, memoToc]);
50
50
  return sectionRefs.length ? /*#__PURE__*/React.createElement(ScrollSpy, {
51
51
  sectionRefs: sectionRefs
52
52
  }, function (_ref3) {
@@ -1,46 +0,0 @@
1
- function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
2
- import { SP_ROUTE_PREFIX } from "../../constants";
3
- import { useAppData, useSiteData } from 'dumi';
4
- import Container from 'dumi/theme/builtins/Container';
5
- import Previewer from 'dumi/theme/builtins/Previewer';
6
- import React, { createElement } from 'react';
7
- import { ErrorBoundary } from 'react-error-boundary';
8
- var DemoErrorBoundary = function DemoErrorBoundary(props) {
9
- return /*#__PURE__*/React.createElement(ErrorBoundary, {
10
- fallbackRender: function fallbackRender(_ref) {
11
- var error = _ref.error;
12
- return /*#__PURE__*/React.createElement(Container, {
13
- type: "error"
14
- }, /*#__PURE__*/React.createElement("p", null, /*#__PURE__*/React.createElement("strong", null, error.message || 'This demo has been crashed.')), error.stack && /*#__PURE__*/React.createElement("p", null, /*#__PURE__*/React.createElement("details", {
15
- open: true
16
- }, /*#__PURE__*/React.createElement("summary", null, "Error stack"), /*#__PURE__*/React.createElement("pre", null, error.stack))));
17
- }
18
- }, props.children);
19
- };
20
- export var DumiDemo = /*#__PURE__*/React.memo(function (props) {
21
- var _useSiteData = useSiteData(),
22
- demos = _useSiteData.demos,
23
- historyType = _useSiteData.historyType;
24
- var _useAppData = useAppData(),
25
- basename = _useAppData.basename;
26
- var _demos$props$demo$id = demos[props.demo.id],
27
- component = _demos$props$demo$id.component,
28
- asset = _demos$props$demo$id.asset;
29
-
30
- // hide debug demo in production
31
- if (process.env.NODE_ENV === 'production' && props.previewerProps.debug) return null;
32
- if (props.demo.inline) {
33
- return /*#__PURE__*/React.createElement(DemoErrorBoundary, null, /*#__PURE__*/createElement(component));
34
- }
35
- var isHashRoute = historyType === 'hash';
36
- return /*#__PURE__*/React.createElement(Previewer, _extends({
37
- asset: asset,
38
- demoUrl:
39
- // allow user override demoUrl by frontmatter
40
- props.previewerProps.demoUrl || // when use hash route, browser can automatically handle relative paths starting with #
41
- "".concat(isHashRoute ? "#" : '').concat(basename).concat(SP_ROUTE_PREFIX, "demos/").concat(props.demo.id)
42
- }, props.previewerProps), props.previewerProps.iframe ? null : /*#__PURE__*/React.createElement(DemoErrorBoundary, null, /*#__PURE__*/createElement(component)));
43
- }, function (prev, next) {
44
- // compare length for performance
45
- return JSON.stringify(prev).length === JSON.stringify(next).length;
46
- });