-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(umi-plugin): support to transform code block to demo previewer (#3)
- Loading branch information
1 parent
1227906
commit 7a399ba
Showing
7 changed files
with
141 additions
and
12 deletions.
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
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
72 changes: 72 additions & 0 deletions
72
packages/umi-plugin-father-doc/src/transformer/previewer/index.ts
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 |
---|---|---|
@@ -0,0 +1,72 @@ | ||
import path from 'path'; | ||
import * as babel from '@babel/core'; | ||
import * as types from '@babel/types'; | ||
import traverse from '@babel/traverse'; | ||
import generator from '@babel/generator'; | ||
|
||
export const PREVIEWER_NAME = 'FatherDocPreviewer'; | ||
|
||
/** | ||
* transform code block statments to preview | ||
*/ | ||
export default (raw: string, dir: string, isTSX?: boolean) => { | ||
const code = babel.transformSync(raw, { | ||
presets: [ | ||
require.resolve('@babel/preset-react'), | ||
require.resolve('@babel/preset-env'), | ||
], | ||
plugins: (isTSX | ||
? [['@babel/plugin-transform-typescript', { isTSX: true }]] | ||
: [] | ||
), | ||
ast: true, | ||
}); | ||
const body = code.ast.program.body as types.Statement[]; | ||
let returnStatement; | ||
|
||
// traverse call expression | ||
traverse(code.ast, { | ||
CallExpression(callPath) { | ||
const nodeCallee = callPath.node.callee; | ||
|
||
// remove original render expression | ||
if ( | ||
types.isMemberExpression(nodeCallee) | ||
&& nodeCallee.object | ||
&& (nodeCallee.object.loc as any).identifierName === 'ReactDOM' | ||
&& nodeCallee.property | ||
&& nodeCallee.property.name === 'render' | ||
&& types.isExpression(callPath.node.arguments[0]) | ||
) { | ||
// save render expression as return statement | ||
returnStatement = types.returnStatement(callPath.node.arguments[0]); | ||
callPath.remove(); | ||
} | ||
|
||
// replace relative module path | ||
if ( | ||
dir | ||
&& types.isIdentifier(nodeCallee) | ||
&& nodeCallee.name === 'require' | ||
&& types.isStringLiteral(callPath.node.arguments[0]) | ||
&& callPath.node.arguments[0].value.startsWith('.') | ||
) { | ||
callPath.node.arguments[0].value = path.join(dir, callPath.node.arguments[0].value); | ||
} | ||
}, | ||
}); | ||
|
||
// push return statement to program body | ||
if (returnStatement) { | ||
body.push(returnStatement); | ||
} | ||
|
||
// create preview function | ||
const previewFunction = types.functionDeclaration( | ||
types.identifier(PREVIEWER_NAME), | ||
[], | ||
types.blockStatement(body), | ||
); | ||
|
||
return generator(types.program([previewFunction]), {}, raw).code; | ||
} |
20 changes: 11 additions & 9 deletions
20
packages/umi-plugin-father-doc/src/transformer/remark/index.ts
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,15 +1,17 @@ | ||
import unified from 'unified'; | ||
import parse from 'remark-parse'; | ||
import rehype from 'remark-rehype'; | ||
import stringify from 'rehype-stringify'; | ||
import prism from '@mapbox/rehype-prism'; | ||
import parse from './parse'; | ||
import rehype from './rehype'; | ||
import jsx from './jsx'; | ||
|
||
const processor = unified() | ||
.use(parse) | ||
.use(rehype) | ||
.use(stringify, { allowDangerousHTML: true }) | ||
.use(prism) | ||
.use(jsx); | ||
export default (raw: string, dir: string) => { | ||
const processor = unified() | ||
.use(parse) | ||
.use(rehype, { dir }) | ||
.use(stringify, { allowDangerousHTML: true }) | ||
.use(prism) | ||
.use(jsx); | ||
|
||
export default (raw: string) => processor.processSync(raw).contents as string; | ||
return processor.processSync(raw).contents as string; | ||
}; |
24 changes: 24 additions & 0 deletions
24
packages/umi-plugin-father-doc/src/transformer/remark/parse.ts
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 |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import parse from 'remark-parse'; | ||
|
||
const { blockTokenizers } = parse.Parser.prototype as any; | ||
const oFencedCode = blockTokenizers.fencedCode; | ||
|
||
// override original fencedCode tokenizer | ||
blockTokenizers.fencedCode = function (...args) { | ||
const result = oFencedCode.apply(this, args); | ||
|
||
// only process jsx & tsx code block | ||
if (result && /^[jt]sx$/.test(result.lang)) { | ||
if ((result.meta || '').indexOf('pure') > -1) { | ||
// clear useless meta if the lang with pure modifier | ||
result.meta = result.meta.replace(/ ?\| ?pure/, ''); | ||
} else { | ||
// customize type (use for rehype previewer handler) | ||
result.type = 'previewer'; | ||
} | ||
} | ||
|
||
return result; | ||
} | ||
|
||
export default parse; |
24 changes: 24 additions & 0 deletions
24
packages/umi-plugin-father-doc/src/transformer/remark/rehype.ts
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 |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import rehype from 'remark-rehype'; | ||
import unist from 'unist-builder'; | ||
import transformer, { PREVIEWER_NAME } from '../previewer'; | ||
|
||
/** | ||
* handle previewer type node from parse | ||
*/ | ||
function previewerHandler(h, node) { | ||
const code = `{(function () { | ||
${transformer(node.value, this.dir, node.lang === 'tsx')} | ||
return <${PREVIEWER_NAME} />; | ||
})()}` | ||
; | ||
|
||
return h(node.position, 'div', [unist('raw', code)]); | ||
} | ||
|
||
export default (options: { [key: string]: any } = {}) => { | ||
return rehype(Object.assign({ | ||
handlers: { | ||
previewer: previewerHandler.bind({ dir: options.dir }), | ||
}, | ||
}, options)); | ||
} |