dumi 2.4.46 → 2.4.48-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.
@@ -60,6 +60,13 @@ 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
+ }
63
70
  function getParseCacheKey(opts) {
64
71
  const entryContent = opts.entryPointCode ?? import_fs.default.readFileSync(opts.fileAbsPath, "utf-8");
65
72
  return JSON.stringify({
@@ -75,10 +82,8 @@ function getParseCacheKey(opts) {
75
82
  hasGenerateSources: Boolean(opts.techStack.generateSources)
76
83
  });
77
84
  }
78
- function getParseDeps(ret, entryFile) {
79
- return Object.values(ret.resolveMap).filter(
80
- (file) => import_path.default.isAbsolute(file) && file !== entryFile
81
- );
85
+ function getParseDeps(ret) {
86
+ return Object.values(ret.resolveMap).filter((file) => import_path.default.isAbsolute(file));
82
87
  }
83
88
  function getCachedBlockAsset(cacheKey) {
84
89
  const cached = blockAssetCache.get(cacheKey);
@@ -86,7 +91,7 @@ function getCachedBlockAsset(cacheKey) {
86
91
  return cloneParsedBlockAsset(cached.result);
87
92
  }
88
93
  }
89
- function setCachedBlockAsset(cacheKey, ret, deps) {
94
+ function setCachedBlockAsset(cacheKey, ret, deps, depsKey) {
90
95
  if (blockAssetCache.size >= MAX_BLOCK_ASSET_CACHE_SIZE) {
91
96
  const firstKey = blockAssetCache.keys().next().value;
92
97
  if (firstKey)
@@ -94,7 +99,7 @@ function setCachedBlockAsset(cacheKey, ret, deps) {
94
99
  }
95
100
  blockAssetCache.set(cacheKey, {
96
101
  deps,
97
- depsKey: getDepsKey(deps),
102
+ depsKey,
98
103
  result: cloneParsedBlockAsset(ret)
99
104
  });
100
105
  }
@@ -116,6 +121,7 @@ async function parseBlockAsset(opts) {
116
121
  resolveMap: {},
117
122
  frontmatter: null
118
123
  };
124
+ const loadedFileSnapshot = /* @__PURE__ */ new Map();
119
125
  const deferrer = (0, import_esbuild.build)({
120
126
  // do not emit file
121
127
  write: false,
@@ -165,6 +171,8 @@ async function parseBlockAsset(opts) {
165
171
  let ext = import_path.default.extname(args.path);
166
172
  const techStack = opts.techStack;
167
173
  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"));
168
176
  const filename = `${isEntryPoint ? "index" : (0, import_plugin_utils.winPath)(
169
177
  import_path.default.format({
170
178
  ...import_path.default.parse(args.pluginData.source),
@@ -172,15 +180,12 @@ async function parseBlockAsset(opts) {
172
180
  ext: ""
173
181
  })
174
182
  )}${ext}`;
175
- let entryPointCode = opts.entryPointCode;
183
+ let entryPointCode = isEntryPoint ? opts.entryPointCode : void 0;
176
184
  let contents = void 0;
177
185
  if (techStack.onBlockLoad) {
178
186
  const result2 = techStack.onBlockLoad({
179
187
  filename,
180
- entryPointCode: entryPointCode ?? (entryPointCode = import_fs.default.readFileSync(
181
- args.path,
182
- "utf-8"
183
- )),
188
+ entryPointCode: entryPointCode ?? (entryPointCode = getSourceContent()),
184
189
  ...args
185
190
  });
186
191
  if (result2) {
@@ -191,9 +196,11 @@ async function parseBlockAsset(opts) {
191
196
  let isModule = import_constants.DEFAULT_DEMO_MODULE_EXTENSIONS.includes(ext);
192
197
  let isPlainText = import_constants.DEFAULT_DEMO_PLAIN_TEXT_EXTENSIONS.includes(ext);
193
198
  if (isModule || isPlainText) {
199
+ const assetValue = getSourceContent();
200
+ loadedFileSnapshot.set(args.path, (0, import_utils.getContentHash)(assetValue));
194
201
  asset.dependencies[filename] = {
195
202
  type: "FILE",
196
- value: opts.entryPointCode ?? import_fs.default.readFileSync(args.path, "utf-8")
203
+ value: assetValue
197
204
  };
198
205
  const file = asset.dependencies[filename];
199
206
  if (isEntryPoint) {
@@ -213,7 +220,7 @@ async function parseBlockAsset(opts) {
213
220
  result.frontmatter = frontmatter;
214
221
  }
215
222
  }
216
- if (opts.techStack.runtimeOpts && (!isEntryPoint || !opts.entryPointCode)) {
223
+ if (opts.techStack.runtimeOpts && (!isEntryPoint || opts.entryPointCode === void 0)) {
217
224
  result.resolveMap[filename] = args.path;
218
225
  }
219
226
  return {
@@ -234,10 +241,12 @@ async function parseBlockAsset(opts) {
234
241
  hasError = true;
235
242
  }
236
243
  if (!hasError && cacheKey) {
244
+ const deps = getParseDeps(result);
237
245
  setCachedBlockAsset(
238
246
  cacheKey,
239
247
  result,
240
- getParseDeps(result, opts.fileAbsPath)
248
+ deps,
249
+ getDepsKeyFromSnapshot(deps, loadedFileSnapshot)
241
250
  );
242
251
  }
243
252
  return result;
@@ -1,14 +1,61 @@
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; }
1
7
  import { useDemo, useLiveDemo, useLocation, useParams } from 'dumi';
2
- import { createElement, useEffect } from 'react';
8
+ import { createElement, useEffect, useState } from 'react';
9
+ import { getDemoHMRRevision, subscribeDemoHMR } from "../../theme-api/DumiDemo/hmr";
3
10
  import { useRenderer } from "../../theme-api/useRenderer";
4
11
  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
+ }
5
48
  var DemoRenderPage = function DemoRenderPage() {
6
49
  var params = useParams();
7
50
  var _useLocation = useLocation(),
8
51
  search = _useLocation.search;
9
52
  var id = params.id;
10
- var routeId = new URLSearchParams(search).get('routeId') || undefined;
11
- var demo = useDemo(id, undefined, undefined, routeId);
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);
12
59
  var _useRenderer = useRenderer({
13
60
  id: id,
14
61
  component: demo.component,
@@ -0,0 +1,5 @@
1
+ export type DemoHMRListener = () => void;
2
+ export declare function registerDemoHMRModule(moduleId: string, semanticVersions: Record<string, string>): void;
3
+ export declare function getDemoHMRRevision(moduleId: string, demoId: string): number;
4
+ export declare function subscribeDemoHMR(moduleId: string, demoId: string, listener: DemoHMRListener): () => void;
5
+ export declare function resetDemoHMRStoreForTest(): void;
@@ -0,0 +1,67 @@
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
+ var DEMO_HMR_STORE_KEY = Symbol.for('dumi.demo-hmr-store');
8
+ function getDemoHMRKey(moduleId, demoId) {
9
+ return JSON.stringify([moduleId, demoId]);
10
+ }
11
+ function getDemoHMRStore() {
12
+ var _globalStore$DEMO_HMR;
13
+ var globalStore = globalThis;
14
+ return (_globalStore$DEMO_HMR = globalStore[DEMO_HMR_STORE_KEY]) !== null && _globalStore$DEMO_HMR !== void 0 ? _globalStore$DEMO_HMR : globalStore[DEMO_HMR_STORE_KEY] = {
15
+ moduleVersions: new Map(),
16
+ revisions: new Map(),
17
+ listeners: new Map()
18
+ };
19
+ }
20
+ export function registerDemoHMRModule(moduleId, semanticVersions) {
21
+ var store = getDemoHMRStore();
22
+ var previousVersions = store.moduleVersions.get(moduleId);
23
+ if (!previousVersions) {
24
+ store.moduleVersions.set(moduleId, new Map(Object.entries(semanticVersions)));
25
+ return;
26
+ }
27
+ for (var _i = 0, _Object$entries = Object.entries(semanticVersions); _i < _Object$entries.length; _i++) {
28
+ var _store$revisions$get, _store$listeners$get;
29
+ var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2),
30
+ demoId = _Object$entries$_i[0],
31
+ nextVersion = _Object$entries$_i[1];
32
+ if (!previousVersions.has(demoId)) {
33
+ previousVersions.set(demoId, nextVersion);
34
+ continue;
35
+ }
36
+ if (previousVersions.get(demoId) === nextVersion) continue;
37
+ previousVersions.set(demoId, nextVersion);
38
+ var key = getDemoHMRKey(moduleId, demoId);
39
+ store.revisions.set(key, ((_store$revisions$get = store.revisions.get(key)) !== null && _store$revisions$get !== void 0 ? _store$revisions$get : 0) + 1);
40
+ (_store$listeners$get = store.listeners.get(key)) === null || _store$listeners$get === void 0 || _store$listeners$get.forEach(function (listener) {
41
+ return listener();
42
+ });
43
+ }
44
+ }
45
+ export function getDemoHMRRevision(moduleId, demoId) {
46
+ var _getDemoHMRStore$revi;
47
+ return (_getDemoHMRStore$revi = getDemoHMRStore().revisions.get(getDemoHMRKey(moduleId, demoId))) !== null && _getDemoHMRStore$revi !== void 0 ? _getDemoHMRStore$revi : 0;
48
+ }
49
+ export function subscribeDemoHMR(moduleId, demoId, listener) {
50
+ var store = getDemoHMRStore();
51
+ var key = getDemoHMRKey(moduleId, demoId);
52
+ var listeners = store.listeners.get(key);
53
+ if (!listeners) {
54
+ listeners = new Set();
55
+ store.listeners.set(key, listeners);
56
+ }
57
+ var currentListeners = listeners;
58
+ currentListeners.add(listener);
59
+ return function () {
60
+ currentListeners.delete(listener);
61
+ if (currentListeners.size === 0) store.listeners.delete(key);
62
+ };
63
+ }
64
+ export function resetDemoHMRStoreForTest() {
65
+ var globalStore = globalThis;
66
+ delete globalStore[DEMO_HMR_STORE_KEY];
67
+ }
@@ -5,6 +5,7 @@ type DemoGetter = () => Promise<{
5
5
  }>;
6
6
  export interface IDumiDemoProps {
7
7
  demo: {
8
+ __dumiUtoopackHMR?: string;
8
9
  id: string;
9
10
  inline?: boolean;
10
11
  loader?: DemoGetter;
@@ -12,5 +13,6 @@ export interface IDumiDemoProps {
12
13
  };
13
14
  previewerProps: Omit<IPreviewerProps, 'asset' | 'children'>;
14
15
  }
16
+ export declare function areDumiDemoPropsEqual(prev: IDumiDemoProps, next: IDumiDemoProps): boolean;
15
17
  export declare const DumiDemo: FC<IDumiDemoProps>;
16
18
  export {};
@@ -1,23 +1,75 @@
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); }
1
2
  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; }
2
14
  import { SP_ROUTE_PREFIX } from "../../../constants";
3
15
  import { useAppData, useDemo, useSiteData } from 'dumi';
4
- import React, { createElement } from 'react';
16
+ import React, { createElement, useEffect, useState } from 'react';
5
17
  import Previewer from 'dumi/theme/builtins/Previewer';
6
18
  import { useRenderer } from "../useRenderer";
7
19
  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
57
  var InternalDumiDemo = function InternalDumiDemo(props) {
9
58
  var _useSiteData = useSiteData(),
10
59
  historyType = _useSiteData.historyType;
11
60
  var _useAppData = useAppData(),
12
61
  basename = _useAppData.basename;
13
62
  var _props$demo = props.demo,
63
+ hmrModuleId = _props$demo.__dumiUtoopackHMR,
14
64
  id = _props$demo.id,
15
65
  loader = _props$demo.loader,
16
66
  version = _props$demo.version;
17
- var demo = useDemo(id, loader, version);
67
+ var cacheVersion = useDemoCacheVersion(id, version, hmrModuleId);
68
+ var demo = useDemo(id, loader, cacheVersion);
18
69
  var component = demo.component,
19
70
  asset = demo.asset,
20
71
  renderOpts = demo.renderOpts;
72
+ var previewerProps = hmrModuleId ? _objectSpread(_objectSpread({}, demo.previewerProps), props.previewerProps) : props.previewerProps;
21
73
  var _useRenderer = useRenderer({
22
74
  id: id,
23
75
  renderOpts: demo.renderOpts,
@@ -26,7 +78,7 @@ var InternalDumiDemo = function InternalDumiDemo(props) {
26
78
  canvasRef = _useRenderer.canvasRef;
27
79
 
28
80
  // hide debug demo in production
29
- if (process.env.NODE_ENV === 'production' && props.previewerProps.debug) return null;
81
+ if (process.env.NODE_ENV === 'production' && previewerProps.debug) return null;
30
82
  var demoNode = /*#__PURE__*/React.createElement(DemoErrorBoundary, null, renderOpts !== null && renderOpts !== void 0 && renderOpts.renderer ? /*#__PURE__*/React.createElement("div", {
31
83
  ref: canvasRef
32
84
  }) : ( /*#__PURE__*/createElement(component)));
@@ -34,19 +86,25 @@ var InternalDumiDemo = function InternalDumiDemo(props) {
34
86
  return demoNode;
35
87
  }
36
88
  var isHashRoute = historyType === 'hash';
37
- var routeQuery = demo.routeId ? "?routeId=".concat(encodeURIComponent(demo.routeId)) : '';
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
96
  return /*#__PURE__*/React.createElement(Previewer, _extends({
39
97
  asset: asset,
40
98
  demoUrl:
41
99
  // allow user override demoUrl by frontmatter
42
- props.previewerProps.demoUrl || // when use hash route, browser can automatically handle relative paths starting with #
100
+ previewerProps.demoUrl || // when use hash route, browser can automatically handle relative paths starting with #
43
101
  "".concat(isHashRoute ? "#" : '').concat(basename).concat(SP_ROUTE_PREFIX, "demos/").concat(props.demo.id).concat(routeQuery)
44
- }, props.previewerProps), props.previewerProps.iframe ? null : demoNode);
102
+ }, previewerProps), previewerProps.iframe ? null : demoNode);
45
103
  };
46
- export var DumiDemo = /*#__PURE__*/React.memo(InternalDumiDemo, function (prev, next) {
47
- // compare length for performance
48
- return JSON.stringify(prev).length === JSON.stringify(next).length;
49
- });
104
+ export function areDumiDemoPropsEqual(prev, next) {
105
+ return JSON.stringify(prev) === JSON.stringify(next);
106
+ }
107
+ export var DumiDemo = /*#__PURE__*/React.memo(InternalDumiDemo, areDumiDemoPropsEqual);
50
108
  if (process.env.NODE_ENV !== 'production') {
51
109
  InternalDumiDemo.displayName = 'DumiDemo';
52
110
  }
@@ -238,6 +238,7 @@ export type IDemoData = {
238
238
  component: ReactComponentType | AgnosticComponentType;
239
239
  asset: IPreviewerProps['asset'];
240
240
  routeId: string;
241
+ previewerProps?: Omit<IPreviewerProps, 'asset' | 'children'>;
241
242
  context?: Record<string, unknown>;
242
243
  renderOpts?: {
243
244
  /**
@@ -44,6 +44,9 @@ var import_makoHooks = require("./makoHooks");
44
44
  var import_utils2 = require("./utils");
45
45
  var import_utoopackLoaders = require("./utoopackLoaders");
46
46
  var techStacks = [];
47
+ function replaceTechStacks(nextTechStacks) {
48
+ techStacks.splice(0, techStacks.length, ...nextTechStacks);
49
+ }
47
50
  function getUtoopackDemoAssetsFile(api) {
48
51
  if (api.env !== "production" || !api.isPluginEnable("exportStatic")) {
49
52
  return void 0;
@@ -77,6 +80,24 @@ function normalizeMakoAliases(alias, cwd) {
77
80
  }
78
81
  var compile_default = (api) => {
79
82
  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
+ });
80
101
  api.register({
81
102
  key: "registerTechStack",
82
103
  stage: Infinity,
@@ -92,8 +113,7 @@ var compile_default = (api) => {
92
113
  }
93
114
  memo.babelLoaderCustomize = require.resolve("./babelLoaderCustomize");
94
115
  const cacheDirPath = api.userConfig.cacheDirectoryPath || memo.cacheDirectoryPath;
95
- if (cacheDirPath)
96
- (0, import_utils._setFSCacheDir)(import_path.default.join(cacheDirPath, "dumi"));
116
+ (0, import_utils._setFSCacheDir)((0, import_utils.resolveDumiCacheDir)(api.cwd, cacheDirPath));
97
117
  const SEARCH_WORKER_CODE = import_fs.default.readFileSync(
98
118
  import_path.default.resolve(
99
119
  __dirname,
@@ -113,8 +133,8 @@ var compile_default = (api) => {
113
133
  // and `before` only insert before the last one
114
134
  stage: -Infinity,
115
135
  async fn() {
116
- techStacks.push(
117
- ...await api.applyPlugins({
136
+ replaceTechStacks(
137
+ await api.applyPlugins({
118
138
  key: "registerTechStack",
119
139
  type: api.ApplyPluginsType.add
120
140
  })
@@ -2,6 +2,9 @@ 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;
5
8
  export declare function buildLoaderContextContent(techStacks: IDumiTechStack[], builtins?: Record<string, {
6
9
  specifier: string;
7
10
  source: string;
@@ -30,22 +30,31 @@ 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,
33
34
  UTOOPACK_DEMO_ASSETS_FILENAME: () => UTOOPACK_DEMO_ASSETS_FILENAME,
34
35
  UTOOPACK_LOADER_CTX_KEY: () => UTOOPACK_LOADER_CTX_KEY,
36
+ UTOOPACK_MD_CACHE_NAMESPACE: () => UTOOPACK_MD_CACHE_NAMESPACE,
35
37
  buildLoaderContextContent: () => buildLoaderContextContent,
38
+ getUtoopackMdCacheNamespace: () => getUtoopackMdCacheNamespace,
36
39
  getUtoopackRules: () => getUtoopackRules
37
40
  });
38
41
  module.exports = __toCommonJS(utoopackLoaders_exports);
42
+ var import_utils = require("../../utils");
39
43
  var import_esbuild = __toESM(require("@umijs/bundler-utils/compiled/esbuild"));
40
- var import_utils = require("@umijs/utils");
44
+ var import_utils2 = require("@umijs/utils");
41
45
  var import_path = __toESM(require("path"));
42
- var import_utils2 = require("./utils");
46
+ var import_utils3 = require("./utils");
43
47
  var mdLoaderPath = require.resolve("../../loaders/markdown");
44
48
  var utilsRegisterPath = require.resolve("@umijs/utils");
45
49
  var esbuildImplementorPath = require.resolve("@umijs/bundler-utils/compiled/esbuild");
46
50
  var UTOOPACK_LOADER_CTX_KEY = "__dumiLoaderContextPath";
47
51
  var LOADER_CTX_FILENAME = "dumi-loader-ctx.cjs";
48
52
  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
+ }
49
58
  function toSerializable(value) {
50
59
  return JSON.parse(JSON.stringify(value));
51
60
  }
@@ -89,8 +98,8 @@ function findInModuleExports(target, mod) {
89
98
  return null;
90
99
  }
91
100
  function findInSourceFiles(target, sourceFiles) {
92
- import_utils.register.register({ implementor: import_esbuild.default });
93
- import_utils.register.clearFiles();
101
+ import_utils2.register.register({ implementor: import_esbuild.default });
102
+ import_utils2.register.clearFiles();
94
103
  try {
95
104
  for (const file of sourceFiles) {
96
105
  try {
@@ -106,13 +115,13 @@ function findInSourceFiles(target, sourceFiles) {
106
115
  }
107
116
  return null;
108
117
  } finally {
109
- for (const file of import_utils.register.getFiles()) {
118
+ for (const file of import_utils2.register.getFiles()) {
110
119
  delete require.cache[file];
111
120
  }
112
121
  for (const file of sourceFiles) {
113
122
  delete require.cache[file];
114
123
  }
115
- import_utils.register.restore();
124
+ import_utils2.register.restore();
116
125
  }
117
126
  }
118
127
  function toRequireRef(found) {
@@ -198,13 +207,18 @@ exports.extraRehypePlugins = ${toPluginRefs(
198
207
  `;
199
208
  }
200
209
  var getUtoopackRules = (api, config = api.config) => {
201
- const disableLiveDemo = (0, import_utils2.shouldDisabledLiveDemo)(api);
210
+ const disableLiveDemo = (0, import_utils3.shouldDisabledLiveDemo)(api);
202
211
  const loaderContextPath = import_path.default.join(
203
212
  api.paths.absTmpPath,
204
213
  LOADER_CTX_FILENAME
205
214
  );
206
215
  const cfgResolve = config.resolve ?? {};
207
216
  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,
208
222
  cwd: api.cwd,
209
223
  alias: config.alias || {},
210
224
  resolve: {
@@ -219,6 +233,7 @@ var getUtoopackRules = (api, config = api.config) => {
219
233
  locales: config.locales || [],
220
234
  pkg: api.pkg,
221
235
  disableLiveDemo,
236
+ useUtoopackDemoHMR: api.env === "development",
222
237
  [UTOOPACK_LOADER_CTX_KEY]: loaderContextPath
223
238
  });
224
239
  const externalDemoLoader = {
@@ -366,8 +381,11 @@ var getUtoopackRules = (api, config = api.config) => {
366
381
  // Annotate the CommonJS export names for ESM import in node:
367
382
  0 && (module.exports = {
368
383
  LOADER_CTX_FILENAME,
384
+ MARKDOWN_LOADER_CACHE_EPOCH,
369
385
  UTOOPACK_DEMO_ASSETS_FILENAME,
370
386
  UTOOPACK_LOADER_CTX_KEY,
387
+ UTOOPACK_MD_CACHE_NAMESPACE,
371
388
  buildLoaderContextContent,
389
+ getUtoopackMdCacheNamespace,
372
390
  getUtoopackRules
373
391
  });
@@ -2,6 +2,8 @@ import type { IThemeLoadResult } from '../../features/theme/loader';
2
2
  import { type IMdTransformerOptions, type IMdTransformerResult } from './transformer';
3
3
  interface IMdLoaderDefaultModeOptions extends Omit<IMdTransformerOptions, 'fileAbsPath'> {
4
4
  mode?: 'markdown';
5
+ cacheDirectory?: string;
6
+ cacheEpoch?: string;
5
7
  builtins: IThemeLoadResult['builtins'];
6
8
  onResolveDemos?: (demos: NonNullable<IMdTransformerResult['meta']['demos']>) => void;
7
9
  onResolveAtomMeta?: (atomId: string, meta: IMdTransformerResult['meta']['frontmatter']) => void;
@@ -27,7 +29,39 @@ export type IMdLoaderOptions = IMdLoaderDefaultModeOptions | IMdLoaderDemosModeO
27
29
  type MdLoaderCache = {
28
30
  getSync: (key: string, defaultValue: any) => any;
29
31
  };
32
+ type MdTransformCacheRecord = {
33
+ version: 2;
34
+ deps: string[];
35
+ depsKey: string;
36
+ result: IMdTransformerResult;
37
+ };
38
+ type ReadDependency = (file: string) => Promise<string>;
39
+ export declare function getMdTransformCacheKeys({ resourcePath, content, useUtoopackDemoHMR, opts, }: {
40
+ resourcePath: string;
41
+ content: string;
42
+ useUtoopackDemoHMR: boolean;
43
+ opts: IMdLoaderOptions;
44
+ }): {
45
+ depsHintKey: string;
46
+ baseCacheKey: string;
47
+ };
30
48
  export declare function getMdLoaderCacheSync<T>(cache: MdLoaderCache, key: string, defaultValue: T): T;
31
49
  export declare function getDemoSourceFiles(demos?: IMdTransformerResult['meta']['demos']): string[];
50
+ export declare function addDemoFileDependency(loaderContext: {
51
+ addDependency: (file: string) => void;
52
+ addMissingDependency?: (file: string) => void;
53
+ }, opts: IMdLoaderOptions, file: string): void;
54
+ export declare function emitDemo(this: any, opts: IMdLoaderDemoModeOptions, ret: IMdTransformerResult): string;
55
+ export declare function getDepsCacheKey(deps?: string[], readDependency?: ReadDependency): Promise<string>;
56
+ export declare function getMdLoaderCacheResult(cache: MdLoaderCache, key: string, readDependency?: ReadDependency): Promise<IMdTransformerResult | undefined>;
57
+ export declare function createStableTransform({ initialDeps, createValue, getDeps, readDependency, onDepsDiscovered, maxAttempts, }: {
58
+ initialDeps?: string[];
59
+ createValue: () => Promise<IMdTransformerResult>;
60
+ getDeps: (result: IMdTransformerResult) => string[];
61
+ readDependency?: ReadDependency;
62
+ onDepsDiscovered?: (deps: string[]) => void;
63
+ maxAttempts?: number;
64
+ }): Promise<MdTransformCacheRecord>;
65
+ export declare function createDependencyReader(loaderContext: any, useUtoopack: boolean, mode?: IMdLoaderOptions['mode']): ReadDependency;
32
66
  export default function mdLoader(this: any, content: string): void;
33
67
  export {};