问题描述
我在我的TypeScript node.js项目中使用JSX语法(根本不使用React)。
在我的tsconfig
中,我正在使用自己的jsxFactory
{
"compilerOptions": {
...
"jsxFactory": "myJSXFactory",...
}
}
<MyBanner backgroundColor="red" />
一切正常,并且在tsc编译后,上面的JSX变为了
myJSXFactory(MyBanner,{
backgroundColor: 'red'
});
现在,我想在编译期间向props
的JSX组件添加额外的All
,例如:
myJSXFactory(MyBanner,{
backgroundColor: 'red',theme: myTheme // a variable that's available in the parent context
});
我当时在看Compiler API,但是在JSX转换过程中如何修改源代码尚不清楚。
解决方法
正在回答我自己的问题...
import * as ts from "typescript";
type TYPESCRIPT = typeof ts;
function nodeVisitor(ts: TYPESCRIPT,ctx: ts.TransformationContext,sf: ts.SourceFile) {
const visitor: ts.Visitor = (node) => {
if (ts.isJsxOpeningElement(node) || ts.isJsxSelfClosingElement(node)) {
// Create theme attr
const themeAttr = ts.createPropertyAssignment(
'theme',ts.createIdentifier('request.query.theme')
)
// Create __my_extra_prop={{ theme: request.query.theme }} JSX Attribute
const sourceJsxAttr = ts.createJsxAttribute(
ts.createIdentifier('__my_extra_prop'),ts.createJsxExpression(undefined,ts.createObjectLiteral([themeAttr]))
)
const jsxAttributes = ts.createJsxAttributes([...node.attributes.properties,sourceJsxAttr])
const clonedNode = ts.getMutableClone(node)
clonedNode.attributes = jsxAttributes
return clonedNode
}
return ts.visitEachChild(node,visitor,ctx)
}
return visitor
}
function transform(ts: TYPESCRIPT): ts.TransformerFactory<ts.SourceFile> {
return (ctx) => (sf) => ts.visitNode(sf,nodeVisitor(ts,ctx,sf))
}
// JSX expression
const source = "<MyBanner backgroundColor='red' />";
const result = ts.transpileModule(source,{
compilerOptions: {
module: ts.ModuleKind.CommonJS,jsxFactory: "myJSXFactory",jsx: ts.JsxEmit.React
},transformers: {
before: [transform(ts)]
}
}
);
console.log(result.outputText);
https://repl.it/@ABMAdnan/TS-JSX-extra-props#index.ts
myJSXFactory(MyBanner,{ backgroundColor: 'red',__my_extra_prop: { theme: request.query.theme } });