dumi 2.4.48-alpha.0 → 2.4.49-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 (32) hide show
  1. package/dist/assetParsers/block.js +14 -23
  2. package/dist/client/pages/Demo/index.js +3 -50
  3. package/dist/client/theme-api/DumiDemo/areDumiDemoPropsEqual.d.ts +1 -0
  4. package/dist/client/theme-api/DumiDemo/areDumiDemoPropsEqual.js +4 -0
  5. package/dist/client/theme-api/DumiDemo/index.d.ts +0 -2
  6. package/dist/client/theme-api/DumiDemo/index.js +7 -67
  7. package/dist/client/theme-api/routeMetaHMR.d.ts +5 -0
  8. package/dist/client/theme-api/routeMetaHMR.js +23 -0
  9. package/dist/client/theme-api/types.d.ts +0 -1
  10. package/dist/client/theme-api/useRouteMeta.d.ts +2 -1
  11. package/dist/client/theme-api/useRouteMeta.js +35 -3
  12. package/dist/features/compile/index.d.ts +1 -0
  13. package/dist/features/compile/index.js +4 -19
  14. package/dist/features/compile/utoopackLoaders.d.ts +0 -3
  15. package/dist/features/compile/utoopackLoaders.js +19 -25
  16. package/dist/features/meta.js +2 -0
  17. package/dist/features/routes.js +18 -6
  18. package/dist/loaders/markdown/index.d.ts +8 -35
  19. package/dist/loaders/markdown/index.js +178 -332
  20. package/dist/loaders/markdown/transformer/index.d.ts +0 -4
  21. package/dist/loaders/markdown/transformer/rehypeDemo.js +82 -129
  22. package/dist/techStacks/react.js +1 -2
  23. package/dist/templates/meta/index.ts.tpl +36 -1
  24. package/dist/types.d.ts +0 -6
  25. package/dist/utils.d.ts +1 -2
  26. package/dist/utils.js +2 -8
  27. package/package.json +7 -9
  28. package/theme-default/slots/SourceCodeEditor/index.js +0 -3
  29. package/dist/client/theme-api/DumiDemo/hmr.d.ts +0 -5
  30. package/dist/client/theme-api/DumiDemo/hmr.js +0 -67
  31. package/dist/loaders/markdown/sharedCache.d.ts +0 -11
  32. package/dist/loaders/markdown/sharedCache.js +0 -131
@@ -60,13 +60,6 @@ function getDepsKey(deps) {
60
60
  Array.from(new Set(deps)).sort().map((file) => `${(0, import_plugin_utils.winPath)(file)}:${getContentHashFromFile(file)}`)
61
61
  );
62
62
  }
63
- function getDepsKeyFromSnapshot(deps, snapshot) {
64
- return JSON.stringify(
65
- Array.from(new Set(deps)).sort().map(
66
- (file) => `${(0, import_plugin_utils.winPath)(file)}:${snapshot.get(file) ?? getContentHashFromFile(file)}`
67
- )
68
- );
69
- }
70
63
  function getParseCacheKey(opts) {
71
64
  const entryContent = opts.entryPointCode ?? import_fs.default.readFileSync(opts.fileAbsPath, "utf-8");
72
65
  return JSON.stringify({
@@ -82,8 +75,10 @@ function getParseCacheKey(opts) {
82
75
  hasGenerateSources: Boolean(opts.techStack.generateSources)
83
76
  });
84
77
  }
85
- function getParseDeps(ret) {
86
- return Object.values(ret.resolveMap).filter((file) => import_path.default.isAbsolute(file));
78
+ function getParseDeps(ret, entryFile) {
79
+ return Object.values(ret.resolveMap).filter(
80
+ (file) => import_path.default.isAbsolute(file) && file !== entryFile
81
+ );
87
82
  }
88
83
  function getCachedBlockAsset(cacheKey) {
89
84
  const cached = blockAssetCache.get(cacheKey);
@@ -91,7 +86,7 @@ function getCachedBlockAsset(cacheKey) {
91
86
  return cloneParsedBlockAsset(cached.result);
92
87
  }
93
88
  }
94
- function setCachedBlockAsset(cacheKey, ret, deps, depsKey) {
89
+ function setCachedBlockAsset(cacheKey, ret, deps) {
95
90
  if (blockAssetCache.size >= MAX_BLOCK_ASSET_CACHE_SIZE) {
96
91
  const firstKey = blockAssetCache.keys().next().value;
97
92
  if (firstKey)
@@ -99,7 +94,7 @@ function setCachedBlockAsset(cacheKey, ret, deps, depsKey) {
99
94
  }
100
95
  blockAssetCache.set(cacheKey, {
101
96
  deps,
102
- depsKey,
97
+ depsKey: getDepsKey(deps),
103
98
  result: cloneParsedBlockAsset(ret)
104
99
  });
105
100
  }
@@ -121,7 +116,6 @@ async function parseBlockAsset(opts) {
121
116
  resolveMap: {},
122
117
  frontmatter: null
123
118
  };
124
- const loadedFileSnapshot = /* @__PURE__ */ new Map();
125
119
  const deferrer = (0, import_esbuild.build)({
126
120
  // do not emit file
127
121
  write: false,
@@ -171,8 +165,6 @@ async function parseBlockAsset(opts) {
171
165
  let ext = import_path.default.extname(args.path);
172
166
  const techStack = opts.techStack;
173
167
  const isEntryPoint = args.pluginData.kind === "entry-point";
174
- let sourceContent;
175
- const getSourceContent = () => sourceContent ?? (sourceContent = isEntryPoint && opts.entryPointCode !== void 0 ? opts.entryPointCode : import_fs.default.readFileSync(args.path, "utf-8"));
176
168
  const filename = `${isEntryPoint ? "index" : (0, import_plugin_utils.winPath)(
177
169
  import_path.default.format({
178
170
  ...import_path.default.parse(args.pluginData.source),
@@ -180,12 +172,15 @@ async function parseBlockAsset(opts) {
180
172
  ext: ""
181
173
  })
182
174
  )}${ext}`;
183
- let entryPointCode = isEntryPoint ? opts.entryPointCode : void 0;
175
+ let entryPointCode = opts.entryPointCode;
184
176
  let contents = void 0;
185
177
  if (techStack.onBlockLoad) {
186
178
  const result2 = techStack.onBlockLoad({
187
179
  filename,
188
- entryPointCode: entryPointCode ?? (entryPointCode = getSourceContent()),
180
+ entryPointCode: entryPointCode ?? (entryPointCode = import_fs.default.readFileSync(
181
+ args.path,
182
+ "utf-8"
183
+ )),
189
184
  ...args
190
185
  });
191
186
  if (result2) {
@@ -196,11 +191,9 @@ async function parseBlockAsset(opts) {
196
191
  let isModule = import_constants.DEFAULT_DEMO_MODULE_EXTENSIONS.includes(ext);
197
192
  let isPlainText = import_constants.DEFAULT_DEMO_PLAIN_TEXT_EXTENSIONS.includes(ext);
198
193
  if (isModule || isPlainText) {
199
- const assetValue = getSourceContent();
200
- loadedFileSnapshot.set(args.path, (0, import_utils.getContentHash)(assetValue));
201
194
  asset.dependencies[filename] = {
202
195
  type: "FILE",
203
- value: assetValue
196
+ value: opts.entryPointCode ?? import_fs.default.readFileSync(args.path, "utf-8")
204
197
  };
205
198
  const file = asset.dependencies[filename];
206
199
  if (isEntryPoint) {
@@ -220,7 +213,7 @@ async function parseBlockAsset(opts) {
220
213
  result.frontmatter = frontmatter;
221
214
  }
222
215
  }
223
- if (opts.techStack.runtimeOpts && (!isEntryPoint || opts.entryPointCode === void 0)) {
216
+ if (opts.techStack.runtimeOpts && (!isEntryPoint || !opts.entryPointCode)) {
224
217
  result.resolveMap[filename] = args.path;
225
218
  }
226
219
  return {
@@ -241,12 +234,10 @@ async function parseBlockAsset(opts) {
241
234
  hasError = true;
242
235
  }
243
236
  if (!hasError && cacheKey) {
244
- const deps = getParseDeps(result);
245
237
  setCachedBlockAsset(
246
238
  cacheKey,
247
239
  result,
248
- deps,
249
- getDepsKeyFromSnapshot(deps, loadedFileSnapshot)
240
+ getParseDeps(result, opts.fileAbsPath)
250
241
  );
251
242
  }
252
243
  return result;
@@ -1,61 +1,14 @@
1
- function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
2
- 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."); }
3
- 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); }
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
- function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
6
- function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
7
1
  import { useDemo, useLiveDemo, useLocation, useParams } from 'dumi';
8
- import { createElement, useEffect, useState } from 'react';
9
- import { getDemoHMRRevision, subscribeDemoHMR } from "../../theme-api/DumiDemo/hmr";
2
+ import { createElement, useEffect } from 'react';
10
3
  import { useRenderer } from "../../theme-api/useRenderer";
11
4
  import "./index.less";
12
- function useDemoHMRRevision(moduleId, id) {
13
- var hmr = process.env.NODE_ENV === 'production' ? undefined : moduleId;
14
- var revision = hmr ? getDemoHMRRevision(hmr, id) : 0;
15
- var _useState = useState(function () {
16
- return {
17
- id: id,
18
- moduleId: hmr,
19
- revision: revision
20
- };
21
- }),
22
- _useState2 = _slicedToArray(_useState, 2),
23
- setHMRState = _useState2[1];
24
- useEffect(function () {
25
- if (!hmr) return;
26
- var observedRevision = revision;
27
- var syncRevision = function syncRevision() {
28
- var nextRevision = getDemoHMRRevision(hmr, id);
29
- if (nextRevision === observedRevision) return;
30
- observedRevision = nextRevision;
31
- setHMRState(function (current) {
32
- if (current.id === id && current.moduleId === hmr && current.revision === nextRevision) return current;
33
- return {
34
- id: id,
35
- moduleId: hmr,
36
- revision: nextRevision
37
- };
38
- });
39
- };
40
- var unsubscribe = subscribeDemoHMR(hmr, id, syncRevision);
41
-
42
- // Re-read after subscribing so a change between render and effect is not lost.
43
- syncRevision();
44
- return unsubscribe;
45
- }, [hmr, id, revision]);
46
- return revision;
47
- }
48
5
  var DemoRenderPage = function DemoRenderPage() {
49
6
  var params = useParams();
50
7
  var _useLocation = useLocation(),
51
8
  search = _useLocation.search;
52
9
  var id = params.id;
53
- var routeParams = new URLSearchParams(search);
54
- var routeId = routeParams.get('routeId') || undefined;
55
- var hmrModuleId = routeParams.get('dumi-hmr') || undefined;
56
- var hmrRevision = useDemoHMRRevision(hmrModuleId, id);
57
- var cacheVersion = hmrRevision ? "dumi-hmr:".concat(hmrRevision, ":route=").concat(routeId !== null && routeId !== void 0 ? routeId : '') : undefined;
58
- var demo = useDemo(id, undefined, cacheVersion, routeId);
10
+ var routeId = new URLSearchParams(search).get('routeId') || undefined;
11
+ var demo = useDemo(id, undefined, undefined, routeId);
59
12
  var _useRenderer = useRenderer({
60
13
  id: id,
61
14
  component: demo.component,
@@ -0,0 +1 @@
1
+ export declare function areDumiDemoPropsEqual<T>(prev: T, next: T): boolean;
@@ -0,0 +1,4 @@
1
+ export function areDumiDemoPropsEqual(prev, next) {
2
+ // Ignore loader function identity while still detecting serializable demo updates.
3
+ return JSON.stringify(prev) === JSON.stringify(next);
4
+ }
@@ -5,7 +5,6 @@ type DemoGetter = () => Promise<{
5
5
  }>;
6
6
  export interface IDumiDemoProps {
7
7
  demo: {
8
- __dumiUtoopackHMR?: string;
9
8
  id: string;
10
9
  inline?: boolean;
11
10
  loader?: DemoGetter;
@@ -13,6 +12,5 @@ export interface IDumiDemoProps {
13
12
  };
14
13
  previewerProps: Omit<IPreviewerProps, 'asset' | 'children'>;
15
14
  }
16
- export declare function areDumiDemoPropsEqual(prev: IDumiDemoProps, next: IDumiDemoProps): boolean;
17
15
  export declare const DumiDemo: FC<IDumiDemoProps>;
18
16
  export {};
@@ -1,75 +1,24 @@
1
- function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
2
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); }
3
- function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
4
- function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
5
- function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
6
- function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
7
- function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
8
- function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
9
- 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."); }
10
- 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); }
11
- 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; }
12
- function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
13
- function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
14
2
  import { SP_ROUTE_PREFIX } from "../../../constants";
15
3
  import { useAppData, useDemo, useSiteData } from 'dumi';
16
- import React, { createElement, useEffect, useState } from 'react';
4
+ import React, { createElement } from 'react';
17
5
  import Previewer from 'dumi/theme/builtins/Previewer';
18
6
  import { useRenderer } from "../useRenderer";
19
7
  import DemoErrorBoundary from "./DemoErrorBoundary";
20
- import { getDemoHMRRevision, subscribeDemoHMR } from "./hmr";
21
- function useDemoCacheVersion(id, metadataVersion, hmrModuleId) {
22
- var hmr = process.env.NODE_ENV === 'production' ? undefined : hmrModuleId;
23
- var _useState = useState(function () {
24
- return {
25
- id: id,
26
- moduleId: hmr,
27
- revision: hmr ? getDemoHMRRevision(hmr, id) : 0
28
- };
29
- }),
30
- _useState2 = _slicedToArray(_useState, 2),
31
- hmrState = _useState2[0],
32
- setHMRState = _useState2[1];
33
- useEffect(function () {
34
- if (!hmr) return;
35
- var syncRevision = function syncRevision() {
36
- var revision = getDemoHMRRevision(hmr, id);
37
- setHMRState(function (current) {
38
- if (current.id === id && current.moduleId === hmr && current.revision === revision) return current;
39
- return {
40
- id: id,
41
- moduleId: hmr,
42
- revision: revision
43
- };
44
- });
45
- };
46
- var unsubscribe = subscribeDemoHMR(hmr, id, syncRevision);
47
-
48
- // Re-read after subscribing so a change between render and effect is not lost.
49
- syncRevision();
50
- return unsubscribe;
51
- }, [hmr, id]);
52
- if (!hmr) return metadataVersion;
53
- var storedRevision = getDemoHMRRevision(hmr, id);
54
- var revision = hmrState.id === id && hmrState.moduleId === hmr ? Math.max(hmrState.revision, storedRevision) : storedRevision;
55
- return "".concat(metadataVersion, ":").concat(revision);
56
- }
8
+ import { areDumiDemoPropsEqual } from "./areDumiDemoPropsEqual";
57
9
  var InternalDumiDemo = function InternalDumiDemo(props) {
58
10
  var _useSiteData = useSiteData(),
59
11
  historyType = _useSiteData.historyType;
60
12
  var _useAppData = useAppData(),
61
13
  basename = _useAppData.basename;
62
14
  var _props$demo = props.demo,
63
- hmrModuleId = _props$demo.__dumiUtoopackHMR,
64
15
  id = _props$demo.id,
65
16
  loader = _props$demo.loader,
66
17
  version = _props$demo.version;
67
- var cacheVersion = useDemoCacheVersion(id, version, hmrModuleId);
68
- var demo = useDemo(id, loader, cacheVersion);
18
+ var demo = useDemo(id, loader, version);
69
19
  var component = demo.component,
70
20
  asset = demo.asset,
71
21
  renderOpts = demo.renderOpts;
72
- var previewerProps = hmrModuleId ? _objectSpread(_objectSpread({}, demo.previewerProps), props.previewerProps) : props.previewerProps;
73
22
  var _useRenderer = useRenderer({
74
23
  id: id,
75
24
  renderOpts: demo.renderOpts,
@@ -78,7 +27,7 @@ var InternalDumiDemo = function InternalDumiDemo(props) {
78
27
  canvasRef = _useRenderer.canvasRef;
79
28
 
80
29
  // hide debug demo in production
81
- if (process.env.NODE_ENV === 'production' && previewerProps.debug) return null;
30
+ if (process.env.NODE_ENV === 'production' && props.previewerProps.debug) return null;
82
31
  var demoNode = /*#__PURE__*/React.createElement(DemoErrorBoundary, null, renderOpts !== null && renderOpts !== void 0 && renderOpts.renderer ? /*#__PURE__*/React.createElement("div", {
83
32
  ref: canvasRef
84
33
  }) : ( /*#__PURE__*/createElement(component)));
@@ -86,24 +35,15 @@ var InternalDumiDemo = function InternalDumiDemo(props) {
86
35
  return demoNode;
87
36
  }
88
37
  var isHashRoute = historyType === 'hash';
89
- var routeParams = new URLSearchParams();
90
- if (hmrModuleId) routeParams.set('dumi-hmr', hmrModuleId);
91
- // Keep routeId last for compatibility with custom previewers that append
92
- // their own query string to demoUrl instead of merging URLSearchParams.
93
- if (demo.routeId) routeParams.set('routeId', demo.routeId);
94
- var routeQueryString = routeParams.toString();
95
- var routeQuery = routeQueryString ? "?".concat(routeQueryString) : '';
38
+ var routeQuery = demo.routeId ? "?routeId=".concat(encodeURIComponent(demo.routeId)) : '';
96
39
  return /*#__PURE__*/React.createElement(Previewer, _extends({
97
40
  asset: asset,
98
41
  demoUrl:
99
42
  // allow user override demoUrl by frontmatter
100
- previewerProps.demoUrl || // when use hash route, browser can automatically handle relative paths starting with #
43
+ props.previewerProps.demoUrl || // when use hash route, browser can automatically handle relative paths starting with #
101
44
  "".concat(isHashRoute ? "#" : '').concat(basename).concat(SP_ROUTE_PREFIX, "demos/").concat(props.demo.id).concat(routeQuery)
102
- }, previewerProps), previewerProps.iframe ? null : demoNode);
45
+ }, props.previewerProps), props.previewerProps.iframe ? null : demoNode);
103
46
  };
104
- export function areDumiDemoPropsEqual(prev, next) {
105
- return JSON.stringify(prev) === JSON.stringify(next);
106
- }
107
47
  export var DumiDemo = /*#__PURE__*/React.memo(InternalDumiDemo, areDumiDemoPropsEqual);
108
48
  if (process.env.NODE_ENV !== 'production') {
109
49
  InternalDumiDemo.displayName = 'DumiDemo';
@@ -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
+ }
@@ -238,7 +238,6 @@ export type IDemoData = {
238
238
  component: ReactComponentType | AgnosticComponentType;
239
239
  asset: IPreviewerProps['asset'];
240
240
  routeId: string;
241
- previewerProps?: Omit<IPreviewerProps, 'asset' | 'children'>;
242
241
  context?: Record<string, unknown>;
243
242
  renderOpts?: {
244
243
  /**
@@ -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
- return getCachedRouteMeta(route);
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);
@@ -80,24 +81,6 @@ function normalizeMakoAliases(alias, cwd) {
80
81
  }
81
82
  var compile_default = (api) => {
82
83
  api.describe({ key: "dumi:compile" });
83
- api.register({
84
- key: "onExit",
85
- stage: Infinity,
86
- fn() {
87
- const cacheDirectory = (0, import_utils.resolveDumiCacheDir)(
88
- api.cwd,
89
- api.userConfig.cacheDirectoryPath || api.config.cacheDirectoryPath
90
- );
91
- const sessionCache = (0, import_utils.getCache)(
92
- (0, import_utoopackLoaders.getUtoopackMdCacheNamespace)(import_utoopackLoaders.MARKDOWN_LOADER_CACHE_EPOCH),
93
- cacheDirectory
94
- );
95
- const sessionCachePath = sessionCache.basePath;
96
- if (sessionCachePath) {
97
- import_fs.default.rmSync(sessionCachePath, { force: true, recursive: true });
98
- }
99
- }
100
- });
101
84
  api.register({
102
85
  key: "registerTechStack",
103
86
  stage: Infinity,
@@ -113,7 +96,8 @@ var compile_default = (api) => {
113
96
  }
114
97
  memo.babelLoaderCustomize = require.resolve("./babelLoaderCustomize");
115
98
  const cacheDirPath = api.userConfig.cacheDirectoryPath || memo.cacheDirectoryPath;
116
- (0, import_utils._setFSCacheDir)((0, import_utils.resolveDumiCacheDir)(api.cwd, cacheDirPath));
99
+ if (cacheDirPath)
100
+ (0, import_utils._setFSCacheDir)(import_path.default.join(cacheDirPath, "dumi"));
117
101
  const SEARCH_WORKER_CODE = import_fs.default.readFileSync(
118
102
  import_path.default.resolve(
119
103
  __dirname,
@@ -276,5 +260,6 @@ var compile_default = (api) => {
276
260
  // Annotate the CommonJS export names for ESM import in node:
277
261
  0 && (module.exports = {
278
262
  getUtoopackDemoAssetsFile,
263
+ replaceTechStacks,
279
264
  techStacks
280
265
  });
@@ -2,9 +2,6 @@ import type { IApi, IDumiTechStack } from '../../types';
2
2
  export declare const UTOOPACK_LOADER_CTX_KEY = "__dumiLoaderContextPath";
3
3
  export declare const LOADER_CTX_FILENAME = "dumi-loader-ctx.cjs";
4
4
  export declare const UTOOPACK_DEMO_ASSETS_FILENAME = "dumi-utoopack-demo-assets.jsonl";
5
- export declare const MARKDOWN_LOADER_CACHE_EPOCH: string;
6
- export declare const UTOOPACK_MD_CACHE_NAMESPACE = "md-loader-sessions";
7
- export declare function getUtoopackMdCacheNamespace(epoch: string): string;
8
5
  export declare function buildLoaderContextContent(techStacks: IDumiTechStack[], builtins?: Record<string, {
9
6
  specifier: string;
10
7
  source: string;
@@ -30,31 +30,22 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  var utoopackLoaders_exports = {};
31
31
  __export(utoopackLoaders_exports, {
32
32
  LOADER_CTX_FILENAME: () => LOADER_CTX_FILENAME,
33
- MARKDOWN_LOADER_CACHE_EPOCH: () => MARKDOWN_LOADER_CACHE_EPOCH,
34
33
  UTOOPACK_DEMO_ASSETS_FILENAME: () => UTOOPACK_DEMO_ASSETS_FILENAME,
35
34
  UTOOPACK_LOADER_CTX_KEY: () => UTOOPACK_LOADER_CTX_KEY,
36
- UTOOPACK_MD_CACHE_NAMESPACE: () => UTOOPACK_MD_CACHE_NAMESPACE,
37
35
  buildLoaderContextContent: () => buildLoaderContextContent,
38
- getUtoopackMdCacheNamespace: () => getUtoopackMdCacheNamespace,
39
36
  getUtoopackRules: () => getUtoopackRules
40
37
  });
41
38
  module.exports = __toCommonJS(utoopackLoaders_exports);
42
- var import_utils = require("../../utils");
43
39
  var import_esbuild = __toESM(require("@umijs/bundler-utils/compiled/esbuild"));
44
- var import_utils2 = require("@umijs/utils");
40
+ var import_utils = require("@umijs/utils");
45
41
  var import_path = __toESM(require("path"));
46
- var import_utils3 = require("./utils");
42
+ var import_utils2 = require("./utils");
47
43
  var mdLoaderPath = require.resolve("../../loaders/markdown");
48
44
  var utilsRegisterPath = require.resolve("@umijs/utils");
49
45
  var esbuildImplementorPath = require.resolve("@umijs/bundler-utils/compiled/esbuild");
50
46
  var UTOOPACK_LOADER_CTX_KEY = "__dumiLoaderContextPath";
51
47
  var LOADER_CTX_FILENAME = "dumi-loader-ctx.cjs";
52
48
  var UTOOPACK_DEMO_ASSETS_FILENAME = "dumi-utoopack-demo-assets.jsonl";
53
- var MARKDOWN_LOADER_CACHE_EPOCH = `${process.pid}-${Date.now()}`;
54
- var UTOOPACK_MD_CACHE_NAMESPACE = "md-loader-sessions";
55
- function getUtoopackMdCacheNamespace(epoch) {
56
- return import_path.default.join(UTOOPACK_MD_CACHE_NAMESPACE, epoch);
57
- }
58
49
  function toSerializable(value) {
59
50
  return JSON.parse(JSON.stringify(value));
60
51
  }
@@ -98,8 +89,8 @@ function findInModuleExports(target, mod) {
98
89
  return null;
99
90
  }
100
91
  function findInSourceFiles(target, sourceFiles) {
101
- import_utils2.register.register({ implementor: import_esbuild.default });
102
- import_utils2.register.clearFiles();
92
+ import_utils.register.register({ implementor: import_esbuild.default });
93
+ import_utils.register.clearFiles();
103
94
  try {
104
95
  for (const file of sourceFiles) {
105
96
  try {
@@ -115,13 +106,13 @@ function findInSourceFiles(target, sourceFiles) {
115
106
  }
116
107
  return null;
117
108
  } finally {
118
- for (const file of import_utils2.register.getFiles()) {
109
+ for (const file of import_utils.register.getFiles()) {
119
110
  delete require.cache[file];
120
111
  }
121
112
  for (const file of sourceFiles) {
122
113
  delete require.cache[file];
123
114
  }
124
- import_utils2.register.restore();
115
+ import_utils.register.restore();
125
116
  }
126
117
  }
127
118
  function toRequireRef(found) {
@@ -207,18 +198,13 @@ exports.extraRehypePlugins = ${toPluginRefs(
207
198
  `;
208
199
  }
209
200
  var getUtoopackRules = (api, config = api.config) => {
210
- const disableLiveDemo = (0, import_utils3.shouldDisabledLiveDemo)(api);
201
+ const disableLiveDemo = (0, import_utils2.shouldDisabledLiveDemo)(api);
211
202
  const loaderContextPath = import_path.default.join(
212
203
  api.paths.absTmpPath,
213
204
  LOADER_CTX_FILENAME
214
205
  );
215
206
  const cfgResolve = config.resolve ?? {};
216
207
  const serializableBaseOpts = toSerializable({
217
- cacheDirectory: (0, import_utils.resolveDumiCacheDir)(
218
- api.cwd,
219
- api.userConfig.cacheDirectoryPath || config.cacheDirectoryPath
220
- ),
221
- cacheEpoch: MARKDOWN_LOADER_CACHE_EPOCH,
222
208
  cwd: api.cwd,
223
209
  alias: config.alias || {},
224
210
  resolve: {
@@ -233,7 +219,6 @@ var getUtoopackRules = (api, config = api.config) => {
233
219
  locales: config.locales || [],
234
220
  pkg: api.pkg,
235
221
  disableLiveDemo,
236
- useUtoopackDemoHMR: api.env === "development",
237
222
  [UTOOPACK_LOADER_CTX_KEY]: loaderContextPath
238
223
  });
239
224
  const externalDemoLoader = {
@@ -343,6 +328,18 @@ var getUtoopackRules = (api, config = api.config) => {
343
328
  ],
344
329
  as: "*.js"
345
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
+ },
346
343
  // extract demo index metadata from markdown
347
344
  {
348
345
  condition: { query: /^\?type=demo-index$/ },
@@ -381,11 +378,8 @@ var getUtoopackRules = (api, config = api.config) => {
381
378
  // Annotate the CommonJS export names for ESM import in node:
382
379
  0 && (module.exports = {
383
380
  LOADER_CTX_FILENAME,
384
- MARKDOWN_LOADER_CACHE_EPOCH,
385
381
  UTOOPACK_DEMO_ASSETS_FILENAME,
386
382
  UTOOPACK_LOADER_CTX_KEY,
387
- UTOOPACK_MD_CACHE_NAMESPACE,
388
383
  buildLoaderContextContent,
389
- getUtoopackMdCacheNamespace,
390
384
  getUtoopackRules
391
385
  });
@@ -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)) {