dumi 2.3.0-alpha.7 → 2.3.0-alpha.8

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 (31) hide show
  1. package/dist/client/theme-api/evalCode.d.ts +2 -0
  2. package/dist/client/theme-api/evalCode.js +17 -0
  3. package/dist/client/theme-api/index.d.ts +2 -0
  4. package/dist/client/theme-api/index.js +2 -0
  5. package/dist/client/theme-api/live/LiveProvider.d.ts +16 -0
  6. package/dist/client/theme-api/live/LiveProvider.js +74 -0
  7. package/dist/client/theme-api/live/index.d.ts +3 -0
  8. package/dist/client/theme-api/live/index.js +3 -0
  9. package/dist/client/theme-api/live/useDemoScopes.d.ts +2 -0
  10. package/dist/client/theme-api/live/useDemoScopes.js +15 -0
  11. package/dist/client/theme-api/types.d.ts +4 -0
  12. package/dist/features/compile/index.js +6 -0
  13. package/dist/features/exports.js +2 -1
  14. package/dist/features/live.d.ts +3 -0
  15. package/dist/features/live.js +74 -0
  16. package/dist/loaders/markdown/index.d.ts +7 -1
  17. package/dist/loaders/markdown/index.js +95 -0
  18. package/dist/preset.js +2 -1
  19. package/dist/templates/live/demo-scopes.ts.tpl +22 -0
  20. package/dist/templates/live/disabled.ts.tpl +1 -0
  21. package/package.json +6 -1
  22. package/theme-default/builtins/Previewer/index.js +37 -5
  23. package/theme-default/slots/LiveDemo/index.d.ts +3 -0
  24. package/theme-default/slots/LiveDemo/index.js +8 -0
  25. package/theme-default/slots/LiveEditor/index.d.ts +4 -0
  26. package/theme-default/slots/LiveEditor/index.js +20 -0
  27. package/theme-default/slots/LiveError/index.d.ts +4 -0
  28. package/theme-default/slots/LiveError/index.js +15 -0
  29. package/theme-default/slots/LiveError/index.less +22 -0
  30. package/theme-default/slots/PreviewerActions/index.d.ts +1 -0
  31. package/theme-default/slots/PreviewerActions/index.js +1 -1
@@ -0,0 +1,2 @@
1
+ import type { ComponentType } from 'react';
2
+ export declare const evalCode: (code: string, scope: any) => ComponentType;
@@ -0,0 +1,17 @@
1
+ function _construct(Parent, args, Class) { if (_isNativeReflectConstruct()) { _construct = Reflect.construct.bind(); } else { _construct = function _construct(Parent, args, Class) { var a = [null]; a.push.apply(a, args); var Constructor = Function.bind.apply(Parent, a); var instance = new Constructor(); if (Class) _setPrototypeOf(instance, Class.prototype); return instance; }; } return _construct.apply(null, arguments); }
2
+ function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
3
+ function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
4
+ function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
5
+ function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
6
+ 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); }
7
+ function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
8
+ function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
9
+ 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; }
10
+ export var evalCode = function evalCode(code, scope) {
11
+ var scopeKeys = Object.keys(scope);
12
+ var scopeValues = scopeKeys.map(function (key) {
13
+ return scope[key];
14
+ });
15
+ var importReg = /import.*from.*;/g;
16
+ return _construct(Function, scopeKeys.concat([code.replace(importReg, '').replace('export default', 'return').trim()])).apply(void 0, _toConsumableArray(scopeValues));
17
+ };
@@ -4,6 +4,8 @@ export { DumiDemo } from './DumiDemo';
4
4
  export { DumiDemoGrid } from './DumiDemoGrid';
5
5
  export { DumiPage } from './DumiPage';
6
6
  export { useDemoData, useSiteData } from './context';
7
+ export { evalCode } from './evalCode';
8
+ export { LiveContext, LiveProvider, isLiveEnabled } from './live';
7
9
  export { openCodeSandbox } from './openCodeSandbox';
8
10
  export { openStackBlitz } from './openStackBlitz';
9
11
  export type { IPreviewerProps } from './types';
@@ -4,6 +4,8 @@ export { DumiDemo } from "./DumiDemo";
4
4
  export { DumiDemoGrid } from "./DumiDemoGrid";
5
5
  export { DumiPage } from "./DumiPage";
6
6
  export { useDemoData, useSiteData } from "./context";
7
+ export { evalCode } from "./evalCode";
8
+ export { LiveContext, LiveProvider, isLiveEnabled } from "./live";
7
9
  export { openCodeSandbox } from "./openCodeSandbox";
8
10
  export { openStackBlitz } from "./openStackBlitz";
9
11
  export { useAtomAssets } from "./useAtomAssets";
@@ -0,0 +1,16 @@
1
+ import React, { FC } from 'react';
2
+ type LiveContextProps = {
3
+ enabled: boolean;
4
+ code: string;
5
+ onCodeChange: (code: string) => void;
6
+ demo: React.ReactNode;
7
+ error: string;
8
+ };
9
+ export declare const LiveContext: React.Context<LiveContextProps>;
10
+ export type LiveProviderProps = {
11
+ initialCode: string;
12
+ demoId: string;
13
+ children: React.ReactElement;
14
+ };
15
+ export declare const LiveProvider: FC<LiveProviderProps>;
16
+ export default LiveProvider;
@@ -0,0 +1,74 @@
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(arr, i) { var _i = null == arr ? null : "undefined" != typeof Symbol && arr[Symbol.iterator] || arr["@@iterator"]; if (null != _i) { var _s, _e, _x, _r, _arr = [], _n = !0, _d = !1; try { if (_x = (_i = _i.call(arr)).next, 0 === i) { if (Object(_i) !== _i) return; _n = !1; } else for (; !(_n = (_s = _x.call(_i)).done) && (_arr.push(_s.value), _arr.length !== i); _n = !0); } catch (err) { _d = !0, _e = err; } finally { try { if (!_n && null != _i.return && (_r = _i.return(), Object(_r) !== _r)) return; } finally { if (_d) throw _e; } } return _arr; } }
6
+ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
7
+ import { evalCode } from 'dumi';
8
+ import React, { useMemo, useState } from 'react';
9
+ import ReactDOM from 'react-dom/server';
10
+ import { transform } from 'sucrase';
11
+ import { useDemoScopes } from "./useDemoScopes";
12
+ export var LiveContext = /*#__PURE__*/React.createContext({
13
+ enabled: false,
14
+ code: '',
15
+ onCodeChange: function onCodeChange() {},
16
+ demo: null,
17
+ error: ''
18
+ });
19
+ var transformCode = function transformCode(code, scopes) {
20
+ if (!scopes) {
21
+ return /*#__PURE__*/React.createElement(React.Fragment, null);
22
+ }
23
+ var Comp = evalCode(transform(code, {
24
+ transforms: ['typescript', 'jsx']
25
+ }).code, scopes);
26
+ return /*#__PURE__*/React.createElement(Comp, null);
27
+ };
28
+ export var LiveProvider = function LiveProvider(_ref) {
29
+ var initialCode = _ref.initialCode,
30
+ demoId = _ref.demoId,
31
+ children = _ref.children;
32
+ var scopes = useDemoScopes(demoId);
33
+ var _useState = useState(initialCode),
34
+ _useState2 = _slicedToArray(_useState, 2),
35
+ code = _useState2[0],
36
+ setCode = _useState2[1];
37
+ var _useState3 = useState(function () {
38
+ return transformCode(code, scopes);
39
+ }),
40
+ _useState4 = _slicedToArray(_useState3, 2),
41
+ demo = _useState4[0],
42
+ setDemo = _useState4[1];
43
+ var _useState5 = useState(''),
44
+ _useState6 = _slicedToArray(_useState5, 2),
45
+ error = _useState6[0],
46
+ setError = _useState6[1];
47
+ var onCodeChange = function onCodeChange(newCode) {
48
+ setCode(newCode);
49
+ try {
50
+ var liveDemo = transformCode(newCode, scopes);
51
+ ReactDOM.renderToString(liveDemo);
52
+ setDemo(liveDemo);
53
+ setError('');
54
+ } catch (e) {
55
+ setError(e.message);
56
+ }
57
+ };
58
+ var contextValue = useMemo(function () {
59
+ return {
60
+ error: error,
61
+ enabled: scopes !== null,
62
+ demo: demo,
63
+ code: code,
64
+ onCodeChange: onCodeChange
65
+ };
66
+ }, [code, scopes, demo, error]);
67
+ if (!scopes) {
68
+ return children;
69
+ }
70
+ return /*#__PURE__*/React.createElement(LiveContext.Provider, {
71
+ value: contextValue
72
+ }, children);
73
+ };
74
+ export default LiveProvider;
@@ -0,0 +1,3 @@
1
+ import LiveProvider, { LiveContext } from './LiveProvider';
2
+ import { isLiveEnabled } from './useDemoScopes';
3
+ export { LiveProvider, LiveContext, isLiveEnabled };
@@ -0,0 +1,3 @@
1
+ import LiveProvider, { LiveContext } from "./LiveProvider";
2
+ import { isLiveEnabled } from "./useDemoScopes";
3
+ export { LiveProvider, LiveContext, isLiveEnabled };
@@ -0,0 +1,2 @@
1
+ export declare const useDemoScopes: (id: string) => any;
2
+ export declare const isLiveEnabled: () => boolean;
@@ -0,0 +1,15 @@
1
+ import { getDemoScopesById } from 'dumi';
2
+ import use from "../context/use";
3
+ var cache = new Map();
4
+ export var useDemoScopes = function useDemoScopes(id) {
5
+ if (!getDemoScopesById) {
6
+ return null;
7
+ }
8
+ if (!cache.has(id)) {
9
+ cache.set(id, getDemoScopesById(id));
10
+ }
11
+ return use(cache.get(id));
12
+ };
13
+ export var isLiveEnabled = function isLiveEnabled() {
14
+ return !!getDemoScopesById;
15
+ };
@@ -41,6 +41,10 @@ export interface IPreviewerProps {
41
41
  * background color for demo content
42
42
  */
43
43
  background?: string;
44
+ /**
45
+ * enable live demo
46
+ */
47
+ live?: boolean;
44
48
  /**
45
49
  * asset metadata of current demo
46
50
  */
@@ -80,6 +80,12 @@ var compile_default = (api) => {
80
80
  }).end().end().oneOf("md-text").resourceQuery(/text$/).use("md-text-loader").loader(loaderPath).options({
81
81
  ...loaderBaseOpts,
82
82
  mode: "text"
83
+ }).end().end().oneOf("md-scope").resourceQuery(/scope$/).use("babel-loader").loader(babelInUmi.loader).options(babelInUmi.options).end().use("md-scope-loader").loader(loaderPath).options({
84
+ ...loaderBaseOpts,
85
+ mode: "scope"
86
+ }).end().end().oneOf("md-scope-index").resourceQuery(/scope-index$/).use("md-scope-index-loader").loader(loaderPath).options({
87
+ ...loaderBaseOpts,
88
+ mode: "scope-index"
83
89
  }).end().end().oneOf("md").use("babel-loader").loader(babelInUmi.loader).options(babelInUmi.options).end().use("md-loader").loader(loaderPath).options({
84
90
  ...loaderBaseOpts,
85
91
  builtins: api.service.themeData.builtins,
@@ -46,7 +46,8 @@ var exports_default = (api) => {
46
46
  content: `export * from '../exports';
47
47
  export * from '${(0, import_plugin_utils.winPath)(require.resolve("../client/theme-api"))}';
48
48
  export { getRouteMetaById } from './meta/route-meta';
49
- export { loadFilesMeta } from './meta/search';`
49
+ export { loadFilesMeta } from './meta/search';
50
+ export { getDemoScopesById } from './live/demo-scopes';`
50
51
  });
51
52
  });
52
53
  };
@@ -0,0 +1,3 @@
1
+ import { IApi } from 'umi';
2
+ declare const _default: (api: IApi) => void;
3
+ export default _default;
@@ -0,0 +1,74 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __export = (target, all) => {
6
+ for (var name in all)
7
+ __defProp(target, name, { get: all[name], enumerable: true });
8
+ };
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
+
19
+ // src/features/live.ts
20
+ var live_exports = {};
21
+ __export(live_exports, {
22
+ default: () => live_default
23
+ });
24
+ module.exports = __toCommonJS(live_exports);
25
+ var import_constants = require("../constants");
26
+ var import_tabs = require("./tabs");
27
+ var import_path = require("path");
28
+ var import_plugin_utils = require("umi/plugin-utils");
29
+ var live_default = (api) => {
30
+ const mdFiles = [];
31
+ api.describe({
32
+ key: "live",
33
+ config: {
34
+ schema(joi) {
35
+ return joi.boolean();
36
+ }
37
+ },
38
+ enableBy: api.EnableBy.register
39
+ });
40
+ api.register({
41
+ key: "modifyRoutes",
42
+ // make sure it is called last
43
+ stage: Infinity,
44
+ fn: (routes) => {
45
+ mdFiles.length = 0;
46
+ Object.values(routes).forEach((route) => {
47
+ if (!route.isLayout && !/\*|:/.test(route.path) && route.file && !(0, import_tabs.isTabRouteFile)(route.file) && route.file.endsWith(".md")) {
48
+ mdFiles.push({
49
+ index: mdFiles.length,
50
+ file: (0, import_plugin_utils.winPath)(route.file),
51
+ id: route.id
52
+ });
53
+ }
54
+ });
55
+ return routes;
56
+ }
57
+ });
58
+ api.onGenerateFiles(async () => {
59
+ api.writeTmpFile({
60
+ noPluginDir: true,
61
+ path: "dumi/live/demo-scopes.ts",
62
+ tplPath: (0, import_plugin_utils.winPath)(
63
+ (0, import_path.join)(
64
+ import_constants.TEMPLATES_DIR,
65
+ "live",
66
+ !!api.config.live ? "demo-scopes.ts.tpl" : "disabled.ts.tpl"
67
+ )
68
+ ),
69
+ context: {
70
+ metaFiles: mdFiles
71
+ }
72
+ });
73
+ });
74
+ };
@@ -21,6 +21,12 @@ interface IMdLoaderFrontmatterModeOptions extends Omit<IMdLoaderDefaultModeOptio
21
21
  interface IMdLoaderTextModeOptions extends Omit<IMdLoaderDefaultModeOptions, 'builtins' | 'mode'> {
22
22
  mode: 'text';
23
23
  }
24
- export type IMdLoaderOptions = IMdLoaderDefaultModeOptions | IMdLoaderDemosModeOptions | IMdLoaderDemoModeOptions | IMdLoaderFrontmatterModeOptions | IMdLoaderTextModeOptions | IMdLoaderDemoIndexModeOptions;
24
+ interface IMdLoaderScopeModeOptions extends Omit<IMdLoaderDefaultModeOptions, 'builtins' | 'mode'> {
25
+ mode: 'scope';
26
+ }
27
+ interface IMdLoaderScopeIndexModeOptions extends Omit<IMdLoaderDefaultModeOptions, 'builtins' | 'mode'> {
28
+ mode: 'scope-index';
29
+ }
30
+ export type IMdLoaderOptions = IMdLoaderDefaultModeOptions | IMdLoaderDemosModeOptions | IMdLoaderDemoModeOptions | IMdLoaderFrontmatterModeOptions | IMdLoaderTextModeOptions | IMdLoaderDemoIndexModeOptions | IMdLoaderScopeModeOptions | IMdLoaderScopeIndexModeOptions;
25
31
  export default function mdLoader(this: any, content: string): void;
26
32
  export {};
@@ -133,6 +133,97 @@ export const texts = {{{texts}}};`,
133
133
  }
134
134
  );
135
135
  }
136
+ function emitScope(opts, ret) {
137
+ const { demos } = ret.meta;
138
+ const importReg = /import(?!(\stype)).*from.*;/g;
139
+ return import_plugin_utils.Mustache.render(
140
+ `{{#renderImport}}
141
+ {{{.}}}
142
+ {{/renderImport}}
143
+
144
+ export const scopes = {
145
+ {{#demos}}
146
+ '{{{id}}}': { {{{renderScope}}} },
147
+ {{/demos}}
148
+ }`,
149
+ {
150
+ demos,
151
+ renderImport: function renderImport() {
152
+ if (!demos)
153
+ return [];
154
+ const imports = {};
155
+ for (const demo of demos) {
156
+ if ("asset" in demo) {
157
+ const { asset } = demo;
158
+ Object.entries(asset.dependencies).forEach(([filename, file]) => {
159
+ if (filename.endsWith(".tsx")) {
160
+ const fileImports = file.value.match(importReg) || [];
161
+ fileImports.forEach((item) => {
162
+ var _a;
163
+ const scope = item.replace(/import(.*)from.*;/, "$1").trim();
164
+ const dep = item.replace(/import.*from(.*);/, "$1").trim();
165
+ const namedReg = /.*\{(.*)}/g;
166
+ const namedScope = namedReg.test(scope) ? scope.replace(namedReg, "$1").split(",").map((item2) => item2.trim()).filter(Boolean) : [];
167
+ const defaultReg = /(?:(?![,{]).)*/;
168
+ const defaultScope = (_a = scope.match(defaultReg)) == null ? void 0 : _a[0].trim();
169
+ imports[dep] ?? (imports[dep] = []);
170
+ if (defaultScope) {
171
+ const defaultImport = `default as ${defaultScope}`;
172
+ if (!imports[dep].includes(defaultImport)) {
173
+ imports[dep].push(defaultImport);
174
+ }
175
+ }
176
+ if (namedScope.length) {
177
+ for (const item2 of namedScope) {
178
+ if (!imports[dep].includes(item2)) {
179
+ imports[dep].push(item2);
180
+ }
181
+ }
182
+ }
183
+ });
184
+ }
185
+ });
186
+ }
187
+ }
188
+ return Object.entries(imports).map(([key, value]) => {
189
+ return value.length ? `import { ${value.join(", ")} } from ${key};` : "";
190
+ }).filter(Boolean);
191
+ },
192
+ renderScope: function renderScope() {
193
+ if (!("asset" in this))
194
+ return "";
195
+ const { asset } = this;
196
+ const demoScopes = [];
197
+ Object.entries(asset.dependencies).forEach(([filename, file]) => {
198
+ if (filename.endsWith(".tsx")) {
199
+ const imports = file.value.match(importReg) || [];
200
+ const scopes = imports.reduce((acc, item) => {
201
+ const scope = item.replace(/import(.*)from.*;/, "$1").trim();
202
+ const scopeList = scope.replace(/[{}]/g, "").trim();
203
+ return [...acc, scopeList];
204
+ }, []);
205
+ demoScopes.push(...scopes);
206
+ }
207
+ });
208
+ return demoScopes.join(", ");
209
+ }
210
+ }
211
+ );
212
+ }
213
+ function emitScopeIndex(opts, ret) {
214
+ const { demos } = ret.meta;
215
+ return import_plugin_utils.Mustache.render(
216
+ `export const scopeIndex = {
217
+ {{#demos}}
218
+ '{{{id}}}': {{{getter}}},
219
+ {{/demos}}
220
+ };`,
221
+ {
222
+ demos,
223
+ getter: `() => import('${(0, import_plugin_utils.winPath)(this.resourcePath)}?type=scope')`
224
+ }
225
+ );
226
+ }
136
227
  function emit(opts, ret) {
137
228
  const { demos, embeds } = ret.meta;
138
229
  embeds.forEach((file) => this.addDependency(file));
@@ -146,6 +237,10 @@ function emit(opts, ret) {
146
237
  return emitFrontmatter.call(this, opts, ret);
147
238
  case "text":
148
239
  return emitText.call(this, opts, ret);
240
+ case "scope":
241
+ return emitScope.call(this, opts, ret);
242
+ case "scope-index":
243
+ return emitScopeIndex.call(this, opts, ret);
149
244
  default:
150
245
  return emitDefault.call(this, opts, ret);
151
246
  }
package/dist/preset.js CHANGED
@@ -52,7 +52,8 @@ var preset_default = (api) => {
52
52
  require.resolve("./features/assets"),
53
53
  require.resolve("./features/exportStatic"),
54
54
  require.resolve("./features/sitemap"),
55
- require.resolve("./features/html2sketch")
55
+ require.resolve("./features/html2sketch"),
56
+ require.resolve("./features/live")
56
57
  ]
57
58
  };
58
59
  };
@@ -0,0 +1,22 @@
1
+ {{#metaFiles}}
2
+ import { scopeIndex as scpi{{{index}}} } from '{{{file}}}?type=scope-index';
3
+ {{/metaFiles}}
4
+
5
+ const scopeIndexes: Record<string, { ids: string[], getter: () => Promise<any> }> = {
6
+ {{#metaFiles}}
7
+ ...scpi{{{index}}},
8
+ {{/metaFiles}}
9
+ };
10
+
11
+ /** Async to load demo by id */
12
+ export const getDemoScopesById = async (id: string) => {
13
+ const getter = scopeIndexes[id];
14
+
15
+ if (!getter) {
16
+ return {};
17
+ }
18
+
19
+ const { scopes }: any = await getter() || {};
20
+
21
+ return scopes?.[id] || {};
22
+ };
@@ -0,0 +1 @@
1
+ export const getDemoScopesById = null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dumi",
3
- "version": "2.3.0-alpha.7",
3
+ "version": "2.3.0-alpha.8",
4
4
  "description": "📖 Documentation Generator of React Component",
5
5
  "keywords": [
6
6
  "generator",
@@ -122,6 +122,7 @@
122
122
  "react-copy-to-clipboard": "^5.1.0",
123
123
  "react-error-boundary": "^4.0.10",
124
124
  "react-intl": "^6.4.4",
125
+ "react-simple-code-editor": "^0.13.1",
125
126
  "rehype-autolink-headings": "^6.1.1",
126
127
  "rehype-remove-comments": "^5.0.0",
127
128
  "rehype-stringify": "^9.0.3",
@@ -132,6 +133,7 @@
132
133
  "remark-rehype": "^10.1.0",
133
134
  "sass": "^1.64.1",
134
135
  "sitemap": "^7.1.1",
136
+ "sucrase": "^3.34.0",
135
137
  "umi": "^4.0.84",
136
138
  "unified": "^10.1.2",
137
139
  "unist-util-visit": "^4.1.2",
@@ -150,8 +152,10 @@
150
152
  "@types/lodash.throttle": "^4.1.7",
151
153
  "@types/node": "^18.17.1",
152
154
  "@types/pluralize": "^0.0.30",
155
+ "@types/prismjs": "^1.26.0",
153
156
  "@types/react": "^18.2.17",
154
157
  "@types/react-copy-to-clipboard": "^5.0.4",
158
+ "@types/react-dom": "^18.2.7",
155
159
  "@umijs/lint": "^4.0.84",
156
160
  "@umijs/plugins": "4.0.32",
157
161
  "dumi-theme-mobile": "workspace:*",
@@ -165,6 +169,7 @@
165
169
  "prettier-plugin-organize-imports": "^3.2.3",
166
170
  "prettier-plugin-packagejson": "^2.4.5",
167
171
  "react": "^18.2.0",
172
+ "react-dom": "^18.2.0",
168
173
  "stylelint": "^15.10.2",
169
174
  "ts-node": "^10.9.1",
170
175
  "typescript": "~5.0.4",
@@ -1,16 +1,27 @@
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(arr, i) { var _i = null == arr ? null : "undefined" != typeof Symbol && arr[Symbol.iterator] || arr["@@iterator"]; if (null != _i) { var _s, _e, _x, _r, _arr = [], _n = !0, _d = !1; try { if (_x = (_i = _i.call(arr)).next, 0 === i) { if (Object(_i) !== _i) return; _n = !1; } else for (; !(_n = (_s = _x.call(_i)).done) && (_arr.push(_s.value), _arr.length !== i); _n = !0); } catch (err) { _d = !0, _e = err; } finally { try { if (!_n && null != _i.return && (_r = _i.return(), Object(_r) !== _r)) return; } finally { if (_d) throw _e; } } return _arr; } }
6
+ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
1
7
  function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
2
8
  function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
3
9
  import classnames from 'classnames';
4
- import { useLocation } from 'dumi';
10
+ import { LiveContext, LiveProvider, isLiveEnabled, useLocation } from 'dumi';
11
+ import LiveDemo from 'dumi/theme/slots/LiveDemo';
12
+ import LiveEditor from 'dumi/theme/slots/LiveEditor';
13
+ import LiveError from 'dumi/theme/slots/LiveError';
5
14
  import PreviewerActions from 'dumi/theme/slots/PreviewerActions';
6
- import React, { useRef } from 'react';
15
+ import React, { useContext, useRef } from 'react';
7
16
  import "./index.less";
8
- var Previewer = function Previewer(props) {
17
+ var InternalPreviewer = function InternalPreviewer(props) {
9
18
  var _demoContainer$curren;
10
19
  var demoContainer = useRef(null);
11
20
  var _useLocation = useLocation(),
12
21
  hash = _useLocation.hash;
13
22
  var link = "#".concat(props.asset.id);
23
+ var _useContext = useContext(LiveContext),
24
+ enabled = _useContext.enabled;
14
25
  return /*#__PURE__*/React.createElement("div", {
15
26
  id: props.asset.id,
16
27
  className: classnames('dumi-default-previewer', props.className),
@@ -31,7 +42,7 @@ var Previewer = function Previewer(props) {
31
42
  height: Number(props.iframe)
32
43
  } : {},
33
44
  src: props.demoUrl
34
- }) : props.children), /*#__PURE__*/React.createElement("div", {
45
+ }) : enabled ? /*#__PURE__*/React.createElement(LiveDemo, null) : props.children), /*#__PURE__*/React.createElement("div", {
35
46
  className: "dumi-default-previewer-meta"
36
47
  }, (props.title || props.debug) && /*#__PURE__*/React.createElement("div", {
37
48
  className: "dumi-default-previewer-desc"
@@ -43,7 +54,28 @@ var Previewer = function Previewer(props) {
43
54
  __html: props.description
44
55
  }
45
56
  })), /*#__PURE__*/React.createElement(PreviewerActions, _extends({}, props, {
46
- demoContainer: props.iframe ? (_demoContainer$curren = demoContainer.current) === null || _demoContainer$curren === void 0 ? void 0 : _demoContainer$curren.firstElementChild : demoContainer.current
57
+ demoContainer: props.iframe ? (_demoContainer$curren = demoContainer.current) === null || _demoContainer$curren === void 0 ? void 0 : _demoContainer$curren.firstElementChild : demoContainer.current,
58
+ sourceCode: enabled ? /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement(LiveEditor, null), /*#__PURE__*/React.createElement(LiveError, null)) : null
47
59
  }))));
48
60
  };
61
+ var Previewer = function Previewer(props) {
62
+ var children = /*#__PURE__*/React.createElement(InternalPreviewer, props);
63
+
64
+ // Only Single File
65
+ if (!isLiveEnabled() || props.live === false || Object.entries(props.asset.dependencies).filter(function (_ref) {
66
+ var _ref2 = _slicedToArray(_ref, 2),
67
+ type = _ref2[1].type;
68
+ return type === 'FILE';
69
+ }).length > 1) {
70
+ return children;
71
+ }
72
+ return /*#__PURE__*/React.createElement(LiveProvider, {
73
+ initialCode: Object.entries(props.asset.dependencies).filter(function (_ref3) {
74
+ var _ref4 = _slicedToArray(_ref3, 2),
75
+ type = _ref4[1].type;
76
+ return type === 'FILE';
77
+ })[0][1].value,
78
+ demoId: props.asset.id
79
+ }, children);
80
+ };
49
81
  export default Previewer;
@@ -0,0 +1,3 @@
1
+ import { FC } from 'react';
2
+ declare const LiveDemo: FC;
3
+ export default LiveDemo;
@@ -0,0 +1,8 @@
1
+ import { LiveContext } from 'dumi';
2
+ import React, { useContext } from 'react';
3
+ var LiveDemo = function LiveDemo() {
4
+ var _useContext = useContext(LiveContext),
5
+ demo = _useContext.demo;
6
+ return /*#__PURE__*/React.createElement(React.Fragment, null, demo);
7
+ };
8
+ export default LiveDemo;
@@ -0,0 +1,4 @@
1
+ import { ComponentProps, FC } from 'react';
2
+ import Editor from 'react-simple-code-editor';
3
+ declare const LiveEditor: FC<ComponentProps<typeof Editor>>;
4
+ export default LiveEditor;
@@ -0,0 +1,20 @@
1
+ function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
2
+ import { LiveContext } from 'dumi';
3
+ import { highlight, languages } from 'prismjs';
4
+ import React, { useContext } from 'react';
5
+ import Editor from 'react-simple-code-editor';
6
+ var LiveEditor = function LiveEditor(props) {
7
+ var _props$highlight, _props$padding;
8
+ var _useContext = useContext(LiveContext),
9
+ code = _useContext.code,
10
+ onCodeChange = _useContext.onCodeChange;
11
+ return /*#__PURE__*/React.createElement(Editor, _extends({}, props, {
12
+ value: code,
13
+ onValueChange: onCodeChange,
14
+ highlight: (_props$highlight = props.highlight) !== null && _props$highlight !== void 0 ? _props$highlight : function (code) {
15
+ return highlight(code, languages.js, 'tsx');
16
+ },
17
+ padding: (_props$padding = props.padding) !== null && _props$padding !== void 0 ? _props$padding : 20
18
+ }));
19
+ };
20
+ export default LiveEditor;
@@ -0,0 +1,4 @@
1
+ import { FC } from 'react';
2
+ import './index.less';
3
+ declare const LiveError: FC;
4
+ export default LiveError;
@@ -0,0 +1,15 @@
1
+ import { ReactComponent as IconError } from '@ant-design/icons-svg/inline-svg/filled/close-circle.svg';
2
+ import { LiveContext } from 'dumi';
3
+ import React, { useContext } from 'react';
4
+ import "./index.less";
5
+ var LiveError = function LiveError() {
6
+ var _useContext = useContext(LiveContext),
7
+ error = _useContext.error;
8
+ if (!error) {
9
+ return null;
10
+ }
11
+ return /*#__PURE__*/React.createElement("pre", {
12
+ className: 'dumi-default-live-error'
13
+ }, /*#__PURE__*/React.createElement(IconError, null), error);
14
+ };
15
+ export default LiveError;
@@ -0,0 +1,22 @@
1
+ @import (reference) '../../styles/variables.less';
2
+
3
+ .dumi-default-live-error {
4
+ @color: darken(desaturate(@c-error, 20%), 1%);
5
+
6
+ white-space: break-spaces;
7
+ background: lighten(@c-error, 51%);
8
+ color: @color;
9
+ padding: 12px 20px;
10
+ margin: 0;
11
+ border-radius: 0 0 4px 4px;
12
+ display: flex;
13
+ align-items: flex-start;
14
+ gap: 8px;
15
+ line-height: 16px;
16
+
17
+ > svg {
18
+ fill: currentcolor;
19
+ width: 16px;
20
+ flex: none;
21
+ }
22
+ }
@@ -9,6 +9,7 @@ export interface IPreviewerActionsProps extends IPreviewerProps {
9
9
  extra?: ReactNode;
10
10
  forceShowCode?: boolean;
11
11
  demoContainer: HTMLDivElement | HTMLIFrameElement;
12
+ sourceCode?: ReactNode;
12
13
  }
13
14
  declare const PreviewerActions: FC<IPreviewerActionsProps>;
14
15
  export default PreviewerActions;
@@ -168,7 +168,7 @@ var PreviewerActions = function PreviewerActions(props) {
168
168
  label: filename
169
169
  };
170
170
  })
171
- })), /*#__PURE__*/React.createElement(SourceCode, {
171
+ })), props.sourceCode || /*#__PURE__*/React.createElement(SourceCode, {
172
172
  lang: lang
173
173
  }, files[activeKey][1].value)));
174
174
  };