dumi 2.4.48 → 2.4.49-alpha.1
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/areDumiDemoPropsEqual.d.ts +1 -0
- package/dist/client/theme-api/DumiDemo/areDumiDemoPropsEqual.js +4 -0
- package/dist/client/theme-api/DumiDemo/index.js +2 -4
- package/dist/client/theme-api/routeMetaHMR.d.ts +5 -0
- package/dist/client/theme-api/routeMetaHMR.js +23 -0
- package/dist/client/theme-api/useRouteMeta.d.ts +2 -1
- package/dist/client/theme-api/useRouteMeta.js +35 -3
- package/dist/features/compile/index.d.ts +1 -0
- package/dist/features/compile/index.js +7 -2
- package/dist/features/compile/utoopackLoaders.js +12 -0
- package/dist/features/meta.js +2 -0
- package/dist/features/routes.js +18 -6
- package/dist/loaders/markdown/index.d.ts +8 -1
- package/dist/loaders/markdown/index.js +128 -9
- package/dist/loaders/markdown/transformer/index.d.ts +1 -0
- package/dist/loaders/markdown/transformer/rehypeDemo.js +58 -0
- package/dist/templates/meta/index.ts.tpl +36 -1
- package/package.json +7 -7
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function areDumiDemoPropsEqual<T>(prev: T, next: T): boolean;
|
|
@@ -5,6 +5,7 @@ import React, { createElement } from 'react';
|
|
|
5
5
|
import Previewer from 'dumi/theme/builtins/Previewer';
|
|
6
6
|
import { useRenderer } from "../useRenderer";
|
|
7
7
|
import DemoErrorBoundary from "./DemoErrorBoundary";
|
|
8
|
+
import { areDumiDemoPropsEqual } from "./areDumiDemoPropsEqual";
|
|
8
9
|
var InternalDumiDemo = function InternalDumiDemo(props) {
|
|
9
10
|
var _useSiteData = useSiteData(),
|
|
10
11
|
historyType = _useSiteData.historyType;
|
|
@@ -43,10 +44,7 @@ var InternalDumiDemo = function InternalDumiDemo(props) {
|
|
|
43
44
|
"".concat(isHashRoute ? "#" : '').concat(basename).concat(SP_ROUTE_PREFIX, "demos/").concat(props.demo.id).concat(routeQuery)
|
|
44
45
|
}, props.previewerProps), props.previewerProps.iframe ? null : demoNode);
|
|
45
46
|
};
|
|
46
|
-
export var DumiDemo = /*#__PURE__*/React.memo(InternalDumiDemo,
|
|
47
|
-
// compare length for performance
|
|
48
|
-
return JSON.stringify(prev).length === JSON.stringify(next).length;
|
|
49
|
-
});
|
|
47
|
+
export var DumiDemo = /*#__PURE__*/React.memo(InternalDumiDemo, areDumiDemoPropsEqual);
|
|
50
48
|
if (process.env.NODE_ENV !== 'production') {
|
|
51
49
|
InternalDumiDemo.displayName = 'DumiDemo';
|
|
52
50
|
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
type RouteMetaHMRListener = () => void;
|
|
2
|
+
export declare function getRouteMetaHMRRevision(routeId: string): number;
|
|
3
|
+
export declare function subscribeRouteMetaHMR(routeId: string, listener: RouteMetaHMRListener): () => void;
|
|
4
|
+
export declare function notifyRouteMetaHMR(routeId: string): void;
|
|
5
|
+
export {};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
var revisions = new Map();
|
|
2
|
+
var listeners = new Map();
|
|
3
|
+
export function getRouteMetaHMRRevision(routeId) {
|
|
4
|
+
var _revisions$get;
|
|
5
|
+
return (_revisions$get = revisions.get(routeId)) !== null && _revisions$get !== void 0 ? _revisions$get : 0;
|
|
6
|
+
}
|
|
7
|
+
export function subscribeRouteMetaHMR(routeId, listener) {
|
|
8
|
+
var _listeners$get;
|
|
9
|
+
var routeListeners = (_listeners$get = listeners.get(routeId)) !== null && _listeners$get !== void 0 ? _listeners$get : new Set();
|
|
10
|
+
routeListeners.add(listener);
|
|
11
|
+
listeners.set(routeId, routeListeners);
|
|
12
|
+
return function () {
|
|
13
|
+
routeListeners.delete(listener);
|
|
14
|
+
if (!routeListeners.size) listeners.delete(routeId);
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
export function notifyRouteMetaHMR(routeId) {
|
|
18
|
+
var _listeners$get2;
|
|
19
|
+
revisions.set(routeId, getRouteMetaHMRRevision(routeId) + 1);
|
|
20
|
+
(_listeners$get2 = listeners.get(routeId)) === null || _listeners$get2 === void 0 || _listeners$get2.forEach(function (listener) {
|
|
21
|
+
return listener();
|
|
22
|
+
});
|
|
23
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type { IRouteMeta } from './types';
|
|
1
|
+
import type { IRouteMeta, IRoutesById } from './types';
|
|
2
|
+
export declare function getCachedRouteMeta(route: IRoutesById[string], revision: number): IRouteMeta;
|
|
2
3
|
/**
|
|
3
4
|
* hook for get matched route
|
|
4
5
|
* @internal internal use. Do not use in your production code.
|
|
@@ -7,27 +7,35 @@ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
|
|
|
7
7
|
import deepmerge from 'deepmerge';
|
|
8
8
|
import { getRouteMetaById, matchRoutes, useAppData, useLocation, useRouteData } from 'dumi';
|
|
9
9
|
import { useCallback, useState } from 'react';
|
|
10
|
+
import { getRouteMetaHMRRevision, subscribeRouteMetaHMR } from "./routeMetaHMR";
|
|
10
11
|
import { useIsomorphicLayoutEffect } from "./utils";
|
|
11
12
|
var cache = new Map();
|
|
12
13
|
var asyncCache = new Map();
|
|
14
|
+
var cacheRevisions = new Map();
|
|
13
15
|
var EMPTY_META = {
|
|
14
16
|
frontmatter: {},
|
|
15
17
|
toc: [],
|
|
16
18
|
texts: []
|
|
17
19
|
};
|
|
18
20
|
var ASYNC_META_PROPS = ['texts'];
|
|
19
|
-
function getCachedRouteMeta(route) {
|
|
21
|
+
export function getCachedRouteMeta(route, revision) {
|
|
20
22
|
var cacheKey = route.id;
|
|
23
|
+
if (cacheRevisions.get(cacheKey) !== revision) {
|
|
24
|
+
cache.delete(cacheKey);
|
|
25
|
+
asyncCache.delete(cacheKey);
|
|
26
|
+
cacheRevisions.set(cacheKey, revision);
|
|
27
|
+
}
|
|
21
28
|
if (!cache.get(cacheKey)) {
|
|
22
29
|
var _meta$tabs;
|
|
23
30
|
var merge = function merge() {
|
|
24
31
|
var meta = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : EMPTY_META;
|
|
25
32
|
if (route.meta) {
|
|
33
|
+
var _ref2, _ref3;
|
|
26
34
|
Object.keys(route.meta).forEach(function (key) {
|
|
27
35
|
var _ref, _ref$key;
|
|
28
36
|
(_ref$key = (_ref = meta)[key]) !== null && _ref$key !== void 0 ? _ref$key : _ref[key] = route.meta[key];
|
|
29
37
|
});
|
|
30
|
-
meta.frontmatter = deepmerge(meta.frontmatter, route.meta.frontmatter, {
|
|
38
|
+
meta.frontmatter = deepmerge((_ref2 = revision ? route.meta.frontmatter : meta.frontmatter) !== null && _ref2 !== void 0 ? _ref2 : {}, (_ref3 = revision ? meta.frontmatter : route.meta.frontmatter) !== null && _ref3 !== void 0 ? _ref3 : {}, {
|
|
31
39
|
arrayMerge: function arrayMerge(_destinationArray, sourceArray) {
|
|
32
40
|
return sourceArray;
|
|
33
41
|
}
|
|
@@ -45,6 +53,10 @@ function getCachedRouteMeta(route) {
|
|
|
45
53
|
// load async meta then replace cache
|
|
46
54
|
if (routeMetaPromise) {
|
|
47
55
|
asyncCache.set(cacheKey, routeMetaPromise.then(function (full) {
|
|
56
|
+
if (cacheRevisions.get(cacheKey) !== revision) {
|
|
57
|
+
var _cacheRevisions$get;
|
|
58
|
+
return getCachedRouteMeta(route, (_cacheRevisions$get = cacheRevisions.get(cacheKey)) !== null && _cacheRevisions$get !== void 0 ? _cacheRevisions$get : 0);
|
|
59
|
+
}
|
|
48
60
|
return cache.set(cacheKey, merge(full)).get(cacheKey);
|
|
49
61
|
}));
|
|
50
62
|
}
|
|
@@ -111,5 +123,25 @@ export var useMatchedRoute = function useMatchedRoute() {
|
|
|
111
123
|
*/
|
|
112
124
|
export var useRouteMeta = function useRouteMeta() {
|
|
113
125
|
var route = useMatchedRoute();
|
|
114
|
-
|
|
126
|
+
var _useState3 = useState(0),
|
|
127
|
+
_useState4 = _slicedToArray(_useState3, 2),
|
|
128
|
+
forceUpdate = _useState4[1];
|
|
129
|
+
var revision = process.env.NODE_ENV === 'production' ? 0 : getRouteMetaHMRRevision(route.id);
|
|
130
|
+
useIsomorphicLayoutEffect(function () {
|
|
131
|
+
if (process.env.NODE_ENV === 'production') return;
|
|
132
|
+
var unsubscribe = subscribeRouteMetaHMR(route.id, function () {
|
|
133
|
+
forceUpdate(function (count) {
|
|
134
|
+
return count + 1;
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
// Do not miss an update dispatched between render and subscription.
|
|
139
|
+
if (getRouteMetaHMRRevision(route.id) !== revision) {
|
|
140
|
+
forceUpdate(function (count) {
|
|
141
|
+
return count + 1;
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
return unsubscribe;
|
|
145
|
+
}, [route.id, revision]);
|
|
146
|
+
return getCachedRouteMeta(route, revision);
|
|
115
147
|
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { IApi, IDumiTechStack } from '../../types';
|
|
2
2
|
export declare const techStacks: IDumiTechStack[];
|
|
3
|
+
export declare function replaceTechStacks(nextTechStacks: IDumiTechStack[]): void;
|
|
3
4
|
export declare function getUtoopackDemoAssetsFile(api: {
|
|
4
5
|
env: string;
|
|
5
6
|
paths: {
|
|
@@ -31,6 +31,7 @@ var compile_exports = {};
|
|
|
31
31
|
__export(compile_exports, {
|
|
32
32
|
default: () => compile_default,
|
|
33
33
|
getUtoopackDemoAssetsFile: () => getUtoopackDemoAssetsFile,
|
|
34
|
+
replaceTechStacks: () => replaceTechStacks,
|
|
34
35
|
techStacks: () => techStacks
|
|
35
36
|
});
|
|
36
37
|
module.exports = __toCommonJS(compile_exports);
|
|
@@ -44,6 +45,9 @@ var import_makoHooks = require("./makoHooks");
|
|
|
44
45
|
var import_utils2 = require("./utils");
|
|
45
46
|
var import_utoopackLoaders = require("./utoopackLoaders");
|
|
46
47
|
var techStacks = [];
|
|
48
|
+
function replaceTechStacks(nextTechStacks) {
|
|
49
|
+
techStacks.splice(0, techStacks.length, ...nextTechStacks);
|
|
50
|
+
}
|
|
47
51
|
function getUtoopackDemoAssetsFile(api) {
|
|
48
52
|
if (api.env !== "production" || !api.isPluginEnable("exportStatic")) {
|
|
49
53
|
return void 0;
|
|
@@ -113,8 +117,8 @@ var compile_default = (api) => {
|
|
|
113
117
|
// and `before` only insert before the last one
|
|
114
118
|
stage: -Infinity,
|
|
115
119
|
async fn() {
|
|
116
|
-
|
|
117
|
-
|
|
120
|
+
replaceTechStacks(
|
|
121
|
+
await api.applyPlugins({
|
|
118
122
|
key: "registerTechStack",
|
|
119
123
|
type: api.ApplyPluginsType.add
|
|
120
124
|
})
|
|
@@ -256,5 +260,6 @@ var compile_default = (api) => {
|
|
|
256
260
|
// Annotate the CommonJS export names for ESM import in node:
|
|
257
261
|
0 && (module.exports = {
|
|
258
262
|
getUtoopackDemoAssetsFile,
|
|
263
|
+
replaceTechStacks,
|
|
259
264
|
techStacks
|
|
260
265
|
});
|
|
@@ -328,6 +328,18 @@ var getUtoopackRules = (api, config = api.config) => {
|
|
|
328
328
|
],
|
|
329
329
|
as: "*.js"
|
|
330
330
|
},
|
|
331
|
+
// Keep page rendering on a separate module identity from lazy route
|
|
332
|
+
// metadata so React Refresh can accept text changes locally.
|
|
333
|
+
{
|
|
334
|
+
condition: { query: /^\?type=text-render$/ },
|
|
335
|
+
loaders: [
|
|
336
|
+
{
|
|
337
|
+
loader: mdLoaderPath,
|
|
338
|
+
options: { ...serializableBaseOpts, mode: "text-render" }
|
|
339
|
+
}
|
|
340
|
+
],
|
|
341
|
+
as: "*.js"
|
|
342
|
+
},
|
|
331
343
|
// extract demo index metadata from markdown
|
|
332
344
|
{
|
|
333
345
|
condition: { query: /^\?type=demo-index$/ },
|
package/dist/features/meta.js
CHANGED
|
@@ -84,7 +84,9 @@ var meta_default = (api) => {
|
|
|
84
84
|
path: "dumi/meta/index.ts",
|
|
85
85
|
tplPath: require.resolve("../templates/meta/index.ts.tpl"),
|
|
86
86
|
context: {
|
|
87
|
+
enableUtoopackHMR: useUtoopackDemoHMR,
|
|
87
88
|
metaFiles: parsedMetaFiles,
|
|
89
|
+
metaStructureHash: (0, import_utils.getContentHash)(JSON.stringify(parsedMetaFiles)),
|
|
88
90
|
chunkName: function chunkName() {
|
|
89
91
|
var _a;
|
|
90
92
|
if (!("file" in this)) {
|
package/dist/features/routes.js
CHANGED
|
@@ -39,6 +39,7 @@ var import_path = __toESM(require("path"));
|
|
|
39
39
|
var import_pluralize = require("pluralize");
|
|
40
40
|
var import_plugin_utils = require("umi/plugin-utils");
|
|
41
41
|
var CTX_LAYOUT_ID = "dumi-context-layout";
|
|
42
|
+
var ATOM_ROUTE_MARKDOWN_GLOB = "{*,*/index,*/index.*,*/README,*/README.*}.md";
|
|
42
43
|
function normalizeDocDir(docDir) {
|
|
43
44
|
return typeof docDir === "object" ? docDir : { dir: docDir };
|
|
44
45
|
}
|
|
@@ -79,12 +80,23 @@ function flatRoute(route, docLayoutId) {
|
|
|
79
80
|
}
|
|
80
81
|
var routes_default = (api) => {
|
|
81
82
|
api.describe({ key: "dumi:routes" });
|
|
82
|
-
api.addTmpGenerateWatcherPaths(
|
|
83
|
-
|
|
84
|
-
...api.config.resolve.atomDirs
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
83
|
+
api.addTmpGenerateWatcherPaths(() => {
|
|
84
|
+
const watcherPaths = [
|
|
85
|
+
...api.config.resolve.atomDirs.map(
|
|
86
|
+
({ dir }) => import_path.default.join(api.cwd, dir, ATOM_ROUTE_MARKDOWN_GLOB)
|
|
87
|
+
),
|
|
88
|
+
...api.config.resolve.docDirs.map(normalizeDocDir).map(({ dir }) => import_path.default.join(api.cwd, dir, "**/*.md"))
|
|
89
|
+
].map(import_plugin_utils.winPath);
|
|
90
|
+
if (api.env === "development" && api.config.utoopack) {
|
|
91
|
+
return watcherPaths.map((watcherPath) => ({
|
|
92
|
+
path: watcherPath,
|
|
93
|
+
// Existing Markdown files are already watched by the bundler. Only
|
|
94
|
+
// route topology changes need to regenerate Umi's temporary files.
|
|
95
|
+
events: ["add", "unlink"]
|
|
96
|
+
}));
|
|
97
|
+
}
|
|
98
|
+
return watcherPaths;
|
|
99
|
+
});
|
|
88
100
|
api.modifyDefaultConfig((memo) => {
|
|
89
101
|
if (api.userConfig.resolve) {
|
|
90
102
|
const keys = ["docDirs", "atomDirs"];
|
|
@@ -23,11 +23,18 @@ interface IMdLoaderFrontmatterModeOptions extends Omit<IMdLoaderDefaultModeOptio
|
|
|
23
23
|
interface IMdLoaderTextModeOptions extends Omit<IMdLoaderDefaultModeOptions, 'builtins' | 'mode'> {
|
|
24
24
|
mode: 'text';
|
|
25
25
|
}
|
|
26
|
-
|
|
26
|
+
interface IMdLoaderRenderTextModeOptions extends Omit<IMdLoaderDefaultModeOptions, 'builtins' | 'mode'> {
|
|
27
|
+
mode: 'text-render';
|
|
28
|
+
}
|
|
29
|
+
export type IMdLoaderOptions = IMdLoaderDefaultModeOptions | IMdLoaderDemosModeOptions | IMdLoaderDemoModeOptions | IMdLoaderFrontmatterModeOptions | IMdLoaderTextModeOptions | IMdLoaderRenderTextModeOptions | IMdLoaderDemoIndexModeOptions;
|
|
27
30
|
type MdLoaderCache = {
|
|
28
31
|
getSync: (key: string, defaultValue: any) => any;
|
|
29
32
|
};
|
|
30
33
|
export declare function getMdLoaderCacheSync<T>(cache: MdLoaderCache, key: string, defaultValue: T): T;
|
|
31
34
|
export declare function getDemoSourceFiles(demos?: IMdTransformerResult['meta']['demos']): string[];
|
|
35
|
+
export declare function emitDefault(this: any, opts: IMdLoaderDefaultModeOptions, ret: IMdTransformerResult): string;
|
|
36
|
+
export declare function emitFrontmatter(this: any, opts: IMdLoaderFrontmatterModeOptions, ret: IMdTransformerResult): string;
|
|
37
|
+
export declare function emitText(this: any, opts: IMdLoaderTextModeOptions, ret: IMdTransformerResult): string;
|
|
38
|
+
export declare function emitRenderText(this: any, _opts: IMdLoaderRenderTextModeOptions, ret: IMdTransformerResult): string;
|
|
32
39
|
export default function mdLoader(this: any, content: string): void;
|
|
33
40
|
export {};
|
|
@@ -30,6 +30,10 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
var markdown_exports = {};
|
|
31
31
|
__export(markdown_exports, {
|
|
32
32
|
default: () => mdLoader,
|
|
33
|
+
emitDefault: () => emitDefault,
|
|
34
|
+
emitFrontmatter: () => emitFrontmatter,
|
|
35
|
+
emitRenderText: () => emitRenderText,
|
|
36
|
+
emitText: () => emitText,
|
|
33
37
|
getDemoSourceFiles: () => getDemoSourceFiles,
|
|
34
38
|
getMdLoaderCacheSync: () => getMdLoaderCacheSync
|
|
35
39
|
});
|
|
@@ -91,8 +95,10 @@ function getRouteId(opts, fileAbsPath) {
|
|
|
91
95
|
}
|
|
92
96
|
function emitDefault(opts, ret) {
|
|
93
97
|
const { frontmatter, demos } = ret.meta;
|
|
98
|
+
const sharedDemoProps = ret.meta.demoSharedProps ?? [];
|
|
94
99
|
const isTabContent = (0, import_tabs.isTabRouteFile)(this.resourcePath);
|
|
95
100
|
const wrapper = isTabContent ? "" : "DumiPage";
|
|
101
|
+
const textMode = import_utoopackLoaders.UTOOPACK_LOADER_CTX_KEY in opts && process.env.NODE_ENV !== "production" ? "text-render" : "text";
|
|
96
102
|
if (demos && opts.onResolveDemos) {
|
|
97
103
|
opts.onResolveDemos(demos);
|
|
98
104
|
}
|
|
@@ -125,7 +131,8 @@ import React, { Suspense } from 'react';
|
|
|
125
131
|
import { DumiPage } from 'dumi';
|
|
126
132
|
import { texts as ${import_rehypeText.CONTENT_TEXTS_OBJ_NAME} } from '${(0, import_plugin_utils.winPath)(
|
|
127
133
|
this.resourcePath
|
|
128
|
-
)}?type
|
|
134
|
+
)}?type=${textMode}';
|
|
135
|
+
${sharedDemoProps.length ? `const __dumi_demo_shared_props__ = ${JSON.stringify(sharedDemoProps)};` : ""}
|
|
129
136
|
|
|
130
137
|
// export named function for fastRefresh
|
|
131
138
|
// ref: https://github.com/pmmmwh/react-refresh-webpack-plugin/blob/main/docs/TROUBLESHOOTING.md#edits-always-lead-to-full-reload
|
|
@@ -295,24 +302,81 @@ function emitDemoIndex(opts, ret) {
|
|
|
295
302
|
${renderDemoIndex(this.resourcePath, opts, demos)}`;
|
|
296
303
|
}
|
|
297
304
|
function emitFrontmatter(opts, ret) {
|
|
298
|
-
const {
|
|
305
|
+
const { demos } = ret.meta;
|
|
306
|
+
const frontmatter = ret.meta.frontmatter;
|
|
307
|
+
const toc = ret.meta.toc ?? [];
|
|
299
308
|
const resourcePath = (0, import_plugin_utils.winPath)(this.resourcePath);
|
|
300
309
|
const isUtoopack = import_utoopackLoaders.UTOOPACK_LOADER_CTX_KEY in opts;
|
|
310
|
+
const enableUtoopackHMR = isUtoopack && process.env.NODE_ENV !== "production";
|
|
311
|
+
const routeMetaHMRPath = enableUtoopackHMR ? (0, import_plugin_utils.winPath)(require.resolve("../../client/theme-api/routeMetaHMR")) : void 0;
|
|
312
|
+
const routeId = getRouteId(opts, this.resourcePath);
|
|
301
313
|
const demoIndex = renderDemoIndex(this.resourcePath, opts, demos);
|
|
302
314
|
if (isUtoopack) {
|
|
315
|
+
const routeStructureHash = (0, import_utils.getContentHash)(
|
|
316
|
+
JSON.stringify({
|
|
317
|
+
atomId: frontmatter.atomId,
|
|
318
|
+
demoIds: demos == null ? void 0 : demos.map(({ id }) => id),
|
|
319
|
+
filename: frontmatter.filename,
|
|
320
|
+
group: frontmatter.group,
|
|
321
|
+
nav: frontmatter.nav,
|
|
322
|
+
order: frontmatter.order,
|
|
323
|
+
title: frontmatter.title
|
|
324
|
+
})
|
|
325
|
+
);
|
|
303
326
|
const rendered = import_plugin_utils.Mustache.render(
|
|
304
|
-
`
|
|
327
|
+
`{{#enableUtoopackHMR}}
|
|
328
|
+
import { notifyRouteMetaHMR } from {{{routeMetaHMRSpecifier}}};
|
|
329
|
+
{{/enableUtoopackHMR}}
|
|
330
|
+
import '${resourcePath}?watch=parent';
|
|
305
331
|
globalThis.__DUMI_FM__ = globalThis.__DUMI_FM__ || {};
|
|
306
332
|
globalThis.__DUMI_TOC__ = globalThis.__DUMI_TOC__ || {};
|
|
333
|
+
{{#enableUtoopackHMR}}
|
|
334
|
+
const hadPreviousMeta = Object.prototype.hasOwnProperty.call(globalThis.__DUMI_FM__, '${resourcePath}');
|
|
335
|
+
globalThis.__DUMI_META_STRUCTURE_HASH__ = globalThis.__DUMI_META_STRUCTURE_HASH__ || {};
|
|
336
|
+
const previousRouteStructureHash = globalThis.__DUMI_META_STRUCTURE_HASH__['${resourcePath}'];
|
|
337
|
+
const didRouteStructureChange = previousRouteStructureHash !== undefined && previousRouteStructureHash !== '{{{routeStructureHash}}}';
|
|
338
|
+
globalThis.__DUMI_META_STRUCTURE_HASH__['${resourcePath}'] = '{{{routeStructureHash}}}';
|
|
339
|
+
const nextFrontmatter = {{{frontmatter}}};
|
|
340
|
+
const nextToc = {{{toc}}};
|
|
341
|
+
const frontmatter = globalThis.__DUMI_FM__['${resourcePath}'] || {};
|
|
342
|
+
const toc = globalThis.__DUMI_TOC__['${resourcePath}'] || [];
|
|
343
|
+
Object.keys(frontmatter).forEach((key) => delete frontmatter[key]);
|
|
344
|
+
Object.assign(frontmatter, nextFrontmatter);
|
|
345
|
+
toc.splice(0, toc.length, ...nextToc);
|
|
346
|
+
globalThis.__DUMI_FM__['${resourcePath}'] = frontmatter;
|
|
347
|
+
globalThis.__DUMI_TOC__['${resourcePath}'] = toc;
|
|
348
|
+
{{/enableUtoopackHMR}}
|
|
349
|
+
{{^enableUtoopackHMR}}
|
|
307
350
|
globalThis.__DUMI_FM__['${resourcePath}'] = {{{frontmatter}}};
|
|
308
351
|
globalThis.__DUMI_TOC__['${resourcePath}'] = {{{toc}}};
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
{{
|
|
352
|
+
const frontmatter = globalThis.__DUMI_FM__['${resourcePath}'];
|
|
353
|
+
const toc = globalThis.__DUMI_TOC__['${resourcePath}'];
|
|
354
|
+
{{/enableUtoopackHMR}}
|
|
355
|
+
export { frontmatter, toc };
|
|
356
|
+
{{#enableUtoopackHMR}}
|
|
357
|
+
export const routeStructureHash = '{{{routeStructureHash}}}';
|
|
358
|
+
{{/enableUtoopackHMR}}
|
|
359
|
+
{{{demoIndex}}}
|
|
360
|
+
{{#enableUtoopackHMR}}
|
|
361
|
+
if (module.hot) {
|
|
362
|
+
module.hot.accept();
|
|
363
|
+
if (didRouteStructureChange) {
|
|
364
|
+
module.hot.invalidate();
|
|
365
|
+
}{{#routeId}} else if (hadPreviousMeta) {
|
|
366
|
+
notifyRouteMetaHMR({{{routeId}}});
|
|
367
|
+
}{{/routeId}}{{^routeId}} else if (hadPreviousMeta) {
|
|
368
|
+
module.hot.invalidate();
|
|
369
|
+
}{{/routeId}}
|
|
370
|
+
}
|
|
371
|
+
{{/enableUtoopackHMR}}`,
|
|
312
372
|
{
|
|
313
373
|
toc: JSON.stringify(toc),
|
|
314
374
|
frontmatter: JSON.stringify(frontmatter),
|
|
315
|
-
demoIndex
|
|
375
|
+
demoIndex,
|
|
376
|
+
enableUtoopackHMR,
|
|
377
|
+
routeId: routeId ? JSON.stringify(routeId) : void 0,
|
|
378
|
+
routeMetaHMRSpecifier: routeMetaHMRPath ? JSON.stringify(routeMetaHMRPath) : void 0,
|
|
379
|
+
routeStructureHash
|
|
316
380
|
}
|
|
317
381
|
);
|
|
318
382
|
return rendered;
|
|
@@ -330,10 +394,45 @@ export const frontmatter = new Proxy({{{frontmatter}}}, {});
|
|
|
330
394
|
);
|
|
331
395
|
}
|
|
332
396
|
function emitText(opts, ret) {
|
|
333
|
-
const
|
|
397
|
+
const texts = ret.meta.texts ?? [];
|
|
398
|
+
const resourcePath = (0, import_plugin_utils.winPath)(this.resourcePath);
|
|
399
|
+
const enableUtoopackHMR = import_utoopackLoaders.UTOOPACK_LOADER_CTX_KEY in opts && process.env.NODE_ENV !== "production";
|
|
400
|
+
if (enableUtoopackHMR) {
|
|
401
|
+
const routeId = getRouteId(opts, this.resourcePath);
|
|
402
|
+
const routeMetaHMRSpecifier = JSON.stringify(
|
|
403
|
+
(0, import_plugin_utils.winPath)(require.resolve("../../client/theme-api/routeMetaHMR"))
|
|
404
|
+
);
|
|
405
|
+
return import_plugin_utils.Mustache.render(
|
|
406
|
+
`import { notifyRouteMetaHMR } from {{{routeMetaHMRSpecifier}}};
|
|
407
|
+
import {{{watchSpecifier}}};
|
|
408
|
+
globalThis.__DUMI_TEXTS__ = globalThis.__DUMI_TEXTS__ || {};
|
|
409
|
+
const hadPreviousTexts = Object.prototype.hasOwnProperty.call(globalThis.__DUMI_TEXTS__, {{{resourceSpecifier}}});
|
|
410
|
+
const nextTexts = {{{texts}}};
|
|
411
|
+
const texts = globalThis.__DUMI_TEXTS__[{{{resourceSpecifier}}}] || [];
|
|
412
|
+
texts.splice(0, texts.length, ...nextTexts);
|
|
413
|
+
globalThis.__DUMI_TEXTS__[{{{resourceSpecifier}}}] = texts;
|
|
414
|
+
export { texts };
|
|
415
|
+
|
|
416
|
+
if (module.hot) {
|
|
417
|
+
module.hot.accept();
|
|
418
|
+
{{#routeId}}if (hadPreviousTexts) {
|
|
419
|
+
notifyRouteMetaHMR({{{routeId}}});
|
|
420
|
+
}{{/routeId}}{{^routeId}}if (hadPreviousTexts) {
|
|
421
|
+
module.hot.invalidate();
|
|
422
|
+
}{{/routeId}}
|
|
423
|
+
}`,
|
|
424
|
+
{
|
|
425
|
+
resourceSpecifier: JSON.stringify(resourcePath),
|
|
426
|
+
routeId: routeId ? JSON.stringify(routeId) : void 0,
|
|
427
|
+
routeMetaHMRSpecifier,
|
|
428
|
+
texts: JSON.stringify(texts),
|
|
429
|
+
watchSpecifier: JSON.stringify(`${resourcePath}?watch=parent`)
|
|
430
|
+
}
|
|
431
|
+
);
|
|
432
|
+
}
|
|
334
433
|
return import_plugin_utils.Mustache.render(
|
|
335
434
|
`
|
|
336
|
-
import '${
|
|
435
|
+
import '${resourcePath}?watch=parent';
|
|
337
436
|
export const texts = {{{texts}}};
|
|
338
437
|
`,
|
|
339
438
|
{
|
|
@@ -341,6 +440,20 @@ function emitText(opts, ret) {
|
|
|
341
440
|
}
|
|
342
441
|
);
|
|
343
442
|
}
|
|
443
|
+
function emitRenderText(_opts, ret) {
|
|
444
|
+
return import_plugin_utils.Mustache.render(
|
|
445
|
+
`
|
|
446
|
+
import {{{watchSpecifier}}};
|
|
447
|
+
export const texts = {{{texts}}};
|
|
448
|
+
`,
|
|
449
|
+
{
|
|
450
|
+
texts: JSON.stringify(ret.meta.texts ?? []),
|
|
451
|
+
watchSpecifier: JSON.stringify(
|
|
452
|
+
`${(0, import_plugin_utils.winPath)(this.resourcePath)}?watch=parent`
|
|
453
|
+
)
|
|
454
|
+
}
|
|
455
|
+
);
|
|
456
|
+
}
|
|
344
457
|
function emit(opts, ret) {
|
|
345
458
|
const { demos, embeds } = ret.meta;
|
|
346
459
|
embeds.forEach((file) => this.addDependency(file));
|
|
@@ -358,6 +471,8 @@ function emit(opts, ret) {
|
|
|
358
471
|
return emitFrontmatter.call(this, opts, ret);
|
|
359
472
|
case "text":
|
|
360
473
|
return emitText.call(this, opts, ret);
|
|
474
|
+
case "text-render":
|
|
475
|
+
return emitRenderText.call(this, opts, ret);
|
|
361
476
|
default:
|
|
362
477
|
return emitDefault.call(this, opts, ret);
|
|
363
478
|
}
|
|
@@ -444,6 +559,10 @@ function mdLoader(content) {
|
|
|
444
559
|
}
|
|
445
560
|
// Annotate the CommonJS export names for ESM import in node:
|
|
446
561
|
0 && (module.exports = {
|
|
562
|
+
emitDefault,
|
|
563
|
+
emitFrontmatter,
|
|
564
|
+
emitRenderText,
|
|
565
|
+
emitText,
|
|
447
566
|
getDemoSourceFiles,
|
|
448
567
|
getMdLoaderCacheSync
|
|
449
568
|
});
|
|
@@ -49,6 +49,8 @@ var DEMO_NODE_CONTAINER = "$demo-container";
|
|
|
49
49
|
var DEMO_PROP_VALUE_KEY = "$demo-prop-value-key";
|
|
50
50
|
var DEMO_LOADER_PLACEHOLDER = "__DUMI_DEMO_LOADER__";
|
|
51
51
|
var DEMO_LOADER_PLACEHOLDER_VALUE = DEMO_LOADER_PLACEHOLDER;
|
|
52
|
+
var DEMO_SHARED_PROP_PLACEHOLDER_PREFIX = "__DUMI_DEMO_SHARED_PROP_";
|
|
53
|
+
var MIN_SHARED_PREVIEWER_PROP_SIZE = 1024;
|
|
52
54
|
var DUMI_DEMO_TAG = "DumiDemo";
|
|
53
55
|
var DUMI_DEMO_GRID_TAG = "DumiDemoGrid";
|
|
54
56
|
var SKIP_DEMO_PARSE = "pure";
|
|
@@ -66,6 +68,55 @@ var alwaysDemoRE = new RegExp(
|
|
|
66
68
|
({ toString } = await import("hast-util-to-string"));
|
|
67
69
|
({ isElement } = await import("hast-util-is-element"));
|
|
68
70
|
})();
|
|
71
|
+
function getDemoPropsFromNode(node) {
|
|
72
|
+
var _a;
|
|
73
|
+
return [].concat(
|
|
74
|
+
(_a = node.data) == null ? void 0 : _a[DEMO_PROP_VALUE_KEY]
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
function hoistSharedPreviewerProps(nodes) {
|
|
78
|
+
const candidates = /* @__PURE__ */ new Map();
|
|
79
|
+
nodes.forEach((node) => {
|
|
80
|
+
getDemoPropsFromNode(node).forEach(({ previewerProps }) => {
|
|
81
|
+
Object.values(previewerProps).forEach((value) => {
|
|
82
|
+
if (!value || typeof value !== "object")
|
|
83
|
+
return;
|
|
84
|
+
const serialized = JSON.stringify(value);
|
|
85
|
+
if (serialized.length < MIN_SHARED_PREVIEWER_PROP_SIZE)
|
|
86
|
+
return;
|
|
87
|
+
const candidate = candidates.get(serialized);
|
|
88
|
+
if (candidate) {
|
|
89
|
+
candidate.count += 1;
|
|
90
|
+
} else {
|
|
91
|
+
candidates.set(serialized, { count: 1, value });
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
const sharedValues = [];
|
|
97
|
+
const sharedIndexes = /* @__PURE__ */ new Map();
|
|
98
|
+
candidates.forEach(({ count, value }, serialized) => {
|
|
99
|
+
if (count > 1) {
|
|
100
|
+
sharedIndexes.set(serialized, sharedValues.length);
|
|
101
|
+
sharedValues.push(value);
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
if (!sharedValues.length)
|
|
105
|
+
return sharedValues;
|
|
106
|
+
nodes.forEach((node) => {
|
|
107
|
+
getDemoPropsFromNode(node).forEach(({ previewerProps }) => {
|
|
108
|
+
Object.entries(previewerProps).forEach(([key, value]) => {
|
|
109
|
+
if (!value || typeof value !== "object")
|
|
110
|
+
return;
|
|
111
|
+
const index = sharedIndexes.get(JSON.stringify(value));
|
|
112
|
+
if (index !== void 0) {
|
|
113
|
+
previewerProps[key] = `${DEMO_SHARED_PROP_PLACEHOLDER_PREFIX}${index}__`;
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
return sharedValues;
|
|
119
|
+
}
|
|
69
120
|
function getCodeLang(node, opts) {
|
|
70
121
|
var _a, _b, _c, _d;
|
|
71
122
|
let lang = "";
|
|
@@ -380,6 +431,10 @@ function rehypeDemo(opts) {
|
|
|
380
431
|
});
|
|
381
432
|
await Promise.all(deferrers).then((demos) => {
|
|
382
433
|
vFile.data.demos = demos;
|
|
434
|
+
const sharedPreviewerProps = opts.useUtoopackDemoHMR ? hoistSharedPreviewerProps(replaceNodes) : [];
|
|
435
|
+
if (sharedPreviewerProps.length) {
|
|
436
|
+
vFile.data.demoSharedProps = sharedPreviewerProps;
|
|
437
|
+
}
|
|
383
438
|
replaceNodes.forEach((node) => {
|
|
384
439
|
const demoLoader = `() => import('${(0, import_plugin_utils.winPath)(
|
|
385
440
|
opts.fileAbsPath
|
|
@@ -390,6 +445,9 @@ function rehypeDemo(opts) {
|
|
|
390
445
|
new RegExp(`"${DEMO_LOADER_PLACEHOLDER}"`, "g"),
|
|
391
446
|
demoLoader
|
|
392
447
|
);
|
|
448
|
+
sharedPreviewerProps.forEach((_, index2) => {
|
|
449
|
+
value = value.split(`"${DEMO_SHARED_PROP_PLACEHOLDER_PREFIX}${index2}__"`).join(`__dumi_demo_shared_props__[${index2}]`);
|
|
450
|
+
});
|
|
393
451
|
}
|
|
394
452
|
if (node.JSXAttributes[0].type === "JSXAttribute") {
|
|
395
453
|
node.JSXAttributes[0].value = value;
|
|
@@ -3,11 +3,16 @@
|
|
|
3
3
|
import { frontmatter as fm{{{index}}}, toc as t{{{index}}}, demoIndex as dmi{{{index}}} } from '{{{file}}}?type=frontmatter';
|
|
4
4
|
{{/loadDemoIndex}}
|
|
5
5
|
{{^loadDemoIndex}}
|
|
6
|
-
import { frontmatter as fm{{{index}}}, toc as t{{{index}}} } from '{{{file}}}?type=frontmatter';
|
|
6
|
+
import { frontmatter as fm{{{index}}}, toc as t{{{index}}}{{#enableUtoopackHMR}}{{#isMarkdown}}, routeStructureHash as rsh{{{index}}}{{/isMarkdown}}{{/enableUtoopackHMR}} } from '{{{file}}}?type=frontmatter';
|
|
7
7
|
{{/loadDemoIndex}}
|
|
8
8
|
{{/metaFiles}}
|
|
9
9
|
|
|
10
|
+
{{#enableUtoopackHMR}}
|
|
11
|
+
const nextFilesMeta = {
|
|
12
|
+
{{/enableUtoopackHMR}}
|
|
13
|
+
{{^enableUtoopackHMR}}
|
|
10
14
|
export const filesMeta = {
|
|
15
|
+
{{/enableUtoopackHMR}}
|
|
11
16
|
{{#metaFiles}}
|
|
12
17
|
'{{{id}}}': {
|
|
13
18
|
frontmatter: fm{{{index}}},
|
|
@@ -25,4 +30,34 @@ export const filesMeta = {
|
|
|
25
30
|
{{/metaFiles}}
|
|
26
31
|
}
|
|
27
32
|
|
|
33
|
+
{{#enableUtoopackHMR}}
|
|
34
|
+
const dumiGlobal = globalThis as any;
|
|
35
|
+
dumiGlobal.__DUMI_FILES_META__ = dumiGlobal.__DUMI_FILES_META__ || {};
|
|
36
|
+
const filesMeta = dumiGlobal.__DUMI_FILES_META__;
|
|
37
|
+
Object.keys(filesMeta).forEach((id) => delete filesMeta[id]);
|
|
38
|
+
Object.assign(filesMeta, nextFilesMeta);
|
|
39
|
+
export { filesMeta };
|
|
40
|
+
|
|
41
|
+
const nextMetaStructureHash = JSON.stringify([
|
|
42
|
+
'{{{metaStructureHash}}}',
|
|
43
|
+
{{#metaFiles}}
|
|
44
|
+
{{#isMarkdown}}rsh{{{index}}},{{/isMarkdown}}
|
|
45
|
+
{{^isMarkdown}}JSON.stringify([fm{{{index}}}, t{{{index}}}]),{{/isMarkdown}}
|
|
46
|
+
{{/metaFiles}}
|
|
47
|
+
]);
|
|
48
|
+
const previousMetaStructureHash = dumiGlobal.__DUMI_META_INDEX_STRUCTURE_HASH__;
|
|
49
|
+
const didMetaStructureChange = previousMetaStructureHash !== undefined && previousMetaStructureHash !== nextMetaStructureHash;
|
|
50
|
+
dumiGlobal.__DUMI_META_INDEX_STRUCTURE_HASH__ = nextMetaStructureHash;
|
|
51
|
+
|
|
52
|
+
if (module.hot) {
|
|
53
|
+
// Dynamic imports have an async-loader wrapper module. Accept at this
|
|
54
|
+
// stable metadata boundary as well as inside the loaded text module so an
|
|
55
|
+
// already-loaded search chunk cannot invalidate the global runtime graph.
|
|
56
|
+
module.hot.accept();
|
|
57
|
+
if (didMetaStructureChange) {
|
|
58
|
+
module.hot.invalidate();
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
{{/enableUtoopackHMR}}
|
|
62
|
+
|
|
28
63
|
export { tabs as tabsMeta } from './tabs';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dumi",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.49-alpha.1",
|
|
4
4
|
"description": "📖 Documentation Generator of React Component",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"generator",
|
|
@@ -69,9 +69,9 @@
|
|
|
69
69
|
"@swc/core": "1.9.2",
|
|
70
70
|
"@types/hast": "^2.3.5",
|
|
71
71
|
"@types/mdast": "^3.0.12",
|
|
72
|
-
"@umijs/bundler-utils": "^4.
|
|
73
|
-
"@umijs/core": "^4.
|
|
74
|
-
"@umijs/utils": "^4.
|
|
72
|
+
"@umijs/bundler-utils": "^4.7.3",
|
|
73
|
+
"@umijs/core": "^4.7.3",
|
|
74
|
+
"@umijs/utils": "^4.7.3",
|
|
75
75
|
"animated-scroll-to": "^2.3.0",
|
|
76
76
|
"classnames": "2.3.2",
|
|
77
77
|
"codesandbox-import-utils": "^2.2.3",
|
|
@@ -123,7 +123,7 @@
|
|
|
123
123
|
"sass": "^1.64.1",
|
|
124
124
|
"sitemap": "^7.1.1",
|
|
125
125
|
"sucrase": "^3.34.0",
|
|
126
|
-
"umi": "^4.
|
|
126
|
+
"umi": "^4.7.3",
|
|
127
127
|
"unified": "^10.1.2",
|
|
128
128
|
"unist-util-visit": "^4.1.2",
|
|
129
129
|
"unist-util-visit-parents": "^5.1.3",
|
|
@@ -147,8 +147,8 @@
|
|
|
147
147
|
"@types/react-copy-to-clipboard": "^5.0.4",
|
|
148
148
|
"@types/react-dom": "^18.2.7",
|
|
149
149
|
"@typescript/native-preview": "7.0.0-dev.20260623.1",
|
|
150
|
-
"@umijs/lint": "^4.
|
|
151
|
-
"@umijs/plugins": "4.
|
|
150
|
+
"@umijs/lint": "^4.7.3",
|
|
151
|
+
"@umijs/plugins": "4.7.3",
|
|
152
152
|
"eslint": "^8.46.0",
|
|
153
153
|
"esno": "^4.7.0",
|
|
154
154
|
"fast-glob": "^3.3.1",
|