-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: split markdown meta loader #1875
Merged
Merged
Changes from 4 commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
f8ed1bd
feat: split mdLoader type
MadCcc 7f4fbc0
feat: split mdLoader
MadCcc b6d608f
Merge branch 'feature/2.3.0' into feat/loader-split
MadCcc 904896f
chore: code optimize
MadCcc 9321eb1
fix: use winPath
MadCcc 79b33bd
chore: update getter
MadCcc File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,12 @@ | ||
import * as demo from '../../docs/index.md?type=demo'; | ||
import * as demoIndex from '../../docs/index.md?type=demo-index'; | ||
import * as frontmatter from '../../docs/index.md?type=frontmatter'; | ||
import * as text from '../../docs/index.md?type=text'; | ||
|
||
console.log('frontmatter', frontmatter); | ||
console.log('demo', demo); | ||
console.log('demoIndex', demoIndex); | ||
console.log('text', text); | ||
|
||
// Customize Page for dumi test | ||
export default () => 'Customize Dumi Test Page'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,11 +13,6 @@ interface IMdLoaderDefaultModeOptions | |
extends Omit<IMdTransformerOptions, 'fileAbsPath'> { | ||
mode?: 'markdown'; | ||
builtins: IThemeLoadResult['builtins']; | ||
} | ||
|
||
interface IMdLoaderDemosModeOptions | ||
extends Omit<IMdLoaderDefaultModeOptions, 'builtins' | 'mode'> { | ||
mode: 'meta'; | ||
onResolveDemos?: ( | ||
demos: NonNullable<IMdTransformerResult['meta']['demos']>, | ||
) => void; | ||
|
@@ -27,9 +22,38 @@ interface IMdLoaderDemosModeOptions | |
) => void; | ||
} | ||
|
||
interface IMdLoaderDemosModeOptions | ||
extends Omit<IMdLoaderDefaultModeOptions, 'builtins' | 'mode'> { | ||
mode: 'meta'; | ||
} | ||
|
||
interface IMdLoaderDemoModeOptions | ||
extends Omit<IMdLoaderDefaultModeOptions, 'builtins' | 'mode'> { | ||
mode: 'demo'; | ||
} | ||
|
||
interface IMdLoaderDemoIndexModeOptions | ||
extends Omit<IMdLoaderDefaultModeOptions, 'builtins' | 'mode'> { | ||
mode: 'demo-index'; | ||
} | ||
|
||
interface IMdLoaderFrontmatterModeOptions | ||
extends Omit<IMdLoaderDefaultModeOptions, 'builtins' | 'mode'> { | ||
mode: 'frontmatter'; | ||
} | ||
|
||
interface IMdLoaderTextModeOptions | ||
extends Omit<IMdLoaderDefaultModeOptions, 'builtins' | 'mode'> { | ||
mode: 'text'; | ||
} | ||
|
||
export type IMdLoaderOptions = | ||
| IMdLoaderDefaultModeOptions | ||
| IMdLoaderDemosModeOptions; | ||
| IMdLoaderDemosModeOptions | ||
| IMdLoaderDemoModeOptions | ||
| IMdLoaderFrontmatterModeOptions | ||
| IMdLoaderTextModeOptions | ||
| IMdLoaderDemoIndexModeOptions; | ||
|
||
function getDemoSourceFiles(demos: IMdTransformerResult['meta']['demos'] = []) { | ||
return demos.reduce<string[]>((ret, demo) => { | ||
|
@@ -41,30 +65,15 @@ function getDemoSourceFiles(demos: IMdTransformerResult['meta']['demos'] = []) { | |
}, []); | ||
} | ||
|
||
function emit(this: any, opts: IMdLoaderOptions, ret: IMdTransformerResult) { | ||
const { demos, embeds } = ret.meta; | ||
|
||
// declare embedded files as loader dependency, for re-compiling when file changed | ||
embeds!.forEach((file) => this.addDependency(file)); | ||
|
||
// declare demo source files as loader dependency, for re-compiling when file changed | ||
getDemoSourceFiles(demos).forEach((file) => this.addDependency(file)); | ||
|
||
if (opts.mode === 'meta') { | ||
const { frontmatter, toc, texts } = ret.meta; | ||
|
||
// apply demos resolve hook | ||
if (demos && opts.onResolveDemos) { | ||
opts.onResolveDemos(demos); | ||
} | ||
function emitMeta( | ||
this: any, | ||
opts: IMdLoaderDemosModeOptions, | ||
ret: IMdTransformerResult, | ||
) { | ||
const { frontmatter, toc, texts, demos } = ret.meta; | ||
|
||
// apply atom meta resolve hook | ||
if (frontmatter!.atomId && opts.onResolveAtomMeta) { | ||
opts.onResolveAtomMeta(frontmatter!.atomId, frontmatter); | ||
} | ||
|
||
return Mustache.render( | ||
`import React from 'react'; | ||
return Mustache.render( | ||
`import React from 'react'; | ||
|
||
export const demos = { | ||
{{#demos}} | ||
|
@@ -78,43 +87,60 @@ export const frontmatter = {{{frontmatter}}}; | |
export const toc = {{{toc}}}; | ||
export const texts = {{{texts}}}; | ||
`, | ||
{ | ||
demos, | ||
frontmatter: JSON.stringify(frontmatter), | ||
toc: JSON.stringify(toc), | ||
texts: JSON.stringify(texts), | ||
renderAsset: function renderAsset(this: NonNullable<typeof demos>[0]) { | ||
// do not render asset for inline demo | ||
if (!('asset' in this)) return 'null'; | ||
|
||
// render asset for normal demo | ||
let { asset } = this; | ||
const { sources } = this; | ||
|
||
// use raw-loader to load all source files | ||
Object.keys(this.sources).forEach((file: string) => { | ||
// handle un-existed source file, e.g. custom tech-stack return custom dependencies | ||
if (!asset.dependencies[file]) return; | ||
|
||
// to avoid modify original asset object | ||
asset = lodash.cloneDeep(asset); | ||
asset.dependencies[ | ||
file | ||
].value = `{{{require('-!${sources[file]}?dumi-raw').default}}}`; | ||
}); | ||
|
||
return JSON.stringify(asset, null, 2).replace(/"{{{|}}}"/g, ''); | ||
}, | ||
{ | ||
demos, | ||
frontmatter: JSON.stringify(frontmatter), | ||
toc: JSON.stringify(toc), | ||
texts: JSON.stringify(texts), | ||
renderAsset: function renderAsset(this: NonNullable<typeof demos>[0]) { | ||
// do not render asset for inline demo | ||
if (!('asset' in this)) return 'null'; | ||
|
||
// render asset for normal demo | ||
let { asset } = this; | ||
const { sources } = this; | ||
|
||
// use raw-loader to load all source files | ||
Object.keys(this.sources).forEach((file: string) => { | ||
// handle un-existed source file, e.g. custom tech-stack return custom dependencies | ||
if (!asset.dependencies[file]) return; | ||
|
||
// to avoid modify original asset object | ||
asset = lodash.cloneDeep(asset); | ||
asset.dependencies[ | ||
file | ||
].value = `{{{require('-!${sources[file]}?dumi-raw').default}}}`; | ||
}); | ||
|
||
return JSON.stringify(asset, null, 2).replace(/"{{{|}}}"/g, ''); | ||
}, | ||
); | ||
} else { | ||
// do not wrap DumiPage for tab content | ||
const isTabContent = isTabRouteFile(this.resourcePath); | ||
|
||
// import all builtin components, may be used by markdown content | ||
return `${Object.values(opts.builtins) | ||
.map((item) => `import ${item.specifier} from '${item.source}';`) | ||
.join('\n')} | ||
}, | ||
); | ||
} | ||
|
||
function emitDefault( | ||
this: any, | ||
opts: IMdLoaderDefaultModeOptions, | ||
ret: IMdTransformerResult, | ||
) { | ||
const { frontmatter, demos } = ret.meta; | ||
// do not wrap DumiPage for tab content | ||
const isTabContent = isTabRouteFile(this.resourcePath); | ||
|
||
// apply demos resolve hook | ||
if (demos && opts.onResolveDemos) { | ||
opts.onResolveDemos(demos); | ||
} | ||
|
||
// apply atom meta resolve hook | ||
if (frontmatter!.atomId && opts.onResolveAtomMeta) { | ||
opts.onResolveAtomMeta(frontmatter!.atomId, frontmatter); | ||
} | ||
|
||
// import all builtin components, may be used by markdown content | ||
return `${Object.values(opts.builtins) | ||
.map((item) => `import ${item.specifier} from '${item.source}';`) | ||
.join('\n')} | ||
import React from 'react'; | ||
${ | ||
isTabContent | ||
|
@@ -126,12 +152,122 @@ ${ | |
// ref: https://github.com/pmmmwh/react-refresh-webpack-plugin/blob/main/docs/TROUBLESHOOTING.md#edits-always-lead-to-full-reload | ||
function DumiMarkdownContent() { | ||
const { texts: ${CONTENT_TEXTS_OBJ_NAME} } = use${ | ||
isTabContent ? 'TabMeta' : 'RouteMeta' | ||
}(); | ||
isTabContent ? 'TabMeta' : 'RouteMeta' | ||
}(); | ||
return ${isTabContent ? ret.content : `<DumiPage>${ret.content}</DumiPage>`}; | ||
} | ||
|
||
export default DumiMarkdownContent;`; | ||
} | ||
|
||
function emitDemo(opts: IMdLoaderDemoModeOptions, ret: IMdTransformerResult) { | ||
const { demos } = ret.meta; | ||
|
||
return Mustache.render( | ||
`import React from 'react'; | ||
|
||
export const demos = { | ||
{{#demos}} | ||
'{{{id}}}': { | ||
component: {{{component}}}, | ||
asset: {{{renderAsset}}} | ||
}, | ||
{{/demos}} | ||
};`, | ||
{ | ||
demos, | ||
renderAsset: function renderAsset(this: NonNullable<typeof demos>[0]) { | ||
// do not render asset for inline demo | ||
if (!('asset' in this)) return 'null'; | ||
|
||
// render asset for normal demo | ||
let { asset } = this; | ||
const { sources } = this; | ||
|
||
// use raw-loader to load all source files | ||
Object.keys(this.sources).forEach((file: string) => { | ||
// handle un-existed source file, e.g. custom tech-stack return custom dependencies | ||
if (!asset.dependencies[file]) return; | ||
|
||
// to avoid modify original asset object | ||
asset = lodash.cloneDeep(asset); | ||
asset.dependencies[ | ||
file | ||
].value = `{{{require('-!${sources[file]}?dumi-raw').default}}}`; | ||
}); | ||
|
||
return JSON.stringify(asset, null, 2).replace(/"{{{|}}}"/g, ''); | ||
}, | ||
}, | ||
); | ||
} | ||
|
||
function emitDemoIndex( | ||
this: any, | ||
opts: IMdLoaderDemoIndexModeOptions, | ||
ret: IMdTransformerResult, | ||
) { | ||
const { demos } = ret.meta; | ||
|
||
return Mustache.render( | ||
`export const demoIndex = { | ||
ids: {{{ids}}}, | ||
getter: () => {{{getter}}} | ||
};`, | ||
{ | ||
ids: JSON.stringify(demos?.map((demo) => demo.id)), | ||
getter: `() => import('${this.resourcePath}?type=demo')`, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. resourcePath 要套一下 winPath,应该是这里引起了 CI 报错 |
||
}, | ||
); | ||
} | ||
|
||
function emitFrontmatter( | ||
opts: IMdLoaderFrontmatterModeOptions, | ||
ret: IMdTransformerResult, | ||
) { | ||
const { frontmatter } = ret.meta; | ||
|
||
return Mustache.render(`export const frontmatter = {{{frontmatter}}};`, { | ||
frontmatter: JSON.stringify(frontmatter), | ||
}); | ||
} | ||
|
||
function emitText(opts: IMdLoaderTextModeOptions, ret: IMdTransformerResult) { | ||
const { texts, toc } = ret.meta; | ||
|
||
return Mustache.render( | ||
`export const toc = {{{toc}}}; | ||
export const texts = {{{texts}}};`, | ||
{ | ||
toc: JSON.stringify(toc), | ||
texts: JSON.stringify(texts), | ||
}, | ||
); | ||
} | ||
|
||
function emit(this: any, opts: IMdLoaderOptions, ret: IMdTransformerResult) { | ||
const { demos, embeds } = ret.meta; | ||
|
||
// declare embedded files as loader dependency, for re-compiling when file changed | ||
embeds!.forEach((file) => this.addDependency(file)); | ||
|
||
// declare demo source files as loader dependency, for re-compiling when file changed | ||
getDemoSourceFiles(demos).forEach((file) => this.addDependency(file)); | ||
|
||
switch (opts.mode) { | ||
// TODO: Should be removed | ||
case 'meta': | ||
return emitMeta.call(this, opts, ret); | ||
case 'demo': | ||
return emitDemo.call(this, opts, ret); | ||
case 'demo-index': | ||
return emitDemoIndex.call(this, opts, ret); | ||
case 'frontmatter': | ||
return emitFrontmatter.call(this, opts, ret); | ||
case 'text': | ||
return emitText.call(this, opts, ret); | ||
default: | ||
return emitDefault.call(this, opts, ret); | ||
} | ||
} | ||
|
||
|
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
留着 meta 是为了让编译能通过对么,下面
onResolveDemos
的钩子函数和里面的参数类型是不是可以先删了,不然调用两遍资产元数据会有问题