方式一
添加路由配置项到 AppModule 中的 RouterModule.forRoot([...]) 里面
function addAppFieldToRouterModule(fileToAdd: string, routeLiterial: string) {
const tpl = fs.readFileSync(fileToAdd).toString();
const sourceFile = ts.createSourceFile(fileToAdd,tpl,ts.ScriptTarget.ES2015,true,ts.ScriptKind.TS);
const app: ts.ClassDeclaration = findNodes(sourceFile, ts.SyntaxKind.ClassDeclaration).find(r=> (r as ts.ClassDeclaration).name.text === 'AppModule') as ts.ClassDeclaration;
const decoraor: ts.Decorator = app.decorators[0] as ts.Decorator;;
const callExp = decoraor.expression as ts.CallExpression;
const allExp = callExp.arguments[0] as ts.ObjectLiteralExpression;
const importExp = allExp.properties.find(r=>r.kind === ts.SyntaxKind.PropertyAssignment && r.name.getText() === 'imports') as ts.PropertyAssignment;
const routeExp = importExp.initializer as ts.ArrayLiteralExpression;
const route = routeExp.elements.find(r=>r.kind === ts.SyntaxKind.CallExpression && (r as ts.CallExpression).expression.kind === ts.SyntaxKind.PropertyAccessExpression && r.getText().includes('RouterModule.forRoot')) as ts.CallExpression;
const routes = route.arguments[0] as ts.ArrayLiteralExpression;
const lastExp = routes.elements[routes.elements.length - 1];
const text = lastExp.getFullText();
const textMatch = text.match(/\r?\n(\r?)\s*/) || [];
const textLiterial = `${textMatch[0] ?? ' '}${routeLiterial}`;
const pos = lastExp.end;
const routeText = `,${textLiterial}`;
const rawText = fs.readFileSync(fileToAdd).toString('utf-8');
const prefix = rawText.substring(0, pos);
const suffix = rawText.substring(pos);
const fullText = `${prefix}${routeText}${suffix}`;
console.log(fullText);
const dest = __dirname+'/demo.ts';
saveAs(dest, fullText);
}
saveAs
保存文件到本地
function saveAs(fileToAdd: string, content:string) {
if(fs.existsSync(fileToAdd)) {
fs.unlinkSync(fileToAdd);
}
fs.writeFileSync(fileToAdd, content);
}
findNodes
通过遍历 ast 节点,找到条件对应的 ast
function findNodes(node: ts.Node, kind: ts.SyntaxKind): ts.Node[] {
const ans: ts.Node[] = [];
if(node.kind === kind) {
ans.push(node);
} else {
for(let child of node.getChildren()) {
findNodes(child, kind).forEach((node: ts.Node) => {
ans.push(node);
});
}
}
return ans;
}
addAppFieldToRouterModule(__dirname+'/demo.tpl', 'demoApp');
方式二
function addAppToRouterModule() {
const tpl = fs.readFileSync(__dirname+'/demo.tpl').toString();
const sourceFile = ts.createSourceFile(__dirname+'/demo.ts', tpl, ts.ScriptTarget.ES2015,true,ts.ScriptKind.TS);
let ans: ts.CallExpression;
function visitor(node: ts.Node): void {
if(!ans && node) {
if(ts.isPropertyAccessExpression(node) && node.getText().includes('RouterModule')) {
ans = node.parent as ts.CallExpression;
return;
}
node.forEachChild(visitor);
}
}
ts.forEachChild(sourceFile, visitor);
const exp = ans.arguments[0] as ts.ArrayLiteralExpression;
const elems = exp.elements;
const lastExp:any = elems[elems.length-1];
const rawText = fs.readFileSync(__dirname+'/demo.tpl').toString();
const text = lastExp.getFullText();
const textMatch = text.match(/\r?\n(\r?)\s*/) || [];
const textLiterial = `${textMatch[0] ?? ''}demoApp`;
const pos = lastExp.end;
const routeText = `,${textLiterial}`;
const prefix = rawText.substring(0, pos);
const suffix = rawText.substring(pos);
const result = `${prefix}${routeText}${suffix}`;
console.log(result);
}
方式三
if(ts.isIdentifier(lastExp)) {
const declaration = getAppDeclaration(sourceFile,lastExp.getText()) as ts.VariableStatement;
text = declaration.getText();
text = `\r\nconst demoApp = {
name: 'app.device',
url: '/app/device'
}`;
prefix = result.substring(0, declaration.end);
suffix = result.substring(declaration.end);
result = `${prefix}${text}${suffix}`;
}
console.log(result);
getAppDeclaration
function getAppDeclaration(node: ts.SourceFile, name: string): ts.VariableStatement | null {
const ans: ts.VariableStatement[] = [];
for(let child of node.statements) {
if(ts.isVariableStatement(child)) {
ans.push(child);
}
}
for(let vs of ans) {
const vd = vs.declarationList.declarations[0] as ts.VariableDeclaration;
for(let cd of vd.getChildren()) {
if(cd.getText() === name) {
return vs as ts.VariableStatement;
}
}
}
return null;
}
网友评论