使用typescript来修改js文件

原理

使用typescript把源代码读成ast,然后修改ast结构,然后将ast重新还原成js代码,最后将js代码重新写入文件。

具体步骤

将需要修改的代码以字符串的形式读进来

var file = fs.readFileSync(path, 'utf-8');

使用ts提供的一系列工具函数来生成和修改ast

const ts = require('typescript')

关键的转换代码

function transformTS(source, transformer) {
    const sourceFile = ts.createSourceFile(
        'test.ts', source, ts.ScriptTarget.ES2015, true, ts.ScriptKind.TS
    );
    const printer = ts.createPrinter();
    const result = ts.transform(
        sourceFile, [transformer]
    );
    const transformedSourceFile = result.transformed[0];
    const newContent = printer.printFile(transformedSourceFile)
    result.dispose()
    return newContent
}

这个函数主要是接受一个源代码字符串,可以是任意的js代码或者ts代码,还接受一个transformer,用来对生成的ast(抽象语法树)进行遍历,根据需要在对应的位置插入或修改。
一个transformer是一个函数,要写成下面这样的格式提供给ts.transform函数

 const transformer = (context) => {
        return (rootNode) => {
            function visit(node) {
                node = ts.visitEachChild(node, visit, context);
                if (ts.isArrowFunction(node)) {
                    console.log(node.body.statements);
                    let newLine = ts.createExpressionStatement(
                        ts.createCall(
                            ts.createPropertyAccess(
                                ts.createIdentifier('router'), 'get'), undefined,
                            [
                                ts.createLiteral(`/${namespace}/${pageName}`),
                                ts.createPropertyAccess(ts.createIdentifier('controller'),
                                    ts.createPropertyAccess(ts.createIdentifier(namespace), pageName))
                            ]))
                    node.body.statements = node.body.statements.concat(newLine);
                }
                return node;
            }
            return ts.visitNode(rootNode, visit);
        }
    }

这个函数主要是遍历ast的node节点,对于匹配的节点进行编辑操作,这个例子中遍历节点,在ts.isClassDelaration(node)这里判断是不是类声明,如果是的话就给这个类添加一个新的成员方法node.members = node.members.concat(createControllerMethod(pageName))
将代码转换之后并没有执行写入操作,需要将修改后的代码重新写入

fs.writeFileSync('app/router.ts', result);

你可能感兴趣的:(使用typescript来修改js文件)