Last active
December 15, 2020 05:22
-
-
Save cevek/b3abc1de42303eab69d9bab0220a75c0 to your computer and use it in GitHub Desktop.
Typescript pre transformer
This file contains hidden or 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
"use strict"; | |
function Bar(props) { return null; } | |
React.createElement(Bar, { sdf: true, id: 'hello' }); | |
React.createElement("div", { id: 'hi' }, "abc"); | |
React.createElement("div", null, "abc"); |
This file contains hidden or 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
function Bar(props: {id: string}){return null} | |
<Bar.hello sdf={true}></Bar>; | |
<div.hi>abc</div>; | |
<div>abc</div> ; |
This file contains hidden or 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
import * as ts from 'typescript'; | |
const createProgram: any = ts.createProgram; | |
const options = { | |
jsx: ts.JsxEmit.React, | |
strict: true, | |
}; | |
const host = ts.createCompilerHost(options); | |
const originalGetSource = host.getSourceFile; | |
host.getSourceFile = (fileName: string, languageVersion: ts.ScriptTarget, ...args: any[]) => { | |
if (fileName.match(/(\.d\.ts|\.js)$/)) { | |
return originalGetSource(fileName, languageVersion, ...args); | |
} | |
const sourceText = ts.sys.readFile(fileName)!; | |
patchJsxClosingElementToAvoidDifferentTagNamesError(); | |
const source = ts.createSourceFile(fileName, sourceText, languageVersion); | |
const { transformed } = (ts as any).transformNodes( | |
undefined, | |
host, | |
options, | |
[source], | |
[transformer], | |
/*allowDtsFiles*/ false | |
); | |
const changedSource = transformed[0]; | |
// if (!changed.ambientModuleNames) { | |
// changed.ambientModuleNames = []; | |
// } | |
changedSource.flags = 0; | |
return changedSource; | |
}; | |
const myprogram = ts.createProgram({ | |
rootNames: ['./test.tsx'], | |
host, | |
options, | |
}); | |
myprogram.emit(); | |
function error(m: any) { | |
return m.messageText; | |
} | |
console.log({ | |
global: myprogram.getGlobalDiagnostics().map(error), | |
options: myprogram.getOptionsDiagnostics().map(error), | |
syntactic: myprogram.getSyntacticDiagnostics().map(error), | |
semantic: myprogram.getSemanticDiagnostics().map(error), | |
}); | |
function transformer(ctx: ts.TransformationContext) { | |
return function transform(source: ts.SourceFile) { | |
function visitor(node: ts.Node): ts.Node { | |
if ( | |
ts.isJsxOpeningElement(node) && | |
ts.isPropertyAccessExpression(node.tagName) && | |
ts.isIdentifier(node.tagName.expression) | |
) { | |
const attrs = node.attributes; | |
const idProp: ts.JsxAttributeLike = updatePos( | |
ts.createJsxAttribute( | |
updatePos(ts.createIdentifier('id')), | |
updatePos(ts.createLiteral(node.tagName.name.text)) | |
) | |
); | |
const newProps = ts.createNodeArray([...attrs.properties, idProp]); | |
const newAttrs = ts.updateJsxAttributes(attrs, newProps); | |
const nnode = ts.updateJsxOpeningElement(node, node.tagName.expression, node.typeArguments, newAttrs); | |
nnode.flags = 0; | |
return nnode; | |
} | |
if ( | |
ts.isJsxClosingElement(node) && | |
ts.isPropertyAccessExpression(node.tagName) && | |
ts.isIdentifier(node.tagName.expression) | |
) { | |
const nnode = ts.updateJsxClosingElement(node, node.tagName.expression); | |
nnode.flags = 0; | |
return nnode; | |
} | |
return ts.visitEachChild(node, visitor, ctx); | |
} | |
return ts.visitNode(source, visitor); | |
}; | |
function updatePos<T extends ts.Node>(node: T) { | |
node.pos = 0; | |
node.end = 1; | |
node.flags = 0; | |
return node; | |
} | |
} | |
function patchJsxClosingElementToAvoidDifferentTagNamesError() { | |
const NodeObj = ts.createJsxClosingElement('ab' as any).constructor; | |
Object.defineProperty(NodeObj.prototype, 'closingElement', { | |
get() { | |
return this._closingElement; | |
}, | |
set(node: ts.JsxClosingElement) { | |
debugger; | |
if ( | |
ts.isPropertyAccessExpression(this.openingElement.tagName) && | |
ts.isIdentifier(this.openingElement.tagName.expression) | |
) { | |
node = ts.updateJsxClosingElement(node, this.openingElement.tagName); | |
node.flags = 0; | |
} | |
this._closingElement = node; | |
}, | |
configurable: true, | |
}); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment