微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

有没有办法从模板中获取 Angular AST使用 ng-ast?

如何解决有没有办法从模板中获取 Angular AST使用 ng-ast?

我想构建一个应用程序,它可以读取 Angular 应用程序的源文件,然后使用模板文件的 AST。

这是一个可以重现问题的独立节点脚本:

const Path = require('path');
const fs = require('fs');
const { WorkspaceSymbols } = require('ngast');

try { fs.mkdirsync("./foo") } catch (e) {};
try { fs.mkdirsync("./foo/src") } catch (e) {};
try { fs.mkdirsync("./foo/src/app") } catch (e) {};

const files = {
    "README.md": "# angular-ivy-scfsqv\n\n[Edit on StackBlitz ⚡️](https://stackblitz.com/edit/angular-ivy-scfsqv)","angular.json": "{\n  \"$schema\": \"./node_modules/@angular/cli/lib/config/schema.json\",\n  \"version\": 1,\n  \"newProjectRoot\": \"projects\",\n  \"projects\": {\n    \"demo\": {\n      \"root\": \"\",\n      \"sourceRoot\": \"src\",\n      \"projectType\": \"application\",\n      \"prefix\": \"app\",\n      \"schematics\": {},\n      \"architect\": {\n        \"build\": {\n          \"builder\": \"@angular-devkit/build-angular:browser\",\n          \"options\": {\n            \"outputPath\": \"dist/demo\",\n            \"index\": \"src/index.html\",\n            \"main\": \"src/main.ts\",\n            \"polyfills\": \"src/polyfills.ts\",\n            \"tsConfig\": \"src/tsconfig.app.json\",\n            \"assets\": [\n              \"src/favicon.ico\",\n              \"src/assets\"\n            ],\n            \"styles\": [\n              \"src/styles.css\"\n            ],\n            \"scripts\": []\n          },\n          \"configurations\": {\n            \"production\": {\n              \"fileReplacements\": [\n                {\n                  \"replace\": \"src/environments/environment.ts\",\n                  \"with\": \"src/environments/environment.prod.ts\"\n                }\n              ],\n              \"optimization\": true,\n              \"outputHashing\": \"all\",\n              \"sourceMap\": false,\n              \"extractCss\": true,\n              \"namedChunks\": false,\n              \"aot\": true,\n              \"extractLicenses\": true,\n              \"vendorChunk\": false,\n              \"buildOptimizer\": true\n            }\n          }\n        },\n        \"serve\": {\n          \"builder\": \"@angular-devkit/build-angular:dev-server\",\n          \"options\": {\n            \"browserTarget\": \"demo:build\"\n          },\n          \"configurations\": {\n            \"production\": {\n              \"browserTarget\": \"demo:build:production\"\n            }\n          }\n        },\n        \"extract-i18n\": {\n          \"builder\": \"@angular-devkit/build-angular:extract-i18n\",\n          \"options\": {\n            \"browserTarget\": \"demo:build\"\n          }\n        },\n        \"test\": {\n          \"builder\": \"@angular-devkit/build-angular:karma\",\n          \"options\": {\n            \"main\": \"src/test.ts\",\n            \"tsConfig\": \"src/tsconfig.spec.json\",\n            \"karmaConfig\": \"src/karma.conf.js\",\n            \"styles\": [\n              \"styles.css\"\n            ],\n            \"scripts\": [],\n              \"src/assets\"\n            ]\n          }\n        },\n        \"lint\": {\n          \"builder\": \"@angular-devkit/build-angular:tslint\",\n          \"options\": {\n            \"tsConfig\": [\n              \"src/tsconfig.app.json\",\n              \"src/tsconfig.spec.json\"\n            ],\n            \"exclude\": [\n              \"**/node_modules/**\"\n            ]\n          }\n        }\n      }\n    }\n  },\n  \"defaultProject\": \"demo\"\n}","package.json": "{\n  \"name\": \"angular\",\n  \"version\": \"0.0.0\",\n  \"private\": true,\n  \"dependencies\": {\n    \"@angular/animations\": \"^11.0.8\",\n    \"@angular/common\": \"^11.0.8\",\n    \"@angular/compiler\": \"^11.0.8\",\n    \"@angular/core\": \"^11.0.8\",\n    \"@angular/forms\": \"^11.0.8\",\n    \"@angular/platform-browser\": \"^11.0.8\",\n    \"@angular/platform-browser-dynamic\": \"^11.0.8\",\n    \"@angular/router\": \"^11.0.8\",\n    \"rxjs\": \"^6.6.3\",\n    \"tslib\": \"^2.1.0\",\n    \"zone.js\": \"^0.11.3\"\n  },\n  \"scripts\": {\n    \"ng\": \"ng\",\n    \"start\": \"ng serve\",\n    \"build\": \"ng build\",\n    \"test\": \"ng test\",\n    \"lint\": \"ng lint\",\n    \"e2e\": \"ng e2e\"\n  },\n  \"devDependencies\": {\n    \"@angular-devkit/build-angular\": \"~0.1100.4\",\n    \"@angular/cli\": \"~11.0.4\",\n    \"@angular/compiler-cli\": \"~11.0.4\",\n    \"@types/jasmine\": \"~3.6.0\",\n    \"@types/node\": \"^12.11.1\",\n    \"codelyzer\": \"^6.0.0\",\n    \"jasmine-core\": \"~3.6.0\",\n    \"jasmine-spec-reporter\": \"~5.0.0\",\n    \"karma\": \"~5.1.0\",\n    \"karma-chrome-launcher\": \"~3.1.0\",\n    \"karma-coverage\": \"~2.0.3\",\n    \"karma-jasmine\": \"~4.0.0\",\n    \"karma-jasmine-html-reporter\": \"^1.5.0\",\n    \"protractor\": \"~7.0.0\",\n    \"ts-node\": \"~8.3.0\",\n    \"tslint\": \"~6.1.0\",\n    \"typescript\": \"~4.0.2\"\n  }\n}","tsconfig.json": "{\n  \"compileOnSave\": false,\n  \"compilerOptions\": {\n    \"baseUrl\": \"./\",\n    \"outDir\": \"./dist/out-tsc\",\n    \"sourceMap\": true,\n    \"declaration\": false,\n    \"downlevelIteration\": true,\n    \"experimentalDecorators\": true,\n    \"module\": \"esnext\",\n    \"moduleResolution\": \"node\",\n    \"importHelpers\": true,\n    \"target\": \"es2015\",\n    \"typeRoots\": [\n      \"node_modules/@types\"\n    ],\n    \"lib\": [\n      \"es2018\",\n      \"dom\"\n    ]\n  },\n  \"angularCompilerOptions\": {\n    \"enableIvy\": true,\n    \"fullTemplateTypeCheck\": true,\n    \"strictInjectionParameters\": true\n  }\n}","src/index.html": "<link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css\">\n<my-app>loading</my-app>","src/main.ts": "import './polyfills';\n\nimport { enableProdMode } from '@angular/core';\nimport { platformbrowserDynamic } from '@angular/platform-browser-dynamic';\n\nimport { AppModule } from './app/app.module';\n\nplatformbrowserDynamic().bootstrapModule(AppModule).then(ref => {\n  // Ensure Angular destroys itself on hot reloads.\n  if (window['ngRef']) {\n    window['ngRef'].destroy();\n  }\n  window['ngRef'] = ref;\n\n  // Otherwise,log the boot error\n}).catch(err => console.error(err));","src/polyfills.ts": "/**\n * This file includes polyfills needed by Angular and is loaded before the app.\n * You can add your own extra polyfills to this file.\n *\n * This file is divided into 2 sections:\n *   1. browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.\n *   2. Application imports. Files imported after ZoneJS that should be loaded before your main\n *      file.\n *\n * The current setup is for so-called \"evergreen\" browsers; the last versions of browsers that\n * automatically update themselves. This includes Safari >= 10,Chrome >= 55 (including Opera),\n * Edge >= 13 on the desktop,and iOS 10 and Chrome on mobile.\n *\n * Learn more in https://angular.io/docs/ts/latest/guide/browser-support.html\n */\n\n/***************************************************************************************************\n * broWSER polyFILLS\n */\n\n/** IE9,IE10 and IE11 requires all of the following polyfills. **/\n// import 'core-js/es6/symbol';\n// import 'core-js/es6/object';\n// import 'core-js/es6/function';\n// import 'core-js/es6/parse-int';\n// import 'core-js/es6/parse-float';\n// import 'core-js/es6/number';\n// import 'core-js/es6/math';\n// import 'core-js/es6/string';\n// import 'core-js/es6/date';\n// import 'core-js/es6/array';\n// import 'core-js/es6/regexp';\n// import 'core-js/es6/map';\n// import 'core-js/es6/set';\n\n/** IE10 and IE11 requires the following for NgClass support on SVG elements */\n// import 'classlist.js';  // Run `npm install --save classlist.js`.\n\n/** IE10 and IE11 requires the following to support `@angular/animation`. */\n// import 'web-animations-js';  // Run `npm install --save web-animations-js`.\n\n\n/** Evergreen browsers require these. **/\n// import 'core-js/es6/reflect';\n// import 'core-js/es7/reflect';\n\n\n/**\n * Web Animations `@angular/platform-browser/animations`\n * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari.\n * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0).\n */\n// import 'web-animations-js';  // Run `npm install --save web-animations-js`.\n\n\n\n/***************************************************************************************************\n * Zone JS is required by Angular itself.\n */\nimport 'zone.js/dist/zone';  // Included with Angular CLI.\n\n\n/***************************************************************************************************\n * APPLICATION IMPORTS\n */\n\n/**\n * Date,currency,decimal and percent pipes.\n * Needed for: All but Chrome,Firefox,Edge,IE11 and Safari 10\n */\n// import 'intl';  // Run `npm install --save intl`.","src/styles.css": "/* Add application styles & imports to this file! */","src/app/app.component.html": "<div class=\"container\">\n<div class=\"row\">\n\t<div class=\"col-md-6\">\n\t\t<h3 class=\"mb-5\">Invoice</h3>\n\t\t<div>\n\t\t\t<div class=\"row mb-2\">\n\t\t\t\t<label for=\"client\" class=\"col-form-label col-2\">Client</label>\n\t\t\t\t<div class=\"col-6\">\n\t\t\t\t\t<input type=\"text\" id=\"client\" class=\"form-control\">\n                </div>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"row mb-2\">\n\t\t\t\t\t<label for=\"amount\" class=\"col-form-label col-2\">Amount</label>\n\t\t\t\t\t<div class=\"col-6\">\n\t\t\t\t\t\t<input type=\"number\" id=\"amount\" class=\"form-control\">\n                </div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"row mb-2\">\n\t\t\t\t\t\t<label for=\"date\" class=\"col-form-label col-2\">Date</label>\n\t\t\t\t\t\t<div class=\"col-6\">\n\t\t\t\t\t\t\t<input type=\"date\" id=\"date\" class=\"form-control\">\n                </div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"col-md-6\">\n\t\t\t\t\t<h3 class=\"mb-5\">Preview</h3>\n\t\t\t\t\t<p>Client: <span class=\"bg-warning rounded p-2\">Todo</span></p>\n\t\t\t\t\t<p>Amount: <span class=\"bg-warning rounded p-2\">Todo</span></p>\n\t\t\t\t\t<p>Date: <span class=\"bg-warning rounded p-2\">Todo</span></p>\n\t\t\t\t</div>\n\t\t\t</div></div>","src/app/app.component.ts": "import { Component,VERSION } from \"@angular/core\";\n\n@Component({\n  selector: \"my-app\",\n  templateUrl: \"./app.component.html\",\n  styleUrls: []\n})\nexport class AppComponent {\n  name = \"Angular \" + VERSION.major;\n}\n","src/app/app.module.ts": "import { NgModule } from '@angular/core';\nimport { browserModule } from '@angular/platform-browser';\nimport { FormsModule } from '@angular/forms';\n\nimport { AppComponent } from './app.component';\n\n@NgModule({\n  imports:      [ browserModule,FormsModule ],\n  declarations: [ AppComponent ],\n  bootstrap:    [ AppComponent ]\n})\nexport class AppModule { }\n"
};

Object.entries(files).forEach(([path,contents]) => {
    fs.writeFileSync(Path.join(__dirname,`./foo/${path}`),contents);
});

const config = Path.join(process.cwd(),'./foo/tsconfig.json');
const workspace = new WorkspaceSymbols(config);
console.log(workspace.getAllComponents()[0].getTemplateAst());

最后,即使存在 workspace.getAllComponents()[0].getTemplateAst() 模板,null 也会返回 app.component.html

我真的不需要编译整个项目 - 我只需要一种方法获取单个 Angular HTML 文件并从中获取 AST。这可能吗?

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。