dumi 2.0.0-beta.3 → 2.0.0-beta.5
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/client/theme-api/DumiDemo.js +1 -1
- package/dist/client/theme-api/DumiPage.d.ts +4 -0
- package/dist/client/theme-api/DumiPage.js +39 -0
- package/dist/client/theme-api/index.d.ts +2 -1
- package/dist/client/theme-api/index.js +2 -1
- package/dist/client/theme-api/types.d.ts +14 -1
- package/dist/client/theme-api/useSidebarData.js +4 -2
- package/dist/features/configPlugins/schema.js +1 -1
- package/dist/features/meta.d.ts +1 -0
- package/dist/features/meta.js +42 -19
- package/dist/features/parser.js +7 -1
- package/dist/features/routes.js +14 -4
- package/dist/features/tabs.d.ts +5 -0
- package/dist/features/tabs.js +106 -0
- package/dist/loaders/markdown/index.js +4 -9
- package/dist/loaders/markdown/transformer/rehypeJsxify.js +1 -1
- package/dist/loaders/markdown/transformer/remarkMeta.js +7 -2
- package/dist/preset.js +1 -0
- package/dist/types.d.ts +4 -1
- package/package.json +1 -1
- package/theme-default/locales/en-US.json +2 -1
- package/theme-default/locales/zh-CN.json +2 -1
- package/theme-default/slots/Content/index.less +1 -1
- package/theme-default/slots/ContentTabs/index.d.ts +11 -0
- package/theme-default/slots/ContentTabs/index.js +35 -0
- package/theme-default/slots/ContentTabs/index.less +57 -0
- package/theme-default/styles/variables.less +1 -0
|
@@ -14,6 +14,6 @@ export var DumiDemo = function DumiDemo(props) {
|
|
|
14
14
|
return /*#__PURE__*/React.createElement(Previewer, _extends({
|
|
15
15
|
asset: asset,
|
|
16
16
|
demoUrl: // allow user override demoUrl by frontmatter
|
|
17
|
-
props.previewerProps.demoUrl || "".concat(SP_ROUTE_PREFIX, "demos/").concat(props.demo.id)
|
|
17
|
+
props.previewerProps.demoUrl || "/".concat(SP_ROUTE_PREFIX, "demos/").concat(props.demo.id)
|
|
18
18
|
}, props.previewerProps), /*#__PURE__*/createElement(component));
|
|
19
19
|
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
|
|
2
|
+
|
|
3
|
+
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
4
|
+
|
|
5
|
+
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
|
|
6
|
+
|
|
7
|
+
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; }
|
|
8
|
+
|
|
9
|
+
function _iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
|
|
10
|
+
|
|
11
|
+
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
|
|
12
|
+
|
|
13
|
+
import { useRouteMeta, useSiteData } from 'dumi';
|
|
14
|
+
import ContentTabs from 'dumi/theme/slots/ContentTabs';
|
|
15
|
+
import React, { useEffect, useState } from 'react';
|
|
16
|
+
export var DumiPage = function DumiPage(props) {
|
|
17
|
+
var _useRouteMeta = useRouteMeta(),
|
|
18
|
+
tabs = _useRouteMeta.tabs;
|
|
19
|
+
|
|
20
|
+
var _useState = useState(),
|
|
21
|
+
_useState2 = _slicedToArray(_useState, 2),
|
|
22
|
+
tab = _useState2[0],
|
|
23
|
+
setTab = _useState2[1];
|
|
24
|
+
|
|
25
|
+
var _useSiteData = useSiteData(),
|
|
26
|
+
setLoading = _useSiteData.setLoading; // update loading status when page loaded
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
useEffect(function () {
|
|
30
|
+
setLoading(false);
|
|
31
|
+
}, []);
|
|
32
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(ContentTabs, {
|
|
33
|
+
tabs: tabs,
|
|
34
|
+
tabKey: tab === null || tab === void 0 ? void 0 : tab.key,
|
|
35
|
+
onChange: function onChange(val) {
|
|
36
|
+
setTab(val);
|
|
37
|
+
}
|
|
38
|
+
}), tab ? /*#__PURE__*/React.createElement(tab.components.default) : props.children);
|
|
39
|
+
};
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
export { useIntl } from 'react-intl';
|
|
1
|
+
export { createIntlCache, defineMessages, FormattedDate, FormattedDateParts, FormattedDisplayName, FormattedList, FormattedMessage, FormattedNumber, FormattedNumberParts, FormattedPlural, FormattedRelativeTime, FormattedTime, FormattedTimeParts, injectIntl, IntlContext, IntlProvider, RawIntlProvider, useIntl, } from 'react-intl';
|
|
2
2
|
export { useSiteData } from './context';
|
|
3
3
|
export { DumiDemo } from './DumiDemo';
|
|
4
4
|
export { DumiDemoGrid } from './DumiDemoGrid';
|
|
5
|
+
export { DumiPage } from './DumiPage';
|
|
5
6
|
export type { IPreviewerProps } from './types';
|
|
6
7
|
export { useAtomAssets } from './useAtomAssets';
|
|
7
8
|
export { useLocale } from './useLocale';
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
export { useIntl } from 'react-intl';
|
|
1
|
+
export { createIntlCache, defineMessages, FormattedDate, FormattedDateParts, FormattedDisplayName, FormattedList, FormattedMessage, FormattedNumber, FormattedNumberParts, FormattedPlural, FormattedRelativeTime, FormattedTime, FormattedTimeParts, injectIntl, IntlContext, IntlProvider, RawIntlProvider, useIntl } from 'react-intl';
|
|
2
2
|
export { useSiteData } from "./context";
|
|
3
3
|
export { DumiDemo } from "./DumiDemo";
|
|
4
4
|
export { DumiDemoGrid } from "./DumiDemoGrid";
|
|
5
|
+
export { DumiPage } from "./DumiPage";
|
|
5
6
|
export { useAtomAssets } from "./useAtomAssets";
|
|
6
7
|
export { useLocale } from "./useLocale";
|
|
7
8
|
export { useNavData } from "./useNavData";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ExampleBlockAsset } from 'dumi-assets-types';
|
|
2
|
-
import type { ReactNode } from 'react';
|
|
2
|
+
import type { ComponentType, ReactNode } from 'react';
|
|
3
3
|
export interface IPreviewerProps {
|
|
4
4
|
/**
|
|
5
5
|
* title of current demo
|
|
@@ -68,6 +68,17 @@ export interface IRouteMeta {
|
|
|
68
68
|
depth: number;
|
|
69
69
|
title: string;
|
|
70
70
|
}[];
|
|
71
|
+
tabs?: {
|
|
72
|
+
key: string;
|
|
73
|
+
components: {
|
|
74
|
+
default: ComponentType;
|
|
75
|
+
Extra: ComponentType;
|
|
76
|
+
Action: ComponentType;
|
|
77
|
+
};
|
|
78
|
+
frontmatter: Omit<IRouteMeta['frontmatter'], 'description' | 'keywords' | 'nav' | 'group'>;
|
|
79
|
+
toc: IRouteMeta['toc'];
|
|
80
|
+
[key: string]: any;
|
|
81
|
+
}[];
|
|
71
82
|
[key: string]: any;
|
|
72
83
|
}
|
|
73
84
|
declare type IBasicLocale = {
|
|
@@ -88,6 +99,8 @@ export interface INavItem {
|
|
|
88
99
|
interface ISidebarItem {
|
|
89
100
|
title: string;
|
|
90
101
|
link: string;
|
|
102
|
+
order: number;
|
|
103
|
+
frontmatter: IRouteMeta['frontmatter'];
|
|
91
104
|
[key: string]: any;
|
|
92
105
|
}
|
|
93
106
|
export interface ISidebarGroup {
|
|
@@ -71,7 +71,8 @@ export var useFullSidebarData = function useFullSidebarData() {
|
|
|
71
71
|
children: [].concat(_toConsumableArray(((_ret$parentPath$title2 = ret[parentPath][titleKey]) === null || _ret$parentPath$title2 === void 0 ? void 0 : _ret$parentPath$title2.children) || []), [{
|
|
72
72
|
title: route.meta.frontmatter.title,
|
|
73
73
|
link: "/".concat(route.path),
|
|
74
|
-
order: route.meta.frontmatter.order || 0
|
|
74
|
+
order: route.meta.frontmatter.order || 0,
|
|
75
|
+
frontmatter: route.meta.frontmatter
|
|
75
76
|
}])
|
|
76
77
|
};
|
|
77
78
|
}
|
|
@@ -125,7 +126,8 @@ export var useSidebarData = function useSidebarData() {
|
|
|
125
126
|
// /a/b => /a
|
|
126
127
|
// /en-US/a => /en-US/a
|
|
127
128
|
// /en-US/a/b => /en-US/a
|
|
129
|
+
// /en-US/a/b/ => /en-US/a (also strip trailing /)
|
|
128
130
|
|
|
129
|
-
var parentPath = clearPath ? pathname.replace(/(\/[^/]+)(\/[^/]
|
|
131
|
+
var parentPath = clearPath ? pathname.replace(/(\/[^/]+)(\/[^/]+\/?)$/, '$1') : pathname;
|
|
130
132
|
return parentPath ? sidebar[parentPath] : [];
|
|
131
133
|
};
|
|
@@ -28,7 +28,7 @@ function getUnifiedPluginSchema(Joi) {
|
|
|
28
28
|
function getSchemas() {
|
|
29
29
|
return {
|
|
30
30
|
resolve: (Joi) => Joi.object({
|
|
31
|
-
docDirs: Joi.array().items(Joi.string()).optional(),
|
|
31
|
+
docDirs: Joi.array().items(Joi.alternatives(Joi.string(), Joi.object({ dir: Joi.string(), type: Joi.string().optional() }))).optional(),
|
|
32
32
|
entityDirs: Joi.array().items(Joi.object({ type: Joi.string(), dir: Joi.string() })).optional(),
|
|
33
33
|
codeBlockMode: Joi.string().valid("active", "passive").optional(),
|
|
34
34
|
entryFile: Joi.string().optional()
|
package/dist/features/meta.d.ts
CHANGED
package/dist/features/meta.js
CHANGED
|
@@ -20,19 +20,22 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
var meta_exports = {};
|
|
21
21
|
__export(meta_exports, {
|
|
22
22
|
ATOMS_META_PATH: () => ATOMS_META_PATH,
|
|
23
|
+
TABS_META_PATH: () => TABS_META_PATH,
|
|
23
24
|
default: () => meta_default
|
|
24
25
|
});
|
|
25
26
|
module.exports = __toCommonJS(meta_exports);
|
|
26
27
|
var import_plugin_utils = require("umi/plugin-utils");
|
|
28
|
+
var import_tabs = require("./tabs");
|
|
29
|
+
var TABS_META_PATH = "dumi/meta/tabs.ts";
|
|
27
30
|
var ATOMS_META_PATH = "dumi/meta/atoms.ts";
|
|
28
31
|
var meta_default = (api) => {
|
|
29
|
-
const
|
|
32
|
+
const metaFiles = [];
|
|
30
33
|
api.modifyRoutes((routes) => {
|
|
31
|
-
|
|
34
|
+
metaFiles.length = 0;
|
|
32
35
|
Object.values(routes).forEach((route) => {
|
|
33
|
-
if (!route.isLayout && !/\*|:/.test(route.path)) {
|
|
34
|
-
|
|
35
|
-
index:
|
|
36
|
+
if (!route.isLayout && !/\*|:/.test(route.path) && !(0, import_tabs.isTabRouteFile)(route.file)) {
|
|
37
|
+
metaFiles.push({
|
|
38
|
+
index: metaFiles.length,
|
|
36
39
|
file: route.file,
|
|
37
40
|
id: route.id
|
|
38
41
|
});
|
|
@@ -40,7 +43,7 @@ var meta_default = (api) => {
|
|
|
40
43
|
});
|
|
41
44
|
return routes;
|
|
42
45
|
});
|
|
43
|
-
api.onGenerateFiles(() => {
|
|
46
|
+
api.onGenerateFiles(async () => {
|
|
44
47
|
api.writeTmpFile({
|
|
45
48
|
noPluginDir: true,
|
|
46
49
|
path: ATOMS_META_PATH,
|
|
@@ -49,32 +52,51 @@ var meta_default = (api) => {
|
|
|
49
52
|
api.writeTmpFile({
|
|
50
53
|
noPluginDir: true,
|
|
51
54
|
path: "dumi/meta/index.ts",
|
|
52
|
-
content: import_plugin_utils.Mustache.render(`{{#
|
|
55
|
+
content: import_plugin_utils.Mustache.render(`{{#metaFiles}}
|
|
53
56
|
import { demos as d{{{index}}}, frontmatter as fm{{{index}}}, toc as toc{{{index}}} } from '{{{file}}}?type=meta';
|
|
54
|
-
{{/
|
|
57
|
+
{{/metaFiles}}
|
|
55
58
|
|
|
56
59
|
export { components } from './atoms';
|
|
60
|
+
export { tabs } from './tabs';
|
|
57
61
|
|
|
58
62
|
export const demos = {
|
|
59
|
-
{{#
|
|
63
|
+
{{#metaFiles}}
|
|
60
64
|
...d{{{index}}},
|
|
61
|
-
{{/
|
|
65
|
+
{{/metaFiles}}
|
|
62
66
|
};
|
|
63
67
|
|
|
64
|
-
export const
|
|
65
|
-
{{#
|
|
66
|
-
'{{{id}}}': {
|
|
67
|
-
|
|
68
|
-
|
|
68
|
+
export const filesMeta = {
|
|
69
|
+
{{#metaFiles}}
|
|
70
|
+
'{{{id}}}': {
|
|
71
|
+
frontmatter: fm{{{index}}},
|
|
72
|
+
toc: toc{{{index}}},
|
|
73
|
+
{{#tabs}}
|
|
74
|
+
tabs: {{{tabs}}},
|
|
75
|
+
{{/tabs}}
|
|
76
|
+
},
|
|
77
|
+
{{/metaFiles}}
|
|
78
|
+
}`, {
|
|
79
|
+
metaFiles: await api.applyPlugins({
|
|
80
|
+
type: api.ApplyPluginsType.modify,
|
|
81
|
+
key: "dumi.modifyMetaFiles",
|
|
82
|
+
initialValue: metaFiles
|
|
83
|
+
})
|
|
84
|
+
})
|
|
69
85
|
});
|
|
70
86
|
api.writeTmpFile({
|
|
71
87
|
noPluginDir: true,
|
|
72
88
|
path: "dumi/meta/runtime.ts",
|
|
73
|
-
content: `import {
|
|
89
|
+
content: `import { filesMeta, tabs } from '.';
|
|
74
90
|
export const patchRoutes = ({ routes }) => {
|
|
75
91
|
Object.values(routes).forEach((route) => {
|
|
76
|
-
if (
|
|
77
|
-
route.meta = { ...route.meta, ...
|
|
92
|
+
if (filesMeta[route.id]) {
|
|
93
|
+
route.meta = { ...route.meta, ...filesMeta[route.id] };
|
|
94
|
+
|
|
95
|
+
// apply real tab data from id
|
|
96
|
+
route.meta.tabs = route.meta.tabs?.map(id => ({
|
|
97
|
+
...tabs[id],
|
|
98
|
+
...filesMeta[id],
|
|
99
|
+
}));
|
|
78
100
|
}
|
|
79
101
|
});
|
|
80
102
|
}
|
|
@@ -85,5 +107,6 @@ export const patchRoutes = ({ routes }) => {
|
|
|
85
107
|
};
|
|
86
108
|
// Annotate the CommonJS export names for ESM import in node:
|
|
87
109
|
0 && (module.exports = {
|
|
88
|
-
ATOMS_META_PATH
|
|
110
|
+
ATOMS_META_PATH,
|
|
111
|
+
TABS_META_PATH
|
|
89
112
|
});
|
package/dist/features/parser.js
CHANGED
|
@@ -35,7 +35,13 @@ var parser_default = (api) => {
|
|
|
35
35
|
content: `export const components = ${JSON.stringify(data.components, null, 2)};`
|
|
36
36
|
});
|
|
37
37
|
};
|
|
38
|
-
api.describe({
|
|
38
|
+
api.describe({
|
|
39
|
+
key: "apiParser",
|
|
40
|
+
enableBy: api.EnableBy.config,
|
|
41
|
+
config: {
|
|
42
|
+
schema: (Joi) => Joi.object()
|
|
43
|
+
}
|
|
44
|
+
});
|
|
39
45
|
api.modifyDefaultConfig((memo) => {
|
|
40
46
|
var _a;
|
|
41
47
|
if (!((_a = api.userConfig.resolve) == null ? void 0 : _a.entryFile)) {
|
package/dist/features/routes.js
CHANGED
|
@@ -32,6 +32,9 @@ var import_path = __toESM(require("path"));
|
|
|
32
32
|
var import_pluralize = require("pluralize");
|
|
33
33
|
var import_plugin_utils = require("umi/plugin-utils");
|
|
34
34
|
var CTX_LAYOUT_ID = "dumi-context-layout";
|
|
35
|
+
function normalizeDocDir(docDir) {
|
|
36
|
+
return typeof docDir === "object" ? docDir : { dir: docDir };
|
|
37
|
+
}
|
|
35
38
|
function localizeUmiRoute(route, locales) {
|
|
36
39
|
const locale = locales.find((locale2) => route.path.endsWith(`/${locale2.id}`) && import_path.default.parse(route.file).name.endsWith(`.${locale2.id}`));
|
|
37
40
|
if (locale) {
|
|
@@ -44,9 +47,11 @@ function localizeUmiRoute(route, locales) {
|
|
|
44
47
|
var routes_default = (api) => {
|
|
45
48
|
var _a, _b, _c;
|
|
46
49
|
const extraWatchPaths = [
|
|
47
|
-
...((
|
|
48
|
-
...((_c = api.userConfig.resolve) == null ? void 0 :
|
|
49
|
-
|
|
50
|
+
...((_a = api.userConfig.resolve) == null ? void 0 : _a.entityDirs) || [],
|
|
51
|
+
...((_c = (_b = api.userConfig.resolve) == null ? void 0 : _b.docDirs) == null ? void 0 : _c.map(normalizeDocDir)) || [
|
|
52
|
+
{ dir: "docs" }
|
|
53
|
+
]
|
|
54
|
+
].map(({ dir }) => import_path.default.join(api.cwd, dir, "**/*.md"));
|
|
50
55
|
const pagesDir = import_path.default.join(api.cwd, ".dumi/pages");
|
|
51
56
|
api.describe({ key: "dumi:routes" });
|
|
52
57
|
api.addTmpGenerateWatcherPaths(() => extraWatchPaths);
|
|
@@ -110,7 +115,7 @@ var routes_default = (api) => {
|
|
|
110
115
|
route.file = import_path.default.resolve(pagesDir, route.file);
|
|
111
116
|
routes[route.id] = route;
|
|
112
117
|
});
|
|
113
|
-
docDirs.forEach((dir) => {
|
|
118
|
+
docDirs.map(normalizeDocDir).forEach(({ type, dir }) => {
|
|
114
119
|
const base = import_path.default.join(api.cwd, dir);
|
|
115
120
|
const dirRoutes = (0, import_core.getConventionRoutes)({
|
|
116
121
|
base,
|
|
@@ -119,6 +124,11 @@ var routes_default = (api) => {
|
|
|
119
124
|
Object.entries(dirRoutes).forEach(([key, route]) => {
|
|
120
125
|
route.id = `${dir}/${key}`;
|
|
121
126
|
route.parentId = docLayoutId;
|
|
127
|
+
if (type) {
|
|
128
|
+
const pluralType = (0, import_pluralize.plural)(type);
|
|
129
|
+
route.path = `${pluralType}/${route.path}`.replace(/\/+$/, "/");
|
|
130
|
+
route.absPath = `/${route.path}`;
|
|
131
|
+
}
|
|
122
132
|
route.file = import_path.default.resolve(base, route.file);
|
|
123
133
|
localizeUmiRoute(route, api.config.locales);
|
|
124
134
|
routes[route.id] = route;
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod));
|
|
20
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
21
|
+
|
|
22
|
+
// src/features/tabs.ts
|
|
23
|
+
var tabs_exports = {};
|
|
24
|
+
__export(tabs_exports, {
|
|
25
|
+
default: () => tabs_default,
|
|
26
|
+
getTabKeyFromFile: () => getTabKeyFromFile,
|
|
27
|
+
isTabRouteFile: () => isTabRouteFile
|
|
28
|
+
});
|
|
29
|
+
module.exports = __toCommonJS(tabs_exports);
|
|
30
|
+
var import_utils = require("@umijs/core/dist/route/utils");
|
|
31
|
+
var import_path = __toESM(require("path"));
|
|
32
|
+
var import_plugin_utils = require("umi/plugin-utils");
|
|
33
|
+
var import_meta = require("./meta");
|
|
34
|
+
function isTabRouteFile(file) {
|
|
35
|
+
return file.includes("$tab-");
|
|
36
|
+
}
|
|
37
|
+
function getTabKeyFromFile(file) {
|
|
38
|
+
return file.match(/\$tab-([^.]+)/)[1];
|
|
39
|
+
}
|
|
40
|
+
var tabs_default = (api) => {
|
|
41
|
+
const tabs = [];
|
|
42
|
+
api.describe({ key: void 0 });
|
|
43
|
+
api.modifyRoutes((routes) => {
|
|
44
|
+
tabs.length = 0;
|
|
45
|
+
Object.values(routes).forEach((route) => {
|
|
46
|
+
if (isTabRouteFile(route.file)) {
|
|
47
|
+
delete routes[route.id];
|
|
48
|
+
const rtlFile = (0, import_plugin_utils.winPath)(import_path.default.relative(api.cwd, route.file));
|
|
49
|
+
const routeId = (0, import_utils.createRouteId)(rtlFile);
|
|
50
|
+
const tabKey = getTabKeyFromFile(rtlFile);
|
|
51
|
+
const parentFile = route.file.replace(/\$tab-[^.]+\./, "");
|
|
52
|
+
tabs.push({
|
|
53
|
+
index: tabs.length,
|
|
54
|
+
key: tabKey,
|
|
55
|
+
id: `${routeId}`,
|
|
56
|
+
file: route.file,
|
|
57
|
+
parentFile
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
return routes;
|
|
62
|
+
});
|
|
63
|
+
api.register({
|
|
64
|
+
key: "dumi.modifyMetaFiles",
|
|
65
|
+
fn: (metaFiles) => {
|
|
66
|
+
const tabsMapping = tabs.reduce((ret, tab) => ({
|
|
67
|
+
...ret,
|
|
68
|
+
[tab.parentFile]: [...ret[tab.parentFile] || [], tab]
|
|
69
|
+
}), {});
|
|
70
|
+
Object.values(metaFiles).forEach((metaFile) => {
|
|
71
|
+
if (tabsMapping[metaFile.file]) {
|
|
72
|
+
metaFile.tabs = JSON.stringify(tabsMapping[metaFile.file].map(({ id }) => id));
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
tabs.forEach((tab) => {
|
|
76
|
+
metaFiles.push({
|
|
77
|
+
id: tab.id,
|
|
78
|
+
file: tab.file,
|
|
79
|
+
index: metaFiles.length
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
return metaFiles;
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
api.onGenerateFiles(() => {
|
|
86
|
+
api.writeTmpFile({
|
|
87
|
+
noPluginDir: true,
|
|
88
|
+
path: import_meta.TABS_META_PATH,
|
|
89
|
+
content: import_plugin_utils.Mustache.render(`{{#tabs}}
|
|
90
|
+
import * as tab{{{index}}} from '{{{file}}}';
|
|
91
|
+
{{/tabs}}
|
|
92
|
+
|
|
93
|
+
export const tabs = {
|
|
94
|
+
{{#tabs}}
|
|
95
|
+
'{{{id}}}': { key: '{{{key}}}', components: tab{{{index}}} },
|
|
96
|
+
{{/tabs}}
|
|
97
|
+
}
|
|
98
|
+
`, { tabs })
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
};
|
|
102
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
103
|
+
0 && (module.exports = {
|
|
104
|
+
getTabKeyFromFile,
|
|
105
|
+
isTabRouteFile
|
|
106
|
+
});
|
|
@@ -71,20 +71,15 @@ export const toc = {{{toc}}}
|
|
|
71
71
|
}
|
|
72
72
|
}));
|
|
73
73
|
} else {
|
|
74
|
+
const isFragment = Boolean(this.resourcePath.includes("$tab-") || this.resourceQuery);
|
|
74
75
|
cb(null, `${Object.values(opts.builtins).map((item) => `import ${item.specifier} from '${item.source}';`).join("\n")}
|
|
75
|
-
import React
|
|
76
|
-
import {
|
|
76
|
+
import React from 'react';${isFragment ? "" : `
|
|
77
|
+
import { DumiPage } from 'dumi'`}
|
|
77
78
|
|
|
78
79
|
// export named function for fastRefresh
|
|
79
80
|
// ref: https://github.com/pmmmwh/react-refresh-webpack-plugin/blob/main/docs/TROUBLESHOOTING.md#edits-always-lead-to-full-reload
|
|
80
81
|
function DumiMarkdownContent() {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
useEffect(() => {
|
|
84
|
-
setLoading(false);
|
|
85
|
-
}, []);
|
|
86
|
-
|
|
87
|
-
return ${ret.content};
|
|
82
|
+
return ${isFragment ? ret.content : `<DumiPage>${ret.content}</DumiPage>`};
|
|
88
83
|
}
|
|
89
84
|
|
|
90
85
|
export default DumiMarkdownContent;`);
|
|
@@ -25,6 +25,7 @@ __export(remarkMeta_exports, {
|
|
|
25
25
|
default: () => remarkMeta
|
|
26
26
|
});
|
|
27
27
|
module.exports = __toCommonJS(remarkMeta_exports);
|
|
28
|
+
var import_tabs = require("../../../features/tabs");
|
|
28
29
|
var import_js_yaml = __toESM(require("js-yaml"));
|
|
29
30
|
var import_path = __toESM(require("path"));
|
|
30
31
|
var import_plugin_utils = require("umi/plugin-utils");
|
|
@@ -52,8 +53,12 @@ function remarkMeta(opts) {
|
|
|
52
53
|
});
|
|
53
54
|
},
|
|
54
55
|
() => {
|
|
55
|
-
|
|
56
|
-
|
|
56
|
+
if ((0, import_tabs.isTabRouteFile)(opts.fileAbsPath)) {
|
|
57
|
+
vFile.data.frontmatter.title = import_plugin_utils.lodash.startCase((0, import_tabs.getTabKeyFromFile)(opts.fileAbsPath));
|
|
58
|
+
} else {
|
|
59
|
+
const pathWithoutIndex = opts.fileAbsPath.replace(/(\/index([^/]+)?)?\.md$/, "");
|
|
60
|
+
vFile.data.frontmatter.title = import_plugin_utils.lodash.startCase(import_path.default.basename(pathWithoutIndex));
|
|
61
|
+
}
|
|
57
62
|
}
|
|
58
63
|
];
|
|
59
64
|
while (!vFile.data.frontmatter.title && titleReaders.length) {
|
package/dist/preset.js
CHANGED
|
@@ -36,6 +36,7 @@ var preset_default = (api) => {
|
|
|
36
36
|
require.resolve("./features/compile"),
|
|
37
37
|
require.resolve("./features/routes"),
|
|
38
38
|
require.resolve("./features/meta"),
|
|
39
|
+
require.resolve("./features/tabs"),
|
|
39
40
|
require.resolve("./features/theme"),
|
|
40
41
|
require.resolve("./features/locales"),
|
|
41
42
|
require.resolve("./features/parser")
|
package/dist/types.d.ts
CHANGED
|
@@ -9,7 +9,10 @@ import type { IApi as IUmiApi } from 'umi';
|
|
|
9
9
|
declare type IUmiConfig = IUmiApi['config'];
|
|
10
10
|
export interface IDumiConfig extends IUmiConfig {
|
|
11
11
|
resolve: {
|
|
12
|
-
docDirs: string
|
|
12
|
+
docDirs: (string | {
|
|
13
|
+
type?: string;
|
|
14
|
+
dir: string;
|
|
15
|
+
})[];
|
|
13
16
|
entityDirs: {
|
|
14
17
|
type: string;
|
|
15
18
|
dir: string;
|
package/package.json
CHANGED
|
@@ -14,5 +14,6 @@
|
|
|
14
14
|
"api.component.default": "Default",
|
|
15
15
|
"api.component.required": "(required)",
|
|
16
16
|
"api.component.loading": "Properties definition is resolving, wait a moment...",
|
|
17
|
-
"api.component.not.found": "Properties definition not found for {id} component"
|
|
17
|
+
"api.component.not.found": "Properties definition not found for {id} component",
|
|
18
|
+
"content.tabs.default": "Doc"
|
|
18
19
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { useRouteMeta } from 'dumi';
|
|
2
|
+
import { type FC } from 'react';
|
|
3
|
+
import './index.less';
|
|
4
|
+
declare type IContentTabs = ReturnType<typeof useRouteMeta>['tabs'];
|
|
5
|
+
export interface IContentTabsProps {
|
|
6
|
+
tabs: IContentTabs;
|
|
7
|
+
tabKey?: string;
|
|
8
|
+
onChange: (tab?: NonNullable<IContentTabs>[0]) => void;
|
|
9
|
+
}
|
|
10
|
+
declare const ContentTabs: FC<IContentTabsProps>;
|
|
11
|
+
export default ContentTabs;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { useIntl } from 'dumi';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import "./index.less";
|
|
4
|
+
|
|
5
|
+
var ContentTabs = function ContentTabs(_ref) {
|
|
6
|
+
var tabs = _ref.tabs,
|
|
7
|
+
key = _ref.tabKey,
|
|
8
|
+
onChange = _ref.onChange;
|
|
9
|
+
var intl = useIntl(); // TODO: tab.Extra & tab.Action render
|
|
10
|
+
|
|
11
|
+
return Boolean(tabs === null || tabs === void 0 ? void 0 : tabs.length) ? /*#__PURE__*/React.createElement("ul", {
|
|
12
|
+
className: "dumi-default-content-tabs"
|
|
13
|
+
}, /*#__PURE__*/React.createElement("li", {
|
|
14
|
+
onClick: function onClick() {
|
|
15
|
+
return onChange();
|
|
16
|
+
},
|
|
17
|
+
"data-active": !key || undefined
|
|
18
|
+
}, /*#__PURE__*/React.createElement("button", {
|
|
19
|
+
type: "button"
|
|
20
|
+
}, intl.formatMessage({
|
|
21
|
+
id: 'content.tabs.default'
|
|
22
|
+
}))), tabs.map(function (tab) {
|
|
23
|
+
return /*#__PURE__*/React.createElement("li", {
|
|
24
|
+
key: tab.key,
|
|
25
|
+
onClick: function onClick() {
|
|
26
|
+
return onChange(tab);
|
|
27
|
+
},
|
|
28
|
+
"data-active": key === tab.key || undefined
|
|
29
|
+
}, /*#__PURE__*/React.createElement("button", {
|
|
30
|
+
type: "button"
|
|
31
|
+
}, tab.frontmatter.title));
|
|
32
|
+
})) : null;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export default ContentTabs;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
@import (reference) '../../styles/variables.less';
|
|
2
|
+
|
|
3
|
+
.@{prefix}-content-tabs {
|
|
4
|
+
list-style-type: none;
|
|
5
|
+
display: flex;
|
|
6
|
+
align-items: center;
|
|
7
|
+
height: 60px;
|
|
8
|
+
margin: -@s-content-padding -@s-content-padding @s-content-padding -@s-content-padding;
|
|
9
|
+
padding: 0 @s-content-padding;
|
|
10
|
+
border-bottom: 1px solid @c-border-light;
|
|
11
|
+
|
|
12
|
+
[data-no-sidebar] & {
|
|
13
|
+
margin: 0 0 @s-content-padding;
|
|
14
|
+
padding: 0;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
> li {
|
|
18
|
+
height: inherit;
|
|
19
|
+
|
|
20
|
+
> button {
|
|
21
|
+
padding: 0;
|
|
22
|
+
height: inherit;
|
|
23
|
+
color: @c-text-secondary;
|
|
24
|
+
font-size: 17px;
|
|
25
|
+
border: 0;
|
|
26
|
+
background: transparent;
|
|
27
|
+
cursor: pointer;
|
|
28
|
+
transition: all 0.2s;
|
|
29
|
+
|
|
30
|
+
&:hover {
|
|
31
|
+
color: @c-primary;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
&:not(last-child) {
|
|
36
|
+
margin-right: 42px;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
&[data-active] {
|
|
40
|
+
position: relative;
|
|
41
|
+
|
|
42
|
+
> button {
|
|
43
|
+
color: @c-text;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
&::after {
|
|
47
|
+
content: '';
|
|
48
|
+
position: absolute;
|
|
49
|
+
left: 0;
|
|
50
|
+
right: 0;
|
|
51
|
+
bottom: -1px;
|
|
52
|
+
height: 1px;
|
|
53
|
+
background-color: @c-primary;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|