diff --git a/package.json b/package.json index 4c0fd6939..14c02bd39 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dumi", - "version": "2.4.7", + "version": "2.4.8-beta.3", "description": "📖 Documentation Generator of React Component", "keywords": [ "generator", diff --git a/src/client/theme-default/slots/SourceCodeEditor/index.tsx b/src/client/theme-default/slots/SourceCodeEditor/index.tsx index 74737655b..bdebbedb2 100644 --- a/src/client/theme-default/slots/SourceCodeEditor/index.tsx +++ b/src/client/theme-default/slots/SourceCodeEditor/index.tsx @@ -89,7 +89,7 @@ const SourceCodeEditor: FC = (props) => { autoComplete="off" autoCorrect="off" autoSave="off" - spellcheck="false" + spellCheck="false" /> ) } diff --git a/src/features/compile/index.ts b/src/features/compile/index.ts index 68e957ab8..6d74793d6 100644 --- a/src/features/compile/index.ts +++ b/src/features/compile/index.ts @@ -89,9 +89,9 @@ export default (api: IApi) => { const loaderPath = require.resolve('../../loaders/markdown'); // support require mjs packages(eg. element-plus/es) - memo.resolve.byDependency.set('commonjs', { - conditionNames: ['require', 'node', 'import'], - }); + // memo.resolve.byDependency.set('commonjs', { + // conditionNames: ['require', 'node', 'import'], + // }); const loaderBaseOpts: Partial = { techStacks, diff --git a/src/loaders/markdown/index.ts b/src/loaders/markdown/index.ts index c0ea3bc35..3cc1639af 100644 --- a/src/loaders/markdown/index.ts +++ b/src/loaders/markdown/index.ts @@ -56,6 +56,11 @@ export type IMdLoaderOptions = | IMdLoaderTextModeOptions | IMdLoaderDemoIndexModeOptions; +interface IDemoDependency { + key: string; + specifier: string; +} + function getDemoSourceFiles(demos: IMdTransformerResult['meta']['demos'] = []) { return demos.reduce((ret, demo) => { if ('resolveMap' in demo) { @@ -68,6 +73,10 @@ function getDemoSourceFiles(demos: IMdTransformerResult['meta']['demos'] = []) { }, []); } +function isRelativePath(path: string) { + return path.startsWith('./') || path.startsWith('../'); +} + function emitDefault( this: any, opts: IMdLoaderDefaultModeOptions, @@ -132,10 +141,50 @@ function emitDemo( ret: IMdTransformerResult, ) { const { demos } = ret.meta; + const shareDepsMap: Record = {}; + const demoDepsMap: Record> = {}; + + demos?.forEach((demo) => { + if ('resolveMap' in demo && 'asset' in demo) { + const entryFileName = Object.keys(demo.asset.dependencies)[0]; + demoDepsMap[demo.id] ??= {}; + Object.keys(demo.resolveMap).forEach((key, index) => { + const specifier = `${demo.id.replace(/-/g, '_')}_deps_${index}`; + if (key !== entryFileName && !isRelativePath(key)) { + if (shareDepsMap[key]) { + demoDepsMap[demo.id][key] = shareDepsMap[key]; + } else { + demoDepsMap[demo.id][key] = specifier; + shareDepsMap[key] = specifier; + } + } else if (isRelativePath(key)) { + demoDepsMap[demo.id][winPath(demo.resolveMap[key])] = specifier; + } + }); + } + }); + const dedupedDemosDeps = Object.entries(demoDepsMap).reduce< + IDemoDependency[] + >((acc, [, deps]) => { + return acc.concat( + Object.entries(deps) + .map(([key, specifier]) => { + const existingIndex = acc.findIndex((obj) => obj.key === key); + if (existingIndex === -1) { + return { key, specifier }; + } + return undefined; + }) + .filter((item) => item !== undefined), + ); + }, []); return Mustache.render( `import React from 'react'; - import '${winPath(this.getDependencies()[0])}?watch=parent'; +import '${winPath(this.getDependencies()[0])}?watch=parent'; +{{#dedupedDemosDeps}} +import * as {{{specifier}}} from '{{{key}}}'; +{{/dedupedDemosDeps}} export const demos = { {{#demos}} '{{{id}}}': { @@ -150,6 +199,7 @@ export const demos = { };`, { demos, + dedupedDemosDeps, renderAsset: function renderAsset(this: NonNullable[0]) { // do not render asset for inline demo if (!('asset' in this)) return 'null'; @@ -181,23 +231,13 @@ export const demos = { ) { // do not render context for inline demo if (!('resolveMap' in this) || !('asset' in this)) return 'undefined'; - - const entryFileName = Object.keys(this.asset.dependencies)[0]; - - // render context for normal demo - const context = Object.entries(this.resolveMap).reduce( - (acc, [key, path]) => ({ + const context = Object.entries(demoDepsMap[this.id]).reduce( + (acc, [key, specifier]) => ({ ...acc, - // omit entry file - ...(key !== entryFileName - ? { - [key]: `{{{require('${path}')}}}`, - } - : {}), + ...{ [key]: `{{{${specifier}}}}` }, }), {}, ); - return JSON.stringify(context, null, 2).replace(/"{{{|}}}"/g, ''); }, renderRenderOpts: function renderRenderOpts(