dumi 2.3.0-alpha.2 → 2.3.0-alpha.3

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.
@@ -20,4 +20,5 @@ export declare const useSiteSearch: () => {
20
20
  setKeywords: (val: string) => void;
21
21
  result: ISearchResult;
22
22
  loading: boolean;
23
+ loadSearchData: () => void;
23
24
  };
@@ -48,10 +48,10 @@ export var useSiteSearch = function useSiteSearch() {
48
48
  var setter = useCallback(function (val) {
49
49
  setLoading(true);
50
50
  setKeywords(val);
51
- if (val) {
52
- setEnabled(true);
53
- }
54
51
  }, []);
52
+ var loadSearchData = function loadSearchData() {
53
+ return setEnabled(true);
54
+ };
55
55
  var _useSearchData = useSearchData(enabled),
56
56
  _useSearchData2 = _slicedToArray(_useSearchData, 2),
57
57
  filledRoutes = _useSearchData2[0],
@@ -112,6 +112,7 @@ export var useSiteSearch = function useSiteSearch() {
112
112
  keywords: keywords,
113
113
  setKeywords: setter,
114
114
  result: result,
115
- loading: mergedLoading
115
+ loading: mergedLoading,
116
+ loadSearchData: loadSearchData
116
117
  };
117
118
  };
@@ -23,11 +23,11 @@ export default function useSearchData(enabled) {
23
23
  tabs = _useSiteData.tabs;
24
24
  React.useEffect(function () {
25
25
  if (enabled) {
26
- loadFilesMeta().then(function (data) {
26
+ loadFilesMeta(Object.keys(routes)).then(function (data) {
27
27
  setFilesMeta(data);
28
28
  });
29
29
  }
30
- }, [enabled]);
30
+ }, [enabled, routes]);
31
31
  return React.useMemo(function () {
32
32
  if (!filesMeta) {
33
33
  return [null, null];
@@ -67,6 +67,7 @@ export default function useSearchData(enabled) {
67
67
  Object.values(meta.demos).forEach(function (demo) {
68
68
  demo.routeId = id;
69
69
  });
70
+
70
71
  // merge demos
71
72
  Object.assign(acc, meta.demos);
72
73
  return acc;
@@ -33,7 +33,6 @@ __export(compile_exports, {
33
33
  });
34
34
  module.exports = __toCommonJS(compile_exports);
35
35
  var import_react = __toESM(require("../../techStacks/react"));
36
- var import_assets = require("../assets");
37
36
  var compile_default = (api) => {
38
37
  api.describe({ key: "dumi:compile" });
39
38
  api.register({
@@ -68,22 +67,7 @@ var compile_default = (api) => {
68
67
  locales: api.config.locales,
69
68
  pkg: api.pkg
70
69
  };
71
- memo.module.rule("dumi-md").type("javascript/auto").test(/\.md$/).oneOf("md-meta").resourceQuery(/meta$/).use("babel-loader").loader(babelInUmi.loader).options(babelInUmi.options).end().use("md-meta-loader").loader(loaderPath).options({
72
- ...loaderBaseOpts,
73
- mode: "meta",
74
- onResolveDemos(demos) {
75
- const assets = demos.reduce(
76
- (ret, demo) => {
77
- if ("asset" in demo)
78
- ret.push(demo.asset);
79
- return ret;
80
- },
81
- []
82
- );
83
- (0, import_assets.addExampleAssets)(assets);
84
- },
85
- onResolveAtomMeta: import_assets.addAtomMeta
86
- }).end().end().oneOf("md-demo").resourceQuery(/demo$/).use("babel-loader").loader(babelInUmi.loader).options(babelInUmi.options).end().use("md-demo-loader").loader(loaderPath).options({
70
+ memo.module.rule("dumi-md").type("javascript/auto").test(/\.md$/).oneOf("md-demo").resourceQuery(/demo$/).use("babel-loader").loader(babelInUmi.loader).options(babelInUmi.options).end().use("md-demo-loader").loader(loaderPath).options({
87
71
  ...loaderBaseOpts,
88
72
  mode: "demo"
89
73
  }).end().end().oneOf("md-demo-index").resourceQuery(/demo-index$/).use("md-demo-index-loader").loader(loaderPath).options({
@@ -35,6 +35,7 @@ __export(meta_exports, {
35
35
  });
36
36
  module.exports = __toCommonJS(meta_exports);
37
37
  var import_constants = require("../constants");
38
+ var import_utils = require("../utils");
38
39
  var import_path = __toESM(require("path"));
39
40
  var import_plugin_utils = require("umi/plugin-utils");
40
41
  var import_tabs = require("./tabs");
@@ -103,7 +104,18 @@ var meta_default = (api) => {
103
104
  path: "dumi/meta/route-meta.ts",
104
105
  tplPath: (0, import_plugin_utils.winPath)((0, import_path.join)(import_constants.TEMPLATES_DIR, "meta-route.ts.tpl")),
105
106
  context: {
106
- metaFiles: mdFiles
107
+ metaFiles: mdFiles,
108
+ chunkName: function chunkName() {
109
+ var _a;
110
+ if (!("file" in this)) {
111
+ return "";
112
+ }
113
+ return `/* webpackChunkName: "${(0, import_utils.generateMetaChunkName)(
114
+ this.file,
115
+ api.cwd,
116
+ (_a = api.config.locales) == null ? void 0 : _a.map(({ id }) => id)
117
+ )}" */`;
118
+ }
107
119
  }
108
120
  });
109
121
  api.writeTmpFile({
@@ -46,44 +46,6 @@ function getDemoSourceFiles(demos = []) {
46
46
  return ret;
47
47
  }, []);
48
48
  }
49
- function emitMeta(opts, ret) {
50
- const { frontmatter, toc, texts, demos } = ret.meta;
51
- return import_plugin_utils.Mustache.render(
52
- `import React from 'react';
53
-
54
- export const demos = {
55
- {{#demos}}
56
- '{{{id}}}': {
57
- component: {{{component}}},
58
- asset: {{{renderAsset}}}
59
- },
60
- {{/demos}}
61
- };
62
- export const frontmatter = {{{frontmatter}}};
63
- export const toc = {{{toc}}};
64
- export const texts = {{{texts}}};
65
- `,
66
- {
67
- demos,
68
- frontmatter: JSON.stringify(frontmatter),
69
- toc: JSON.stringify(toc),
70
- texts: JSON.stringify(texts),
71
- renderAsset: function renderAsset() {
72
- if (!("asset" in this))
73
- return "null";
74
- let { asset } = this;
75
- const { sources } = this;
76
- Object.keys(this.sources).forEach((file) => {
77
- if (!asset.dependencies[file])
78
- return;
79
- asset = import_plugin_utils.lodash.cloneDeep(asset);
80
- asset.dependencies[file].value = `{{{require('-!${sources[file]}?dumi-raw').default}}}`;
81
- });
82
- return JSON.stringify(asset, null, 2).replace(/"{{{|}}}"/g, "");
83
- }
84
- }
85
- );
86
- }
87
49
  function emitDefault(opts, ret) {
88
50
  const { frontmatter, demos } = ret.meta;
89
51
  const isTabContent = (0, import_tabs.isTabRouteFile)(this.resourcePath);
@@ -95,14 +57,12 @@ function emitDefault(opts, ret) {
95
57
  }
96
58
  return `${Object.values(opts.builtins).map((item) => `import ${item.specifier} from '${item.source}';`).join("\n")}
97
59
  import React from 'react';
98
- ${isTabContent ? `` : `import { DumiPage } from 'dumi';`}
99
- import { texts as ${import_rehypeText.CONTENT_TEXTS_OBJ_NAME} } from '${(0, import_plugin_utils.winPath)(
100
- this.resourcePath
101
- )}?type=text';
60
+ ${isTabContent ? `import { useTabMeta } from 'dumi';` : `import { DumiPage, useRouteMeta } from 'dumi';`}
102
61
 
103
62
  // export named function for fastRefresh
104
63
  // ref: https://github.com/pmmmwh/react-refresh-webpack-plugin/blob/main/docs/TROUBLESHOOTING.md#edits-always-lead-to-full-reload
105
64
  function DumiMarkdownContent() {
65
+ const { texts: ${import_rehypeText.CONTENT_TEXTS_OBJ_NAME} } = use${isTabContent ? "TabMeta" : "RouteMeta"}();
106
66
  return ${isTabContent ? ret.content : `<DumiPage>${ret.content}</DumiPage>`};
107
67
  }
108
68
 
@@ -148,7 +108,11 @@ function emitDemoIndex(opts, ret) {
148
108
  };`,
149
109
  {
150
110
  ids: JSON.stringify(demos == null ? void 0 : demos.map((demo) => demo.id)),
151
- getter: `() => import('${(0, import_plugin_utils.winPath)(this.resourcePath)}?type=demo')`
111
+ getter: `() => import(/* webpackChunkName: "${(0, import_utils.generateMetaChunkName)(
112
+ this.resourcePath,
113
+ opts.cwd,
114
+ opts.locales.map(({ id }) => id)
115
+ )}" */'${(0, import_plugin_utils.winPath)(this.resourcePath)}?type=demo')`
152
116
  }
153
117
  );
154
118
  }
@@ -174,8 +138,6 @@ function emit(opts, ret) {
174
138
  embeds.forEach((file) => this.addDependency(file));
175
139
  getDemoSourceFiles(demos).forEach((file) => this.addDependency(file));
176
140
  switch (opts.mode) {
177
- case "meta":
178
- return emitMeta.call(this, opts, ret);
179
141
  case "demo":
180
142
  return emitDemo.call(this, opts, ret);
181
143
  case "demo-index":
@@ -2,7 +2,7 @@
2
2
  import { demoIndex as dmi{{{index}}} } from '{{{file}}}?type=demo-index';
3
3
  {{/metaFiles}}
4
4
 
5
- const demoIndexes: Record<string, { ids: string[], getter: () => Promise<any> }> = {
5
+ export const demoIndexes: Record<string, { ids: string[], getter: () => Promise<any> }> = {
6
6
  {{#metaFiles}}
7
7
  '{{{id}}}': dmi{{{index}}},
8
8
  {{/metaFiles}}
@@ -31,4 +31,4 @@ export const getDemoById = async (id: string) => {
31
31
  const { demos }: any = await getter() || {};
32
32
 
33
33
  return demos?.[id];
34
- };
34
+ };
@@ -4,7 +4,7 @@ import { filesFrontmatter } from './frontmatter';
4
4
  const files = {
5
5
  {{#metaFiles}}
6
6
  '{{{id}}}': {
7
- textGetter: () => import('{{{file}}}?type=text'),
7
+ textGetter: () => import({{{chunkName}}}'{{{file}}}?type=text'),
8
8
  {{#tabs}}
9
9
  tabs: {{{tabs}}},
10
10
  {{/tabs}}
@@ -1,43 +1,41 @@
1
1
  // This will bundle all the site demos and meta data into one file
2
2
  // which should only async load on search
3
- const filesMetaTabs = {
4
- {{#metaFiles}}
5
- {{#tabs}}
6
- '{{{id}}}': {{{tabs}}},
7
- {{/tabs}}
8
- {{/metaFiles}}
9
- }
3
+ import { getRouteMetaById } from './route-meta';
4
+ import { demoIndexes } from './demos';
5
+ import { filesFrontmatter } from './frontmatter';
10
6
 
11
7
  // generate demos data in runtime, for reuse route.id to reduce bundle size
12
8
  export const demos = {};
13
9
 
14
10
  /** @private Internal usage. Safe to refactor. */
15
- export async function loadFilesMeta() {
11
+ export async function loadFilesMeta(idList: string[]) {
16
12
  const metaMap: Record<string, any> = {};
17
- const idList = [
18
- {{#metaFiles}}
19
- '{{{id}}}',
20
- {{/metaFiles}}
21
- ];
22
13
 
23
14
  {{#metaFiles}}
24
- metaMap['{{{id}}}'] = import('{{{file}}}?type=meta');
15
+ if (idList.includes('{{{id}}}')) {
16
+ metaMap['{{{id}}}'] = async () => {
17
+ const routeMeta = await getRouteMetaById('{{{id}}}');
18
+ const demo = await demoIndexes['{{{id}}}']?.getter() || {};
19
+ return {
20
+ frontmatter: filesFrontmatter['{{{id}}}'] ?? {},
21
+ toc: routeMeta?.toc ?? [],
22
+ texts: routeMeta?.texts ?? [],
23
+ tabs: routeMeta?.tabs ?? [],
24
+ demos: demo?.demos ?? {},
25
+ };
26
+ };
27
+ }
25
28
  {{/metaFiles}}
26
29
 
27
30
  // Wait for all meta data to be loaded
28
- const metaList = await Promise.all(idList.map(id => metaMap[id]));
31
+ const metaList = await Promise.all(Object.entries(metaMap).map(([id, getter]) => getter()));
29
32
 
30
33
  // Merge into filesMeta
31
34
  const filesMeta = {};
32
35
 
33
- idList.forEach((id, index) => {
34
- const meta = metaList[index];
35
-
36
- filesMeta[id] = {
37
- ...meta,
38
- tabs: filesMetaTabs[id],
39
- };
36
+ Object.entries(metaMap).forEach(([id], index) => {
37
+ filesMeta[id] = metaList[index];
40
38
  });
41
39
 
42
40
  return filesMeta;
43
- }
41
+ }
package/dist/utils.d.ts CHANGED
@@ -25,7 +25,7 @@ export declare function parseCodeFrontmatter(raw: string): {
25
25
  * get file-system cache for specific namespace
26
26
  */
27
27
  declare const caches: Record<string, ReturnType<typeof Cache>>;
28
- export declare function getCache(ns: string): typeof caches['0'];
28
+ export declare function getCache(ns: string): (typeof caches)['0'];
29
29
  /**
30
30
  * try to get father config
31
31
  */
@@ -34,4 +34,14 @@ export declare function tryFatherBuildConfigs(cwd: string): Promise<any[]>;
34
34
  * get root dir for monorepo project
35
35
  */
36
36
  export declare function getProjectRoot(cwd: string): string;
37
+ /**
38
+ *
39
+ * transform component into webpack chunkName
40
+ * @export
41
+ * @param {string} component component path
42
+ * @param {string} [cwdPath] current root path
43
+ * @return {*} {string}
44
+ */
45
+ export declare function componentToChunkName(component: string, cwdPath?: string): string;
46
+ export declare function generateMetaChunkName(path: string, cwd: string, locales?: string[]): string;
37
47
  export {};
package/dist/utils.js CHANGED
@@ -29,6 +29,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
29
29
  // src/utils.ts
30
30
  var utils_exports = {};
31
31
  __export(utils_exports, {
32
+ componentToChunkName: () => componentToChunkName,
33
+ generateMetaChunkName: () => generateMetaChunkName,
32
34
  getCache: () => getCache,
33
35
  getFileContentByRegExp: () => getFileContentByRegExp,
34
36
  getFileIdFromFsPath: () => getFileIdFromFsPath,
@@ -126,8 +128,31 @@ function getProjectRoot(cwd) {
126
128
  }
127
129
  return (0, import_plugin_utils.winPath)(cwd);
128
130
  }
131
+ function lastSlash(str) {
132
+ return str[str.length - 1] === "/" ? str : `${str}/`;
133
+ }
134
+ function componentToChunkName(component, cwdPath = "/") {
135
+ const cwd = (0, import_plugin_utils.winPath)(cwdPath);
136
+ return typeof component === "string" ? component.replace(
137
+ new RegExp(
138
+ `^(${// match app cwd first
139
+ import_plugin_utils.lodash.escapeRegExp(lastSlash(cwd))})`
140
+ ),
141
+ ""
142
+ ).replace(/^.(\/|\\)/, "").replace(/(\/|\\)/g, "__").replace(/^src__/, "").replace(/\.\.__/g, "").replace(/^pages__/, "p__") : "";
143
+ }
144
+ function generateMetaChunkName(path2, cwd, locales = []) {
145
+ const chunkName = componentToChunkName(path2, cwd);
146
+ const dir = chunkName.replace(/^(.*?)_.*/, "$1");
147
+ const localeRegExp = new RegExp(`.*(${locales.join("|")}).*`);
148
+ const ifLocale = locales.length && localeRegExp.test(chunkName);
149
+ const locale = ifLocale ? `__${chunkName.replace(localeRegExp, "$1")}` : "";
150
+ return `meta__${dir}${locale}`;
151
+ }
129
152
  // Annotate the CommonJS export names for ESM import in node:
130
153
  0 && (module.exports = {
154
+ componentToChunkName,
155
+ generateMetaChunkName,
131
156
  getCache,
132
157
  getFileContentByRegExp,
133
158
  getFileIdFromFsPath,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dumi",
3
- "version": "2.3.0-alpha.2",
3
+ "version": "2.3.0-alpha.3",
4
4
  "description": "📖 Documentation Generator of React Component",
5
5
  "keywords": [
6
6
  "generator",
@@ -2,5 +2,5 @@ import React from 'react';
2
2
  type NativeInputProps = React.DetailedHTMLProps<React.InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>;
3
3
  export declare const Input: React.ForwardRefExoticComponent<{
4
4
  onChange: (keywords: string) => void;
5
- } & Pick<NativeInputProps, "onFocus" | "onBlur"> & React.RefAttributes<HTMLInputElement>>;
5
+ } & Pick<NativeInputProps, "onFocus" | "onBlur" | "onMouseEnter"> & React.RefAttributes<HTMLInputElement>>;
6
6
  export {};
@@ -19,6 +19,7 @@ export var Input = /*#__PURE__*/forwardRef(function (props, ref) {
19
19
  },
20
20
  onFocus: props.onFocus,
21
21
  onBlur: props.onBlur,
22
+ onMouseEnter: props.onMouseEnter,
22
23
  onKeyDown: function onKeyDown(ev) {
23
24
  if (['ArrowDown', 'ArrowUp'].includes(ev.key)) ev.preventDefault();
24
25
  // esc to blur input
@@ -37,7 +37,8 @@ var SearchBar = function SearchBar() {
37
37
  keywords = _useSiteSearch.keywords,
38
38
  setKeywords = _useSiteSearch.setKeywords,
39
39
  result = _useSiteSearch.result,
40
- loading = _useSiteSearch.loading;
40
+ loading = _useSiteSearch.loading,
41
+ loadSearchData = _useSiteSearch.loadSearchData;
41
42
  var _useState5 = useState(false),
42
43
  _useState6 = _slicedToArray(_useState5, 2),
43
44
  modalVisible = _useState6[0],
@@ -86,7 +87,10 @@ var SearchBar = function SearchBar() {
86
87
  className: "dumi-default-search-bar-svg"
87
88
  }), /*#__PURE__*/React.createElement(Input, {
88
89
  onFocus: function onFocus() {
89
- return setFocusing(true);
90
+ setFocusing(true);
91
+ },
92
+ onMouseEnter: function onMouseEnter() {
93
+ loadSearchData();
90
94
  },
91
95
  onBlur: function onBlur() {
92
96
  // wait for item click