[
  {
    "path": ".eslintignore",
    "content": "/tests/\n.yarn/\ndist/\nnode_modules/\ntest/test-project-host-hello-world-app-*\ntest/hello-world-app\njest.builder.config.ts\nbuild-ng-package.ts\nschema-merge.ts\ntest/util\ncommitlint.config.js\nscript\n**/fixture\n*.xspec.ts\nsrc/library/common\nsrc/libary/forms\ntest\nsrc/library/platform/http\ndeploy\ndocs"
  },
  {
    "path": ".eslintrc.json",
    "content": "{\n  \"ignorePatterns\": [\n    \"src/library/forms/**/*\",\n    \"src/library/common/**/*\",\n    \"*.d.ts\",\n    \"src/builder/karma/client/**/*\",\n    \"src/builder/karma/plugin/**/*\"\n  ],\n  \"root\": true,\n  \"env\": {\n    \"es6\": true,\n    \"node\": true\n  },\n  \"extends\": [\n    \"eslint:recommended\",\n    \"plugin:import/typescript\",\n    \"plugin:@typescript-eslint/recommended\",\n    \"plugin:@typescript-eslint/recommended-requiring-type-checking\",\n    \"prettier\"\n  ],\n  \"parser\": \"@typescript-eslint/parser\",\n  \"parserOptions\": {\n    \"project\": \"tsconfig.json\",\n    \"sourceType\": \"module\"\n  },\n  \"plugins\": [\"eslint-plugin-import\", \"@typescript-eslint\"],\n  \"rules\": {\n    \"@typescript-eslint/consistent-type-assertions\": \"warn\",\n    \"@typescript-eslint/no-explicit-any\": \"warn\",\n    \"@typescript-eslint/no-non-null-assertion\": \"off\",\n    \"@typescript-eslint/no-unnecessary-qualifier\": \"warn\",\n    \"@typescript-eslint/no-unused-expressions\": \"warn\",\n    \"curly\": \"warn\",\n    \"import/first\": \"warn\",\n    \"import/newline-after-import\": \"warn\",\n    \"import/no-absolute-path\": \"warn\",\n    \"import/no-duplicates\": \"warn\",\n    \"import/no-extraneous-dependencies\": [\n      \"off\",\n      {\n        \"devDependencies\": false\n      }\n    ],\n    \"import/no-unassigned-import\": [\n      \"warn\",\n      {\n        \"allow\": [\"miniprogram-api-typings\"]\n      }\n    ],\n    \"import/order\": [\n      \"warn\",\n      {\n        \"alphabetize\": {\n          \"order\": \"asc\"\n        },\n        \"groups\": [[\"builtin\", \"external\"], \"parent\", \"sibling\", \"index\"]\n      }\n    ],\n    \"max-len\": [\n      \"warn\",\n      {\n        \"code\": 140,\n        \"ignoreUrls\": true,\n        \"ignoreStrings\": true,\n        \"ignoreTemplateLiterals\": true,\n        \"ignoreComments\": true,\n        \"ignoreRegExpLiterals\": true\n      }\n    ],\n    \"max-lines-per-function\": [\n      \"warn\",\n      {\n        \"max\": 400\n      }\n    ],\n    \"no-caller\": \"warn\",\n    \"no-console\": \"warn\",\n    \"no-empty\": [\n      \"warn\",\n      {\n        \"allowEmptyCatch\": true\n      }\n    ],\n    \"no-eval\": \"warn\",\n    \"no-multiple-empty-lines\": [\"warn\"],\n    \"no-throw-literal\": \"warn\",\n    \"no-var\": \"warn\",\n    \"sort-imports\": [\n      \"warn\",\n      {\n        \"ignoreDeclarationSort\": true\n      }\n    ],\n    \"spaced-comment\": [\n      \"warn\",\n      \"always\",\n      {\n        \"markers\": [\"/\"]\n      }\n    ],\n    /* TODO: evaluate usage of these rules and fix issues as needed */\n    \"no-case-declarations\": \"off\",\n    \"no-fallthrough\": \"off\",\n    \"no-underscore-dangle\": \"off\",\n    \"@typescript-eslint/await-thenable\": \"off\",\n    \"@typescript-eslint/ban-types\": \"off\",\n    \"@typescript-eslint/no-empty-function\": \"off\",\n    \"@typescript-eslint/explicit-module-boundary-types\": \"off\",\n    \"@typescript-eslint/no-implied-eval\": \"off\",\n    \"@typescript-eslint/no-var-requires\": \"off\",\n    \"@typescript-eslint/no-unnecessary-type-assertion\": \"off\",\n    \"@typescript-eslint/no-unsafe-assignment\": \"off\",\n    \"@typescript-eslint/no-unsafe-call\": \"off\",\n    \"@typescript-eslint/no-unsafe-member-access\": \"off\",\n    \"@typescript-eslint/no-unsafe-return\": \"off\",\n    \"@typescript-eslint/no-unused-vars\": \"off\",\n    \"@typescript-eslint/prefer-regexp-exec\": \"off\",\n    \"@typescript-eslint/require-await\": \"off\",\n    \"@typescript-eslint/restrict-plus-operands\": \"off\",\n    \"@typescript-eslint/restrict-template-expressions\": \"off\",\n    \"@typescript-eslint/unbound-method\": \"off\",\n    \"@typescript-eslint/no-unsafe-argument\": \"off\",\n    \"prefer-const\": \"warn\",\n    \"prefer-rest-params\": \"warn\",\n    \"prefer-spread\": \"warn\",\n    \"@typescript-eslint/no-floating-promises\": \"warn\",\n    \"@typescript-eslint/no-inferrable-types\": \"off\",\n    \"@typescript-eslint/no-misused-promises\": [\n      \"warn\",\n      {\n        \"checksVoidReturn\": false\n      }\n    ],\n    \"@typescript-eslint/no-this-alias\": [\n      \"warn\",\n      {\n        \"allowedNames\": [\"_this\"]\n      }\n    ]\n  },\n  \"overrides\": [\n    {\n      \"files\": [\"**/*.spec.ts\"],\n      \"parserOptions\": {\n        \"project\": \"tsconfig.spec.json\"\n      },\n      \"rules\": {\n        \"import/no-extraneous-dependencies\": [\n          \"warn\",\n          {\n            \"devDependencies\": true,\n            \"packageDir\": \"./\"\n          }\n        ],\n        \"max-lines-per-function\": \"off\",\n        \"no-console\": \"off\"\n      }\n    },\n    {\n      \"files\": [\"./src/builder/**/*.ts\"],\n      \"excludedFiles\": [\n        \"./src/**/*.template.ts\",\n        \"./src/**/*.d.ts\",\n        \"**/*.spec.ts\",\n        \"test\"\n      ],\n      \"parserOptions\": {\n        \"project\": \"./tsconfig.builder.json\"\n      }\n    },\n    {\n      \"files\": [\"./src/library/**/*.ts\"],\n      \"excludedFiles\": [\n        \"./src/**/*.template.ts\",\n        \"./src/**/*.d.ts\",\n        \"**/*.spec.ts\",\n        \"test\",\n        \"./src/library/forms/**/*\",\n        \"./src/library/common/**/*\",\n        \"./src/library/platform/http/**/*\"\n      ],\n      \"parserOptions\": {\n        \"project\": \"tsconfig.library.json\"\n      }\n    },\n    {\n      \"files\": [\"schematics/internal/**/*.ts\"],\n      \"excludedFiles\": [],\n      \"parserOptions\": {\n        \"project\": \"tsconfig.internal-schematics.json\"\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": ".github/workflows/alpha.yml",
    "content": "name: CI\n\non:\n  push:\n    branches:\n      - alpha\nenv:\n  REPOSITORY_PATH: https://${{secrets.ACCESS_TOKEN}}@github.com/\njobs:\n  build:\n    runs-on: ubuntu-latest\n\n    steps:\n      - name: init\n        run: |\n          git config --global user.name \"${GITHUB_ACTOR}\"\n          git config --global user.email \"${GITHUB_ACTOR}@gmail.com\"\n      - name: pull-code\n        uses: actions/checkout@v2\n      - name: install-node\n        uses: actions/setup-node@v2\n        with:\n          node-version: 16.x\n          cache: \"npm\"\n      - name: install-dependencies\n        run: |\n          npm ci --legacy-peer-deps\n      - name: lint\n        run: |\n          npm run lint\n      - name: hook-code\n        run: |\n          npm run sync\n      - name: test\n        run: |\n          npm run test:ci\n      - name: build\n        run: |\n          npm run build\n      - id: publish\n        name: publish\n        uses: JS-DevTools/npm-publish@v3\n        if: ${{ github.repository_owner\t== 'wszgrcy' }}\n        with:\n          token: ${{ secrets.NPM_PUBLISH_TOKEN }}\n          package: ./dist/package.json\n          tag: alpha\n      - if: ${{ github.repository_owner\t== 'wszgrcy' && steps.publish.outputs.type  }}\n        run: |\n          echo \"[${{ steps.publish.outputs.type }}]版本已变更: ${{ steps.publish.outputs.old-version }} => ${{ steps.publish.outputs.version }}\"\n          git tag v${{steps.publish.outputs.version}}\n          git push origin v${{steps.publish.outputs.version}}\n"
  },
  {
    "path": ".github/workflows/default.yml",
    "content": "name: CI\n\non:\n  push:\n    branches:\n      - master\nenv:\n  REPOSITORY_PATH: https://${{secrets.ACCESS_TOKEN}}@github.com/\njobs:\n  build:\n    runs-on: ubuntu-latest\n\n    steps:\n      - name: init\n        run: |\n          git config --global user.name \"${GITHUB_ACTOR}\"\n          git config --global user.email \"${GITHUB_ACTOR}@gmail.com\"\n      - name: pull-code\n        uses: actions/checkout@v2\n      - name: install-node\n        uses: actions/setup-node@v2\n        with:\n          node-version: 16.x\n          cache: \"npm\"\n      - name: install-dependencies\n        run: |\n          npm ci --legacy-peer-deps\n      - name: lint\n        run: |\n          npm run lint\n      - name: hook-code\n        run: |\n          npm run sync\n      - name: test\n        run: |\n          npm run test:ci\n      - name: build\n        run: |\n          npm run build\n      - id: publish\n        name: publish\n        uses: JS-DevTools/npm-publish@v1\n        if: ${{ github.repository_owner\t== 'wszgrcy' }}\n        with:\n          token: ${{ secrets.NPM_PUBLISH_TOKEN }}\n          package: ./dist/package.json\n      - if: ${{ github.repository_owner\t== 'wszgrcy' && steps.publish.outputs.type  }}\n        run: |\n          echo \"[${{ steps.publish.outputs.type }}]Version changed: ${{ steps.publish.outputs.old-version }} => ${{ steps.publish.outputs.version }}\"\n          git tag v${{steps.publish.outputs.version}}\n          git push origin v${{steps.publish.outputs.version}}\n"
  },
  {
    "path": ".github/workflows/deploy.yml",
    "content": "name: deploy\n\non:\n  push:\n    branches:\n      - master\nenv:\n  REPOSITORY_PATH: https://${{secrets.ACCESS_TOKEN}}@github.com/\n  # GITHUB_TOKEN: ${{secrets.ACCESS_TOKEN}}\njobs:\n  build:\n    runs-on: ubuntu-latest\n    steps:\n      - name: init\n        run: |\n          git config --global user.name \"${GITHUB_ACTOR}\"\n          git config --global user.email \"${GITHUB_ACTOR}@gmail.com\"\n      - name: pull-code\n        uses: actions/checkout@v2\n      - name: install-node\n        uses: actions/setup-node@v2\n        with:\n          node-version: 16.x\n          cache: \"npm\"\n      - name: install-dependencies\n        run: |\n          npm ci --legacy-peer-deps\n      - name: hook-code\n        run: |\n          npm run sync\n      - name: build-docs\n        continue-on-error: true\n        run: |\n          npm run deploy\n          cp -rp docs/ ../dist\n          git branch gh-pages\n          git checkout gh-pages\n          rm -rf *\n          cp -rp ../dist/* .\n          cp ./index.html 404.html\n        env:\n          INPUT_TOKEN: ''\n      - name: tag\n        run: |\n          git status\n          git add -A\n          HUSKY=0 git commit -m 'build: 页面构建'\n          HUSKY=0 git push --force \"${REPOSITORY_PATH}${GITHUB_REPOSITORY}.git\" gh-pages\n          # git pull\n"
  },
  {
    "path": ".github/workflows/pull_request.yml",
    "content": "name: PR\n\non:\n  pull_request:\n    branches:\n      - master\n      - alpha\n\njobs:\n  pr-test:\n    runs-on: ubuntu-latest\n\n    steps:\n      - name: pull-code\n        uses: actions/checkout@v2\n      - name: install-node\n        uses: actions/setup-node@v2\n        with:\n          node-version: 16.x\n          cache: \"npm\"\n      - name: install-dependencies\n        run: |\n          npm ci --legacy-peer-deps\n      - name: lint\n        run: |\n          npm run lint\n      - name: hook-code\n        run: |\n          npm run sync\n      - name: test\n        run: |\n          npm run test:ci\n      - name: build\n        run: |\n          npm run build\n"
  },
  {
    "path": ".gitignore",
    "content": "node_modules*\ntest-project-host-hello-world-app-*\ndist\n__test-app\ncoverage-builder\nscript/startup-jasmine.js\n.temp-git\n.nyc_output\ndocs\ndeploy/api-doc"
  },
  {
    "path": ".husky/commit-msg",
    "content": "#!/bin/sh\n. \"$(dirname \"$0\")/_/husky.sh\"\n\nnpx --no-install commitlint --edit \"$1\"\n"
  },
  {
    "path": ".husky/pre-commit",
    "content": "#!/bin/sh\n. \"$(dirname \"$0\")/_/husky.sh\"\n\nnpx --no-install pretty-quick --staged\n"
  },
  {
    "path": ".npmrc",
    "content": "# registry =https://registry.npmmirror.com/"
  },
  {
    "path": ".nycrc.json",
    "content": "{\n  \"extension\": [\".ts\"],\n  \"exclude\": [\n    \"**/*.d.ts\",\n    \"**/*.js\",\n    \"**/*.spec.ts\",\n    \"startup-jasmine.js\",\n    \"test/**/*\",\n    \"src/builder/angular-internal/**/*\"\n  ],\n  \"reporter\": [\"html\", \"text\", \"json-summary\", \"json\"],\n  \"all\": false,\n  \"report-dir\": \"./docs/coverage\"\n}\n"
  },
  {
    "path": ".prettierignore",
    "content": "deploy"
  },
  {
    "path": ".prettierrc",
    "content": "{\n  \"singleQuote\": true\n}\n"
  },
  {
    "path": ".vscode/launch.json",
    "content": "{\n  // 使用 IntelliSense 了解相关属性。\n  // 悬停以查看现有属性的描述。\n  // 欲了解更多信息，请访问: https://go.microsoft.com/fwlink/?linkid=830387\n  \"version\": \"0.2.0\",\n  \"configurations\": [\n    {\n      \"name\": \"测试(jasmine)-library\",\n      \"type\": \"node\",\n      \"request\": \"launch\",\n      \"cwd\": \"${workspaceRoot}\",\n      \"runtimeExecutable\": \"npm\",\n      \"runtimeArgs\": [\"run-script\", \"test\", \"library\"],\n      \"port\": 7899\n    },\n    {\n      \"name\": \"测试(jasmine)-browser\",\n      \"type\": \"node\",\n      \"request\": \"launch\",\n      \"cwd\": \"${workspaceRoot}\",\n      \"runtimeExecutable\": \"npm\",\n      \"runtimeArgs\": [\"run-script\", \"test\", \"builder-dev\"],\n      \"port\": 7899\n    },\n    {\n      \"name\": \"测试(jasmine)-builder-prod\",\n      \"type\": \"node\",\n      \"request\": \"launch\",\n      \"cwd\": \"${workspaceRoot}\",\n      \"runtimeExecutable\": \"npm\",\n      \"runtimeArgs\": [\"run-script\", \"test\", \"builder-prod\"],\n      \"port\": 7899\n    },\n    {\n      \"name\": \"测试(jasmine)-browser-watch\",\n      \"type\": \"node\",\n      \"request\": \"launch\",\n      \"cwd\": \"${workspaceRoot}\",\n      \"runtimeExecutable\": \"npm\",\n      \"runtimeArgs\": [\"run-script\", \"test\", \"watch\"],\n      \"port\": 7899\n    }\n  ]\n}\n"
  },
  {
    "path": ".vscode/settings.json",
    "content": "{\n  \"typescript.tsdk\": \"node_modules/typescript/lib\",\n  \"editor.codeActionsOnSave\": {\n    \"source.fixAll.eslint\": \"explicit\",\n    \"source.fixAll.tslint\": \"never\"\n  }\n}\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2021 chen\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "commitlint.config.js",
    "content": "module.exports = {\n  extends: ['@commitlint/config-conventional'],\n};\n"
  },
  {
    "path": "deploy/doc/.gitignore",
    "content": "_site\n.jekyll-cache\n"
  },
  {
    "path": "deploy/doc/Gemfile",
    "content": "source \"https://mirrors.tuna.tsinghua.edu.cn/rubygems/\"\n# Hello! This is where you manage which Jekyll version is used to run.\n# When you want to use a different version, change it below, save the\n# file and run `bundle install`. Run Jekyll with `bundle exec`, like so:\n#\n#     bundle exec jekyll serve\n#\n# This will help ensure the proper Jekyll version is running.\n# Happy Jekylling!\n#gem \"jekyll\", \"~> 4.2.2\"\n# This is the default theme for new Jekyll sites. You may change this to anything you like.\ngem \"minima\", \"~> 2.5\"\n# If you want to use GitHub Pages, remove the \"gem \"jekyll\"\" above and\n# uncomment the line below. To upgrade, run `bundle update github-pages`.\ngem \"github-pages\", \"~> 226\", group: :jekyll_plugins\n\n# If you have any plugins, put them here!\ngroup :jekyll_plugins do\n  gem \"jekyll-feed\", \"~> 0.12\"\nend\n\n# Windows and JRuby does not include zoneinfo files, so bundle the tzinfo-data gem\n# and associated library.\nplatforms :mingw, :x64_mingw, :mswin, :jruby do\n  gem \"tzinfo\", \"~> 1.2\"\n  gem \"tzinfo-data\"\nend\n\n# Performance-booster for watching directories on Windows\ngem \"wdm\", \"~> 0.1.1\", :platforms => [:mingw, :x64_mingw, :mswin]\n\n# Lock `http_parser.rb` gem to `v0.6.x` on JRuby builds since newer versions of the gem\n# do not have a Java counterpart.\ngem \"http_parser.rb\", \"~> 0.6.0\", :platforms => [:jruby]\n"
  },
  {
    "path": "deploy/doc/_config.yml",
    "content": "theme: jekyll-theme-tactile\nbaseurl: /angular-miniprogram\n"
  },
  {
    "path": "deploy/doc/_includes/language-change.html",
    "content": "<div>\n  <button>\n    <a href=\"{{site.baseurl}}{{page.url| replace_first:page.dir,'/zh-Hans/' }}\"\n      >简体中文</a\n    >\n  </button>\n  <button>\n    <a href=\"{{site.baseurl}}{{page.url| replace_first:page.dir,'/en-US/' }}\"\n      >English</a\n    >\n  </button>\n</div>\n"
  },
  {
    "path": "deploy/doc/_layouts/home.html",
    "content": "<!DOCTYPE html>\n<html lang=\"{{ site.lang | default: \" en-US\" }}\">\n\n<head>\n  <meta charset='utf-8'>\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n  <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n  <link rel=\"stylesheet\" href=\"{{ '/assets/css/style.css?v=' | append: site.github.build_revision | relative_url }}\">\n  <link rel=\"stylesheet\" type=\"text/css\" href=\"{{ '/assets/css/print.css' | relative_url }}\" media=\"print\">\n\n  {% seo %}\n  {% include head-custom.html %}\n</head>\n\n<body>\n\n  <div id=\"container\">\n    <div class=\"inner\">\n      <nav class=\"flex\">\n        <div class=\"flex-1\"></div>\n        {% include language-change.html %}\n      </nav>\n      <header>\n        <h1 class=\"text-center\">{{ page.title | default: site.title | default: site.github.repository_name }}</h1>\n\n\n        <!-- <h2>{{ page.description | default: site.description | default: site.github.project_tagline }}</h2> -->\n\n      </header>\n\n      <hr>\n      <section id=\"main_content\">\n        {{ content }}\n      </section>\n\n      <footer>\n        {% if site.github.is_project_page %}\n        {{ site.title | default: site.github.repository_name }} is maintained by <a\n          href=\"{{ site.github.owner_url }}\">{{ site.github.owner_name }}</a><br>\n        {% endif %}\n        This page was generated by <a href=\"https://pages.github.com\">GitHub Pages</a>.\n      </footer>\n\n    </div>\n  </div>\n</body>\n\n</html>"
  },
  {
    "path": "deploy/doc/_layouts/post.html",
    "content": "<!DOCTYPE html>\n<html lang=\"{{ site.lang | default: \"en-US\" }}\">\n  <head>\n    <meta charset='utf-8'>\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n    <link rel=\"stylesheet\" href=\"{{ '/assets/css/style.css?v=' | append: site.github.build_revision | relative_url }}\">\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"{{ '/assets/css/print.css' | relative_url }}\" media=\"print\">\n\n{% seo %}\n    {% include head-custom.html %}\n  </head>\n  <body>\n    <div class=\"inner\">\n      <nav class=\"flex\">\n        <a href=\"{{site.baseurl}}/\">Home</a>\n        <div class=\"flex-1\"></div>\n        {% include language-change.html %}\n      </nav>\n      <header>\n        <h1>{{ page.title | default: site.title | default: site.github.repository_name }}</h1>\n     \n\n      <!-- <h2>{{ page.description | default: site.description | default: site.github.project_tagline }}</h2> -->\n\n    </header>\n      <section class=\"main_content\">{{ content }}</section>\n      <footer>\n        test is maintained by <a href=\"https://github.com/wszgrcy\">wszgrcy</a><br />\n\n        This page was generated by <a href=\"https://pages.github.com\">GitHub Pages</a>.\n      </footer>\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "deploy/doc/_layouts/redirect.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <meta http-equiv=\"Refresh\" content=\"0; url={{ site.baseurl }}/zh-Hans/index\" />\n\n    <title>Document</title>\n</head>\n<body>\n    \n</body>\n</html>"
  },
  {
    "path": "deploy/doc/_posts/2022-02-10-无时间测试.md",
    "content": "---\ntitle: \"无时间测试\"\nlayout: post\n---\n\n# 内容\n- 没有"
  },
  {
    "path": "deploy/doc/_posts/2022-02-10-测试.md",
    "content": "---\ntitle: \"测试\"\nlayout: post\n---\n\n# 内容\n"
  },
  {
    "path": "deploy/doc/assets/css/style.scss",
    "content": "---\n---\n\n@import '{{ site.theme }}';\n\n.action-line {\n  display: flex;\n  align-items: center;\n  justify-content: end;\n}\n\n.flex-1 {\n  flex: 1 1 0%;\n}\n.flex {\n  display: flex;\n}\n\n.text-center {\n  text-align: center;\n}\n\nblockquote p{\n  font-size: 0.8em;\n}"
  },
  {
    "path": "deploy/doc/en-US/attention.md",
    "content": "---\nlayout: post\ntitle: Attention\n---\n## Forbidden\n\n- All Dom operation\n\n## Import Change\n\n- Use `angular-miniprogram/common` replace `@angular/common`\n- Use `angular-miniprogram/common/http` replace `@angular/common/http`\n- Use `angular-miniprogram/forms` replace `@angular/forms`\n- Use `import { HttpClientModule, provideHttpClient } from 'angular-miniprogram'` replace `import { HttpClientModule, provideHttpClient } from '@angular/common/http'`\n\n## Attention\n\n- A event with prefix,like `bind`,`mut-bind`,etc,remove `:`,such as `bind:tap`=>`bindtap`\n  > Prefix in Angular resolve as `target`(window/document/body)\n- Miniprogram native component need set `schemas:[NO_ERRORS_SCHEMA]` in `NgModule`\n- if property operation not display on view, need to use `detectChanges`\n- Now, one file only allow one `@Component`\n\n## Compatible\n\n### Use Template\n\n- `createEmbeddedView` only allow in `structural directive`,or `TemplateRef`\n- `createEmbeddedView`need a `__templateName` property in `context` object,this property is miniprogram name\n- this name can be find in a private variable: `(this.templateRef as any)._declarationTContainer.localNames[0]`\n- only first `template variable` name can be use\n\n```ts\n@Directive({\n  selector: '[appStructural1]',\n})\nexport class Structural1Directive {\n  @Input() appStructural1: TemplateRef<any>;\n  @Input() appStructural1Name: string;\n  constructor(private viewContainerRef: ViewContainerRef) {}\n  ngOnInit(): void {\n    this.viewContainerRef.createEmbeddedView(this.appStructural1, {\n      __templateName: this.appStructural1Name,\n    });\n  }\n}\n\n```\n### Template Rename\n\n- `ng-template` name can't repeat in one Component, if exist, you can use mulit `template variable`\n- `<ng-template #name1 #name2></ng-template>` `#name1` is the alias name, and `#name2` is the repeat name\n- The first name will write in the template file, but all `template variable` can be use in Angular\n\n### Cross Component use Template\n\n- In same project, a Component use other Component `TemlateRef`,template name should follow this format`$$mp$$__self$$xxx`\n\n  > `same application`or`same library` is same project\n\n\n```html\n<ng-template #$$mp$$__self__$$self1> content </ng-template>\n<app-component-need-template\n  [templateRef]=\"$$mp$$__self__$$self1\"\n></app-component-need-template>\n\n```\n- transfer `TemplateRef` to Other library Component, template name should follow this format`$$mp$$TemplateScopeName$$xxx`, `TemplateScopeName`rule as follow:\n\n```ts\nimport { strings } from '@angular-devkit/core';\n//library library name\nexport function libraryTemplateScopeName(library: string) {\n  return strings.classify(library.replace(/[@/]/g, ''));\n}\n```\n\n- for example: `test-library`=>`TestLibrary`,`@my/library`=>`MyLibrary`\n\n\n```html\n<ng-template #$$mp$$TestLibrary$$first>\n  <app-component1></app-component1>\n</ng-template>\n\n<app-outside-template\n  [template]=\"$$mp$$TestLibrary$$first\"\n></app-outside-template>\n```\n\n### Unrealized\n- control flow\n> This part of the functionality currently appears to be dynamically generated, and to convert it to static, we can only use some native methods of the mini program, but it cannot be matched 1:1, so we haven't thought of a good method yet"
  },
  {
    "path": "deploy/doc/en-US/index.md",
    "content": "---\ntitle: 'angular-miniprogram'\nlayout: home\n---\n<h1 align=\"center\">Develop MiniProgram using Angular </h1>\n\n<p align=\"center\"> Use Angular Ecosystem as possible, \nreduce cross-platform costs</p>\n\n<p align=\"center\">\n  <a href=\"https://gitter.im/angular-miniprogram/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge\">\n    <img src=\"https://badges.gitter.im/angular-miniprogram/community.svg\" alt=\"gitter\" />\n  </a>&nbsp;\n    <a href=\"https://www.npmjs.com/package/angular-miniprogram\">\n    <img src=\"https://img.shields.io/npm/v/angular-miniprogram.svg?logo=npm&logoColor=fff&label=NPM+package&color=limegreen\" alt=\"angular-miniprogram on npm\" />\n  </a>&nbsp;\n    <a href=\"https://wszgrcy.github.io/angular-miniprogram/coverage/index.html\">\n    <img src=\"../assets/img/badge.svg\" alt=\"coverage\" />\n  </a>\n\n</p>\n\n\n<hr>\n\n## document\n\n- [Quickstart](quick-start)\n- [Attention](attention)\n- [MiniProgramFeature](miniprogram-feature)\n- [API](../api-doc)\n- [life-time](life-time)\n## Development Environment\n\n### Prerequisites\n\n- `Node.js` greater than 20\n- `@angular/cli` 17\n\n### hello-world\n\n- use this Template [https://github.com/wszgrcy/angular-miniprogram-template](https://github.com/wszgrcy/angular-miniprogram-template) or download\n- use `npm` install dependencies\n\n### Quickstart\n\n- [Quickstart](https://github.com/wszgrcy/angular-miniprogram/blob/master/quick-start-en.md)\n\n## Ecosystem\n\n- support all `Pipe` and `Service`\n- compatible support `Directive`(a little different from web)\n- one file only allow one `Component`\n\n## Support Platform\n\n| Platform Name | Run | Alias                   | comment                                                                                                                   |\n| ------------- | --- | ----------------------- | ------------------------------------------------------------------------------------------------------------------------- |\n| Wechat        | ✅  | Work Wechat             |                                                                                                                           |\n| bytedance     | ✅  |                         |                                                                                                                           |\n| jd            | ❌  |                         | no account                                                                                                                |\n| baidu         | ✅  |                         |                                                                                                                           |\n| Alipay        | ✅  | DingTalk,Alipay IoT,etc | can't compile in Prod, [see](https://forum.alipay.com/mini-app/post/65101060);can't use v2, while `slot` has some problem |\n| qq            | ✅  |                         | unknown error?but can work                                                                                                |\n| feishu        | ❌  |                         | like`bytedance`,but compile fail                                                                                          |\n"
  },
  {
    "path": "deploy/doc/en-US/life-time.md",
    "content": "---\nlayout: post\ntitle: Life Time\n---\n# Component(Component)\n\n- created\n  > Wait for link (miniprogram component is associated with ng component)\n- properties Change(first)\n  > link(init with ng auto)\n- attached\n- ready\n\n# Page(Page)\n\n- onLoad\n  > init and link\n- onShow(first)\n- onReady\n\n# Page(Component)\n\n- onLoad\n- onShow(first)\n- created\n  > init\n- attached\n  > link\n- onReady\n\n# Component(Component) in Page(Page)\n\n\n- ng-constructor(onLoad start)\n> ng page Component\n> init and link\n- ng-constructor(component)\n> ng component Component\n- ng-ngOnInit\n- ng-ngAfterContentInit\n- ng-ngOnInit(component)\n- ng-ngAfterContentInit(component)\n- ng-ngAfterViewInit(component)\n- ng-ngAfterViewInit\n- mp-created(component)\n- mp-attached(component)\n> sub component link(after created ,before created)\n- mp-onLoad(onLoad end)\n- mp-onShow\n- mp-onReady\n- mp-ready(component)\n"
  },
  {
    "path": "deploy/doc/en-US/miniprogram-feature.md",
    "content": "---\nlayout: post\ntitle: Miniprogram Feature\n---\n## Service\n\n- `ComponentFinderService`: get MiniProgram Component corresponding to Angular Component\n\n\n```ts  \nimport { ComponentFinderService } from 'angular-miniprogram';\n//...  \n{\n  constructor(private componentFinderService: ComponentFinderService) {}\n} \n```\n## token\n\n- `APP_TOKEN`: get App instance\n- `PAGE_TOKEN`: get MiniProgram Page corresponding to Angular Component\n\n\n```ts  \nimport {\n  APP_TOKEN,\n  PAGE_TOKEN,\n} from 'angular-miniprogram';\n//...  \n{\n    constructor(\n    @Inject(APP_TOKEN) appInstance: any,\n    @Inject(PAGE_TOKEN) pageInstance: any\n  ) {}\n} \n```\n## api\n\n- `pageStartup`: page entry\n\n```ts\nimport { pageStartup } from 'angular-miniprogram';\n//...\npageStartup(Page1Module, Page1Component);\n```\n- `componentRegistry`: component registry\n\n```ts\nimport { componentRegistry } from 'angular-miniprogram';\n//...\ncomponentRegistry(Component1Component);\n\n```\n## Static property on @Component\n\n- `static mpPageOptions`: like `Page(mpPageOptions)`\n  > use when Component as a Page\n\n```ts\n@Component({\n  selector: 'app-life-time',\n  templateUrl: './life-time.component.html',\n})\nexport class LifeTimePage implements OnInit {\n  static mpPageOptions: WechatMiniprogram.Page.Options<{}, {}> = {\n    onLoad: function (this: MiniProgramComponentInstance) {\n      console.log('mp-onLoad', this.__ngComponentInstance);\n    },\n    onShow: function () {\n      console.log('mp-onShow', this.__ngComponentInstance);\n    },\n    onReady: function (\n      this: WechatMiniprogram.Page.Instance<{}, {}> &\n        MiniProgramComponentInstance<LifeTimePage>\n    ) {\n      console.log('mp-onReady');\n    },\n  };\n//...\n}\n```\n\n- `static mpComponentOptions`: like `Component(mpComponentOptions)`\n  > use when Component as a Component or a Page but `pageStartup` with `{useComponent:true}`\n\n```ts\n@Component({\n  selector: 'app-life-time-component',\n  templateUrl: './life-time.component.html',\n  standalone: true,\n})\nexport class LifeTimeComponent implements OnInit {\n  static mpComponentOptions: WechatMiniprogram.Component.Options<{}, {}, {}> = {\n    lifetimes: {\n      created: function (this: MiniProgramComponentInstance) {\n        console.log('created(component)');\n      },\n      attached: function () {\n        console.log('attached(component)');\n      },\n      ready: function () {\n        console.log('ready(component)');\n      },\n      moved: function () {\n        console.log('moved(component)');\n      },\n      detached: function () {\n        console.log('detached(component)');\n      },\n      error: function () {\n        console.log('error(component)');\n      },\n    },\n    pageLifetimes: {\n      show: function () {\n        console.log('page-show(component)');\n      },\n      hide: function () {\n        console.log('page-hide(component)');\n      },\n      resize: function () {\n        console.log('page-resize(component)');\n      },\n    },\n  };\n//...\n}\n```\n\n## Global Variable\n\n- `miniProgramPlatform`: string, hint miniprogram platform(`wx`,`zfb`,`zj`,`bdzn`,`qq`,`dd`,etc)\n"
  },
  {
    "path": "deploy/doc/en-US/quick-start.md",
    "content": "---\nlayout: post\ntitle: Quick Start\n---\n## set Page pattern\n\n- Set output Page pattern in `angular.json`, same with `assets` field\n\n```json\n\"pages\": [\n  {\n    \"glob\": \"**/*.entry.ts\",\n    \"input\": \"./src/pages\",\n    \"output\": \"pages\"\n  }\n]\n```\n\n- This config is, in `src/pages` dir match `*.entry.ts` file, and output in`[outputDir]/pages` Dir\n\n## add a Page\n\n- Create code with the following structure\n\n```tree\n├── page1.component.html\n├── page1.component.scss\n├── page1.component.ts\n├── page1.entry.json\n├── page1.entry.ts\n└── page1.module.ts\n```\n\n- Create a `page1.entry.ts` file, add code as follow\n\n```ts\nimport { pageStartup } from 'angular-miniprogram';\nimport { Page1Component } from './page1.component';\nimport { Page1Module } from './page1.module';\n\npageStartup(Page1Module, Page1Component);\n```\n\n## set Component pattern\n\n- Set output Component pattern in `angular.json`, same with `assets` field\n\n```json\n\"components\":[\n         {\n           \"glob\": \"**/*.entry.ts\",\n           \"input\": \"./src/components\",\n           \"output\": \"components\"\n         }\n       ]\n```\n\n## add a Component\n\n- Create code with the following structure\n\n```tree\n├── component1.component.html\n├── component1.component.scss\n├── component1.component.ts\n├── component1.entry.json\n├── component1.entry.ts\n└── component1.module.ts\n```\n\n- Create a `component1.entry.ts` file, add code as follow\n\n```ts\nimport { componentRegistry } from 'angular-miniprogram';\nimport { Component1Component } from './component1.component';\n\ncomponentRegistry(Component1Component);\n```\n\n- This code is registry Component as a miniprogram Component\n- because of auto init, so use `Registry`\n"
  },
  {
    "path": "deploy/doc/index.md",
    "content": "---\nlayout: redirect\n---"
  },
  {
    "path": "deploy/doc/zh-Hans/attention.md",
    "content": "---\nlayout: post\ntitle: 注意事项\n---\n## 禁止使用\n\n- 一切 dom 行为\n- 带前缀的事件,如`bind`,`mut-bind`等,去掉冒号直接写,如事件`bind:tap`=>`bindtap`\n  > 前缀在 Angular 被解析为 target(window/document/body)\n\n## 引入变更\n\n- 使用`angular-miniprogram/common`代替`@angular/common`,\n- 使用`angular-miniprogram/common/http`代替`@angular/common/http`\n- 使用`angular-miniprogram/forms`代替`@angular/forms`\n- 使用`import { HttpClientModule, provideHttpClient } from 'angular-miniprogram'`代替`import { HttpClientModule, provideHttpClient } from '@angular/common/http'`\n\n## 注意\n\n- 小程序的原生组件需要在`NgModule`中设置 `schemas:[NO_ERRORS_SCHEMA]` ,规避检测\n- 元素属性赋值操作如果无法响应变更检测,使用`detectChanges`即可\n- 目前,一个文件内只能有一个组件存在\n\n## 兼容性支持\n\n### 模板使用\n\n- `createEmbeddedView`方法只能在结构型指令,或非结构型指令但是为模板引用`TemplateRef`中使用\n- 当使用`createEmbeddedView`进行插入时,需要在上下文中的对象传递`__templateName`属性,这个属性为小程序的实际对应模板名\n- 此模板名也可以访问`TemplateRef`实例的私有变量获得`(this.templateRef as any)._declarationTContainer.localNames[0]`\n\n```ts\n@Directive({\n  selector: '[appStructural1]',\n})\nexport class Structural1Directive {\n  @Input() appStructural1: TemplateRef<any>;\n  @Input() appStructural1Name: string;\n  constructor(private viewContainerRef: ViewContainerRef) {}\n  ngOnInit(): void {\n    this.viewContainerRef.createEmbeddedView(this.appStructural1, {\n      __templateName: this.appStructural1Name,\n    });\n  }\n}\n\n```\n### 模板重命名\n\n- 模板会在编译时编译为静态模板,所以可能存在重命名的情况,`如果`存在这种情况,可以使用多模板引用变量的方式实现\n- `<ng-template #name1 #name2></ng-template>` `#name2`为可能重复的那个命名,`#name1`为编译到模板中的名字\n- 第一个命名始终为模板的真实命名,但是所有的`模板引用变量`都可以引用\n\n### 跨组件调用模板\n\n- 在同一项目下,让其他组件接收到模板时,模板名定义需为`$$mp$$__self$$xxx`,这样就可以在同一项目下传递\n  > `同一application`或`同一library`下,都叫同一项目\n\n```html\n<ng-template #$$mp$$__self__$$self1> content </ng-template>\n<app-component-need-template\n  [templateRef]=\"$$mp$$__self__$$self1\"\n></app-component-need-template>\n\n```\n- 当需要给 library 组件中传入模板时,需要将模板名定义为`$$mp$$TemplateScopeName$$xxx`, `TemplateScopeName`生成规则如下\n\n```ts\nimport { strings } from '@angular-devkit/core';\n//library 为当前libary的名字\nexport function libraryTemplateScopeName(library: string) {\n  return strings.classify(library.replace(/[@/]/g, ''));\n}\n```\n\n- 如`test-library`库为`TestLibrary`,`@my/library`库为`MyLibrary`\n\n```html\n<ng-template #$$mp$$TestLibrary$$first>\n  <app-component1></app-component1>\n</ng-template>\n\n<app-outside-template\n  [template]=\"$$mp$$TestLibrary$$first\"\n></app-outside-template>\n```\n\n\n### 未实现\n- 控制流(control flow)\n> 这部分功能目前看起来是动态生成的,要转换为静态的就只能用小程序原生的一些方法,但是又没法1:1对应,所以暂时没想到好方法"
  },
  {
    "path": "deploy/doc/zh-Hans/index.md",
    "content": "---\ntitle: 'angular-miniprogram'\nlayout: home\n---\n\n<h1 align=\"center\">使用 Angular 开发小程序 </h1>\n\n<p align=\"center\">尽可能使用 Angular 已有生态,降低跨平台时所需成本</p>\n\n<p align=\"center\">\n  <a href=\"https://gitter.im/angular-miniprogram/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge\">\n    <img src=\"https://badges.gitter.im/angular-miniprogram/community.svg\" alt=\"gitter\" />\n  </a>&nbsp;\n    <a href=\"https://www.npmjs.com/package/angular-miniprogram\">\n    <img src=\"https://img.shields.io/npm/v/angular-miniprogram.svg?logo=npm&logoColor=fff&label=NPM+package&color=limegreen\" alt=\"angular-miniprogram on npm\" />\n  </a>&nbsp;\n    <a href=\"https://wszgrcy.github.io/angular-miniprogram/coverage/index.html\">\n    <img src=\"../assets/img/badge.svg\" alt=\"coverage\" />\n  </a>&nbsp;\n    <a href=\"javascript: void(0);\">\n    <img src=\"https://img.shields.io/badge/QQ%E7%BE%A4-287566685-brightgreen\" alt=\"coverage\" />\n  </a>\n\n</p>\n\n\n<hr>\n\n## 文档\n\n- [快速启动](quick-start)\n- [注意事项](attention)\n- [小程序特性](miniprogram-feature)\n- [API](../api-doc)\n- [生命周期](life-time)\n## 开发环境\n\n### 前提条件\n\n- `Node.js` 版本大于 20\n- `@angular/cli` 版本为 17\n\n### hello-world\n\n- 使用[https://github.com/wszgrcy/angular-miniprogram-template](https://github.com/wszgrcy/angular-miniprogram-template)模板或将此项目下载\n- 使用 npm 安装依赖\n\n### 快速启动\n\n- [快速启动](quick-start)\n\n## 生态\n\n- 支持`Angular`的全部服务及管道\n- 兼容性支持指令(与 Angular 不同)\n- 组件目前在一个文件中只能存在一个\n\n## 支持平台\n\n| 平台名    | 是否实现 | 关联               | 注释                                                                                                              |\n| --------- | -------- | ------------------ | ----------------------------------------------------------------------------------------------------------------- |\n| 微信      | ✅       | 企业微信           |                                                                                                                   |\n| 字节跳动  | ✅       |                    |                                                                                                                   |\n| 京东      | ❌       |                    | 没有账号                                                                                                          |\n| 百度智能  | ✅       |                    |                                                                                                                   |\n| 支付宝    | ✅       | 钉钉,支付宝 IoT 等 | 不能使用 Prod,问题[参见](https://forum.alipay.com/mini-app/post/65101060);不能使用基础库 2.0 编译,slot 有部分问题 |\n| qq 小程序 | ✅       |                    | (非微信变种),但是事件有未知报错?但是好像也不影响                                                                  |\n| 飞书      | ❌       |                    | 与字节跳动类似,但是编译有点问题                                                                                   |\n"
  },
  {
    "path": "deploy/doc/zh-Hans/life-time.md",
    "content": "---\nlayout: post\ntitle: 生命周期\n---\n# 组件(Component)\n\n- created\n  > 等待链接(小程序 Component 与 ng Component 关联)\n- properties 变更(第一次)\n  > 链接(ng自动初始化)\n- attached\n- ready\n\n# 页面(Page)\n\n- onLoad\n  > 初始化并链接\n- onShow(第一次)\n- onReady\n\n# 页面(Component)\n\n- onLoad\n- onShow(第一次)\n- created\n  > 初始化\n- attached\n  > 链接\n- onReady\n\n\n# 组件(Component)在页面(Page)中\n\n- ng-constructor(onLoad 开始)\n> 页面组件\n> 初始化并链接\n- ng-constructor(component)\n> 子组件\n- ng-ngOnInit\n- ng-ngAfterContentInit\n- ng-ngOnInit(component)\n- ng-ngAfterContentInit(component)\n- ng-ngAfterViewInit(component)\n- ng-ngAfterViewInit\n- mp-created(component)\n> 子组件链接(created之后,attached之前)\n- mp-attached(component)\n- mp-onLoad(onLoad 末尾)\n- mp-onShow\n- mp-onReady\n- mp-ready(component)\n"
  },
  {
    "path": "deploy/doc/zh-Hans/miniprogram-feature.md",
    "content": "---\nlayout: post\ntitle: 小程序特性\n---\n## 服务\n\n- 通过`ComponentFinderService`服务来查询当前 ng 组件实例对应的小程序组件\n\n\n```ts  \nimport { ComponentFinderService } from 'angular-miniprogram';\n//...  \n{\n  constructor(private componentFinderService: ComponentFinderService) {}\n} \n```\n## token\n\n- 通过`APP_TOKEN`可以获得 App 实例\n- 通过`PAGE_TOKEN`可以获得组件对应的小程序页面实例\n\n```ts  \nimport {\n  APP_TOKEN,\n  PAGE_TOKEN,\n} from 'angular-miniprogram';\n//...  \n{\n    constructor(\n    @Inject(APP_TOKEN) appInstance: any,\n    @Inject(PAGE_TOKEN) pageInstance: any\n  ) {}\n} \n```\n## api\n\n- `pageStartup`函数作为 page 的启动入口\n\n```ts\nimport { pageStartup } from 'angular-miniprogram';\n//...\npageStartup(Page1Module, Page1Component);\n```\n- `componentRegistry`组件注册\n\n```ts\nimport { componentRegistry } from 'angular-miniprogram';\n//...\ncomponentRegistry(Component1Component);\n\n```\n## 组件上静态属性\n\n- 在`Angular`@Component 组件中添加`static mpPageOptions`进行配置传参,与`Page({})`等同\n  > 当使用`pageStartup`函数时,使用此方法\n\n```ts\n@Component({\n  selector: 'app-life-time',\n  templateUrl: './life-time.component.html',\n})\nexport class LifeTimePage implements OnInit {\n  static mpPageOptions: WechatMiniprogram.Page.Options<{}, {}> = {\n    onLoad: function (this: MiniProgramComponentInstance) {\n      console.log('mp-onLoad', this.__ngComponentInstance);\n    },\n    onShow: function () {\n      console.log('mp-onShow', this.__ngComponentInstance);\n    },\n    onReady: function (\n      this: WechatMiniprogram.Page.Instance<{}, {}> &\n        MiniProgramComponentInstance<LifeTimePage>\n    ) {\n      console.log('mp-onReady');\n    },\n  };\n//...\n}\n```\n- 在`Angular`@Component 组件中添加`static mpComponentOptions`进行配置传参,与`Component({})`等同\n  > 当使用`componentRegistry`函数时或使用`pageStartup`函数,但是 options 为`{useComponent:true}`,使用此方法\n\n```ts\n@Component({\n  selector: 'app-life-time-component',\n  templateUrl: './life-time.component.html',\n  standalone: true,\n})\nexport class LifeTimeComponent implements OnInit {\n  static mpComponentOptions: WechatMiniprogram.Component.Options<{}, {}, {}> = {\n    lifetimes: {\n      created: function (this: MiniProgramComponentInstance) {\n        console.log('created(component)');\n      },\n      attached: function () {\n        console.log('attached(component)');\n      },\n      ready: function () {\n        console.log('ready(component)');\n      },\n      moved: function () {\n        console.log('moved(component)');\n      },\n      detached: function () {\n        console.log('detached(component)');\n      },\n      error: function () {\n        console.log('error(component)');\n      },\n    },\n    pageLifetimes: {\n      show: function () {\n        console.log('page-show(component)');\n      },\n      hide: function () {\n        console.log('page-hide(component)');\n      },\n      resize: function () {\n        console.log('page-resize(component)');\n      },\n    },\n  };\n//...\n}\n```\n\n## 全局变量\n\n- `miniProgramPlatform`为一个 string 类型的全局变量,指示当前小程序的运行平台(`wx`,`zfb`,`zj`,`bdzn`,`qq`,`dd`等)\n"
  },
  {
    "path": "deploy/doc/zh-Hans/quick-start.md",
    "content": "---\nlayout: post\ntitle: 快速启动\n---\n## 设置页面匹配\n\n- 在`angular.json`中设置要匹配的页面范围,匹配规则与 assets 相同\n\n```json\n\"pages\": [\n  {\n    \"glob\": \"**/*.entry.ts\",\n    \"input\": \"./src/pages\",\n    \"output\": \"pages\"\n  }\n]\n```\n\n- 上述配置为,在 src/pages 文件夹中,匹配`*.entry.ts`文件,并且编译完成导出在`[输出文件夹]/pages`文件夹中\n\n## 添加一个页面\n\n- 建立如下结构的代码\n\n```tree\n├── page1.component.html\n├── page1.component.scss\n├── page1.component.ts\n├── page1.entry.json\n├── page1.entry.ts\n└── page1.module.ts\n```\n\n- 新建一个`page1.entry.ts`,输入如下\n\n```ts\nimport { pageStartup } from 'angular-miniprogram';\nimport { Page1Component } from './page1.component';\nimport { Page1Module } from './page1.module';\n\npageStartup(Page1Module, Page1Component);\n```\n\n## 设置组件匹配\n\n- 在`angular.json`中设置要匹配的组件范围,匹配规则与 assets 相同\n\n```json\n\"components\":[\n         {\n           \"glob\": \"**/*.entry.ts\",\n           \"input\": \"./src/components\",\n           \"output\": \"components\"\n         }\n       ]\n```\n\n## 添加一个组件\n\n- 建立如下结构的代码\n\n```tree\n├── component1.component.html\n├── component1.component.scss\n├── component1.component.ts\n├── component1.entry.json\n├── component1.entry.ts\n└── component1.module.ts\n```\n\n- 新建一个`component1.entry.ts`,输入如下\n\n```ts\nimport { componentRegistry } from 'angular-miniprogram';\nimport { Component1Component } from './component1.component';\n\ncomponentRegistry(Component1Component);\n```\n\n- 上述代码为注册为将一个普通组件注册为小程序组件\n- 由于该组件的使用为自动初始化,所以使用了`注册`\n"
  },
  {
    "path": "jasmine.json",
    "content": "{\n  \"spec_dir\": \"src\",\n  \"spec_files\": [\"**/*.spec.ts\"],\n  \"failSpecWithNoExpectations\": true,\n  \"stopSpecOnExpectationFailure\": true,\n  \"stopOnSpecFailure\": true,\n  \"random\": false\n}\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"angular-miniprogram\",\n  \"version\": \"0.0.0\",\n  \"description\": \"\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"test:ci\": \"npm run build:library && npm run test:jasmine library&& npm run test:jasmine\",\n    \"test\": \"npm run test:jasmine\",\n    \"test:jasmine\": \"tsc -p ./script/tsconfig.startup-jasmine.json && node ./script/startup-jasmine.js\",\n    \"prebuild\": \"rimraf ./dist\",\n    \"build\": \" npm run build:library && npm run build:builder && npm run copy:assets && npm run build:karma\",\n    \"copy:assets\": \"cpx \\\"./src/builder/**/*.json\\\" ./dist/builder && cpx \\\"./src/builder/**/*.js\\\" ./dist/builder && cpx ./readme.md ./dist\",\n    \"build:library\": \"node ./script/start-build-library\",\n    \"build:builder\": \"tsx ./script/build.ts ./tsconfig.builder.json\",\n    \"build:karma\": \"tsx ./script/build.ts ./src/builder/karma/client/tsconfig.json && tsx ./script/build.ts ./src/builder/karma/plugin/tsconfig.json\",\n    \"prepare\": \"husky install\",\n    \"lint\": \"eslint --max-warnings 0 \\\"./**/*.ts\\\"\",\n    \"sync\": \"code-recycle ./script/package-sync.ts --cwd ./src/library\",\n    \"coverage\": \"nyc npm run test\",\n    \"typedoc\": \"typedoc\",\n    \"deploy\": \"npm run typedoc && npm run build:library && npm run test:jasmine library && npm run coverage-badge -- init && cpx \\\"./deploy/doc/**/*\\\" ./docs && cpx \\\"./deploy/api-doc/**/*\\\" ./docs/api-doc && npm run coverage && npm run coverage-badge -- success && cpx ./deploy/doc/assets/img/badge.svg ./docs/assets/img\",\n    \"coverage-badge\": \"tsx ./script/coverage-badge.ts\"\n  },\n  \"private\": true,\n  \"author\": \"wszgrcy\",\n  \"license\": \"MIT\",\n  \"devDependencies\": {\n    \"@angular-devkit/architect\": \"0.1703.1\",\n    \"@angular-devkit/build-angular\": \"17.3.1\",\n    \"@angular-devkit/core\": \"17.3.1\",\n    \"@angular-devkit/schematics\": \"17.3.1\",\n    \"@angular/compiler\": \"17.3.1\",\n    \"@angular/compiler-cli\": \"17.3.1\",\n    \"@angular/core\": \"17.3.1\",\n    \"@code-recycle/cli\": \"^1.3.10\",\n    \"@commitlint/cli\": \"^13.1.0\",\n    \"@commitlint/config-conventional\": \"^13.1.0\",\n    \"@ngtools/webpack\": \"17.3.1\",\n    \"@types/fs-extra\": \"11.0.4\",\n    \"@types/glob\": \"^7.2.0\",\n    \"@types/jasmine\": \"^3.7.7\",\n    \"@types/karma\": \"^6.3.3\",\n    \"@types/node\": \"20.11.30\",\n    \"@types/socket.io-client\": \"^3.0.0\",\n    \"@typescript-eslint/eslint-plugin\": \"^5.44.0\",\n    \"@typescript-eslint/parser\": \"^5.44.0\",\n    \"cpx\": \"^1.5.0\",\n    \"cross-env\": \"^7.0.3\",\n    \"cyia-ngx-devkit\": \"0.0.5\",\n    \"eslint\": \"^7.32.0\",\n    \"eslint-config-prettier\": \"^8.5.0\",\n    \"eslint-plugin-import\": \"^2.26.0\",\n    \"fs-extra\": \"11.2.0\",\n    \"glob\": \"^7.2.0\",\n    \"husky\": \"^7.0.0\",\n    \"jasmine\": \"5.1.0\",\n    \"jasmine-core\": \"5.1.2\",\n    \"karma\": \"^6.3.17\",\n    \"mini-types\": \"^0.1.7\",\n    \"miniprogram-api-typings\": \"^3.12.2\",\n    \"ng-packagr\": \"17.3.0\",\n    \"prettier\": \"3.2.5\",\n    \"pretty-quick\": \"4.0.0\",\n    \"queue-microtask\": \"^1.2.3\",\n    \"rimraf\": \"5.0.5\",\n    \"rxjs\": \"^7.8.1\",\n    \"static-injector\": \"4.0.2\",\n    \"ts-node\": \"^10.9.2\",\n    \"tslib\": \"2.6.2\",\n    \"tsx\": \"^4.7.1\",\n    \"typedoc\": \"^0.25.12\",\n    \"typescript\": \"5.4.2\",\n    \"weapp.socket.io\": \"^3.0.0\",\n    \"webpack\": \"5.90.3\",\n    \"zone.js\": \"0.14.4\"\n  },\n  \"dependencies\": {\n    \"cyia-code-util\": \"^1.8.0\",\n    \"nyc\": \"^15.1.0\",\n    \"webpack-bootstrap-assets-plugin\": \"^2.0.3\"\n  },\n  \"resolutions\": {}\n}\n"
  },
  {
    "path": "readme.md",
    "content": "<h1 align=\"center\">angular-miniprogram - 使用 Angular 开发小程序 </h1>\n\n<p align=\"center\">尽可能使用 Angular 已有生态,降低跨平台时所需成本</p>\n\n- 文档 [https://wszgrcy.github.io/angular-miniprogram/](https://wszgrcy.github.io/angular-miniprogram/)\n- document [https://wszgrcy.github.io/angular-miniprogram/en-US/](https://wszgrcy.github.io/angular-miniprogram/en-US/)\n"
  },
  {
    "path": "script/build-ng-package.ts",
    "content": "import * as path from 'path';\nimport { ngPackagrFactory } from '../src/builder/library/ng-packagr-factory';\nasync function main() {\n  let packagr = await ngPackagrFactory(\n    path.resolve(process.cwd(), './src/library/ng-package.json'),\n    path.resolve(process.cwd(), './tsconfig.library.json')\n  );\n\n  await packagr.build();\n}\nmain();\n"
  },
  {
    "path": "script/build.ts",
    "content": "import * as path from 'path';\nimport * as fs from 'fs';\nimport * as ts from 'typescript';\nimport { createTransformer } from 'static-injector/transform';\nexport function main() {\n  let inputPath = process.argv[2];\n  let filePath = path.resolve(process.cwd(), inputPath);\n  let tsConfigBuffer = fs.readFileSync(filePath);\n  let jsonSourceFile = ts.parseJsonText(filePath, tsConfigBuffer.toString());\n  let config = ts.parseJsonSourceFileConfigFileContent(\n    jsonSourceFile,\n    ts.sys,\n    path.dirname(filePath)\n  );\n  let program = ts.createProgram({\n    rootNames: config.fileNames,\n    options: config.options,\n    projectReferences: config.projectReferences,\n  });\n  let errors = [\n    ...program.getOptionsDiagnostics(),\n    ...program.getGlobalDiagnostics(),\n  ];\n  program.getSourceFiles().forEach((sf) => {\n    errors.push(\n      ...program.getSyntacticDiagnostics(sf),\n      ...program.getSemanticDiagnostics(sf)\n    );\n  });\n\n  if (errors.length) {\n    console.log(\n      ts.formatDiagnostics(errors, {\n        getCurrentDirectory: () => ts.sys.getCurrentDirectory(),\n        getNewLine: () => ts.sys.newLine,\n        getCanonicalFileName: (f: string) => f,\n      })\n    );\n    return;\n  }\n  let transformer = createTransformer(program);\n  program.emit(undefined, undefined, undefined, undefined, {\n    before: [transformer],\n  });\n}\n\nif (require.main === module) {\n  main();\n}\n"
  },
  {
    "path": "script/coverage-badge.ts",
    "content": "import * as fs from 'fs-extra';\nimport * as path from 'path';\nenum Status {\n  success = 'success',\n  init = 'init',\n}\nfunction main() {\n  let status = process.argv[2];\n  let outputPath = path.join(\n    process.cwd(),\n    'deploy',\n    'doc',\n    'assets',\n    'img',\n    'badge.svg'\n  );\n  let content: string;\n  if (status === Status.init) {\n    content = svgFailedGenerate();\n  } else if (status === Status.success) {\n    let file = fs\n      .readFileSync(\n        path.join(process.cwd(), 'docs', 'coverage', 'coverage-summary.json')\n      )\n      .toString();\n    let json = JSON.parse(file);\n    console.log(json.total.lines.pct);\n    content = svgGenerate(json.total.lines.pct + '%');\n  }\n  if (!fs.existsSync(path.dirname(outputPath))) {\n    fs.mkdirSync(path.dirname(outputPath), { recursive: true });\n  }\n  fs.writeFileSync(outputPath, content);\n}\nfunction svgGenerate(percent: any) {\n  return `\n    <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"90\" height=\"20\">\n      <defs>\n        <linearGradient id=\"workflow-fill\" x1=\"50%\" y1=\"0%\" x2=\"50%\" y2=\"100%\">\n          <stop stop-color=\"#444D56\" offset=\"0%\"></stop>\n          <stop stop-color=\"#24292E\" offset=\"100%\"></stop>\n        </linearGradient>\n        <linearGradient id=\"state-fill\" x1=\"50%\" y1=\"0%\" x2=\"50%\" y2=\"100%\">\n          <stop stop-color=\"#34D058\" offset=\"0%\"></stop>\n          <stop stop-color=\"#28A745\" offset=\"100%\"></stop>\n        </linearGradient>\n      </defs>\n      <g fill=\"none\" fill-rule=\"evenodd\">\n        <g font-family=\"&#39;DejaVu Sans&#39;,Verdana,Geneva,sans-serif\" font-size=\"11\">\n          <path id=\"workflow-bg\" d=\"M0,3 C0,1.3431 1.3552,0 3.02702703,0 L40,0 L40,20 L3.02702703,20 C1.3552,20 0,18.6569 0,17 L0,3 Z\" fill=\"url(#workflow-fill)\" fill-rule=\"nonzero\"></path>\n          <text fill=\"#010101\" fill-opacity=\".3\">\n            <tspan x=\"22.1981982\" y=\"15\">CI</tspan>\n          </text>\n          <text fill=\"#FFFFFF\">\n            <tspan x=\"22.1981982\" y=\"14\">CI</tspan>\n          </text>\n        </g>\n        <g transform=\"translate(40)\" font-family=\"&#39;DejaVu Sans&#39;,Verdana,Geneva,sans-serif\" font-size=\"11\">\n          <path d=\"M0 0h46.939C48.629 0 50 1.343 50 3v14c0 1.657-1.37 3-3.061 3H0V0z\" id=\"state-bg\" fill=\"url(#state-fill)\" fill-rule=\"nonzero\"></path>\n          <text fill=\"#010101\" fill-opacity=\".3\">\n            <tspan x=\"4\" y=\"15\">${percent}</tspan>\n          </text>\n          <text fill=\"#FFFFFF\">\n            <tspan x=\"4\" y=\"14\">${percent}</tspan>\n          </text>\n        </g>\n        <path fill=\"#959DA5\" d=\"M11 3c-3.868 0-7 3.132-7 7a6.996 6.996 0 0 0 4.786 6.641c.35.062.482-.148.482-.332 0-.166-.01-.718-.01-1.304-1.758.324-2.213-.429-2.353-.822-.079-.202-.42-.823-.717-.99-.245-.13-.595-.454-.01-.463.552-.009.946.508 1.077.718.63 1.058 1.636.76 2.039.577.061-.455.245-.761.446-.936-1.557-.175-3.185-.779-3.185-3.456 0-.762.271-1.392.718-1.882-.07-.175-.315-.892.07-1.855 0 0 .586-.183 1.925.718a6.5 6.5 0 0 1 1.75-.236 6.5 6.5 0 0 1 1.75.236c1.338-.91 1.925-.718 1.925-.718.385.963.14 1.68.07 1.855.446.49.717 1.112.717 1.882 0 2.686-1.636 3.28-3.194 3.456.254.219.473.639.473 1.295 0 .936-.009 1.689-.009 1.925 0 .184.131.402.481.332A7.011 7.011 0 0 0 18 10c0-3.867-3.133-7-7-7z\"></path>\n      </g>\n    </svg>\n    \n    `;\n}\nfunction svgFailedGenerate() {\n  return `\n  <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"83\" height=\"20\">\n    <defs>\n      <linearGradient id=\"workflow-fill\" x1=\"50%\" y1=\"0%\" x2=\"50%\" y2=\"100%\">\n        <stop stop-color=\"#444D56\" offset=\"0%\"></stop>\n        <stop stop-color=\"#24292E\" offset=\"100%\"></stop>\n      </linearGradient>\n      <linearGradient id=\"state-fill\" x1=\"50%\" y1=\"0%\" x2=\"50%\" y2=\"100%\">\n        <stop stop-color=\"#D73A49\" offset=\"0%\"></stop>\n        <stop stop-color=\"#CB2431\" offset=\"100%\"></stop>\n      </linearGradient>\n    </defs>\n    <g fill=\"none\" fill-rule=\"evenodd\">\n      <g font-family=\"&#39;DejaVu Sans&#39;,Verdana,Geneva,sans-serif\" font-size=\"11\">\n        <path id=\"workflow-bg\" d=\"M0,3 C0,1.3431 1.3552,0 3.02702703,0 L40,0 L40,20 L3.02702703,20 C1.3552,20 0,18.6569 0,17 L0,3 Z\" fill=\"url(#workflow-fill)\" fill-rule=\"nonzero\"></path>\n        <text fill=\"#010101\" fill-opacity=\".3\">\n          <tspan x=\"22.1981982\" y=\"15\">CI</tspan>\n        </text>\n        <text fill=\"#FFFFFF\">\n          <tspan x=\"22.1981982\" y=\"14\">CI</tspan>\n        </text>\n      </g>\n      <g transform=\"translate(40)\" font-family=\"&#39;DejaVu Sans&#39;,Verdana,Geneva,sans-serif\" font-size=\"11\">\n        <path d=\"M0 0h40.47C41.869 0 43 1.343 43 3v14c0 1.657-1.132 3-2.53 3H0V0z\" id=\"state-bg\" fill=\"url(#state-fill)\" fill-rule=\"nonzero\"></path>\n        <text fill=\"#010101\" fill-opacity=\".3\">\n          <tspan x=\"5\" y=\"15\">failing</tspan>\n        </text>\n        <text fill=\"#FFFFFF\">\n          <tspan x=\"5\" y=\"14\">failing</tspan>\n        </text>\n      </g>\n      <path fill=\"#959DA5\" d=\"M11 3c-3.868 0-7 3.132-7 7a6.996 6.996 0 0 0 4.786 6.641c.35.062.482-.148.482-.332 0-.166-.01-.718-.01-1.304-1.758.324-2.213-.429-2.353-.822-.079-.202-.42-.823-.717-.99-.245-.13-.595-.454-.01-.463.552-.009.946.508 1.077.718.63 1.058 1.636.76 2.039.577.061-.455.245-.761.446-.936-1.557-.175-3.185-.779-3.185-3.456 0-.762.271-1.392.718-1.882-.07-.175-.315-.892.07-1.855 0 0 .586-.183 1.925.718a6.5 6.5 0 0 1 1.75-.236 6.5 6.5 0 0 1 1.75.236c1.338-.91 1.925-.718 1.925-.718.385.963.14 1.68.07 1.855.446.49.717 1.112.717 1.882 0 2.686-1.636 3.28-3.194 3.456.254.219.473.639.473 1.295 0 .936-.009 1.689-.009 1.925 0 .184.131.402.481.332A7.011 7.011 0 0 0 18 10c0-3.867-3.133-7-7-7z\"></path>\n    </g>\n  </svg>\n  \n  `;\n}\nmain();\n"
  },
  {
    "path": "script/package-sync.ts",
    "content": "import {\n  type NodeQueryOption,\n  type ScriptFunction,\n  type FileQueryLayer,\n  completePromise,\n  fileBufferToString,\n  stringToFileBuffer,\n} from '@code-recycle/cli';\nconst templateName = `__templateName`;\n\nfunction getTemplateNameExpressionStr(templateRefName: string) {\n  return `(${templateRefName} as any)._declarationTContainer.localNames?(${templateRefName} as any)._declarationTContainer.localNames[0]:null`;\n}\nlet fn: ScriptFunction = async (util, rule, host, injector) => {\n  let path = util.path;\n\n  let data = await rule.os.gitClone(\n    'https://github.com/angular/angular.git',\n    [\n      '/packages/common',\n      '/packages/forms',\n      '!/packages/common/test',\n      '!/packages/forms/test',\n      '!**/*.bazel',\n      '!**/*spec.ts',\n      '!**/*.js',\n      '!**/*.md',\n    ],\n    'packages',\n    'branch',\n    '17.3.1'\n  );\n  let exclude = [\n    'forms/src/directives/default_value_accessor.ts',\n    'forms/src/directives/checkbox_value_accessor.ts',\n    // 'forms/src/directives/number_value_accessor.ts',\n    'forms/src/directives/radio_control_value_accessor.ts',\n    // 'forms/src/directives/range_value_accessor.ts',\n    // 'forms/src/directives/select_control_value_accessor.ts',\n    // 'forms/src/directives/select_multiple_control_value_accessor.ts',\n    'forms/src/directives.ts',\n    'forms/src/forms.ts',\n  ];\n\n  for (const key in data) {\n    if (exclude.includes(key)) {\n      continue;\n    }\n    let buffer = data[key];\n    if (key.startsWith('common')) {\n      let content = fileBufferToString(buffer).replace(\n        /@angular\\/common/g,\n        `angular-miniprogram/common`\n      );\n      buffer = stringToFileBuffer(content);\n    }\n    await completePromise(host.write(path.normalize(key), buffer));\n  }\n  let list = await util.changeList([\n    {\n      path: './common/src/directives/ng_for_of.ts',\n      list: [\n        {\n          query: `Constructor>CloseParenToken`,\n          insertBefore: true,\n          replace: `public ${templateName}:string`,\n        },\n        {\n          query: `NewExpression:like(new NgForOfContext)>CloseParenToken`,\n          insertBefore: true,\n          replace: `,${getTemplateNameExpressionStr('this._template')}`,\n        },\n      ],\n    },\n    {\n      path: './common/src/directives/ng_if.ts',\n      list: [\n        {\n          query: `IfStatement:has(>PrefixUnaryExpression:like(this._thenViewRef) ) CallExpression:like(this._viewContainer.createEmbeddedView)>OpenParenToken+*::children(2)`,\n          replace: `{...{{''|ctxValue}},${templateName}:${getTemplateNameExpressionStr(\n            'this._thenTemplateRef'\n          )}}`,\n        },\n        {\n          query: `IfStatement:has(>PrefixUnaryExpression:like(this._elseViewRef) ) CallExpression:like(this._viewContainer.createEmbeddedView)>OpenParenToken+*::children(2)`,\n          replace: `{...{{''|ctxValue}},${templateName}:${getTemplateNameExpressionStr(\n            'this._elseTemplateRef'\n          )}}`,\n        },\n        {\n          query: `ClassDeclaration:has(>Identifier[value=NgIfContext])>CloseBraceToken`,\n          insertBefore: true,\n          replace: `public ${templateName}!:string`,\n        },\n      ],\n    },\n    {\n      path: `./common/src/directives/ng_switch.ts`,\n      list: [\n        {\n          query: `CallExpression:like(this._viewContainerRef.createEmbeddedView)>CloseParenToken`,\n          insertBefore: true,\n          replace: `,{${templateName}:${getTemplateNameExpressionStr(\n            'this._templateRef'\n          )}}`,\n        },\n      ],\n    },\n    {\n      path: `./common/src/directives/ng_template_outlet.ts`,\n      list: [\n        {\n          query: `CallExpression:like(viewContainerRef.createEmbeddedView)>OpenParenToken+*::children(2)`,\n          replace: `{...{{''|ctxValue}},${templateName}:${getTemplateNameExpressionStr(\n            'this.ngTemplateOutlet'\n          )}}as any`,\n        },\n      ],\n    },\n    {\n      path: `./common/src/common.ts`,\n      list: [\n        {\n          query: `ExportDeclaration:has(StringLiteral[value*=i18n])`,\n          delete: true,\n          multi: true,\n        },\n        {\n          query: `ExportSpecifier[value^=I18n]:use(*,*+*)`,\n          delete: true,\n          multi: true,\n        },\n        {\n          query: `ExportSpecifier[value=NgComponentOutlet]:use(*,*+*)`,\n          delete: true,\n          multi: true,\n        },\n      ],\n    },\n    {\n      path: `./common/src/pipes/index.ts`,\n      list: [\n        {\n          query: `ImportDeclaration:has(Identifier[value^=I18n])`,\n          multi: true,\n          delete: true,\n        },\n        {\n          query: `ExportSpecifier[value^=I18n]:use(*,*+*)`,\n          delete: true,\n          multi: true,\n        },\n        {\n          query: `ArrayLiteralExpression Identifier[value^=I18n]:use(*,*+*)`,\n          delete: true,\n          multi: true,\n        },\n      ],\n    },\n    {\n      path: `./common/src/directives/index.ts`,\n      list: [\n        {\n          query: `ImportDeclaration:has(Identifier[value=NgComponentOutlet])`,\n          multi: true,\n          delete: true,\n        },\n        {\n          query: `ExportSpecifier[value=NgComponentOutlet]:use(*,*+*)`,\n          delete: true,\n          multi: true,\n        },\n        {\n          query: `ArrayLiteralExpression Identifier[value=NgComponentOutlet]:use(*,*+*)`,\n          delete: true,\n          multi: true,\n        },\n      ],\n    },\n  ]);\n  await util.updateChangeList(list);\n};\nexport default fn;\n"
  },
  {
    "path": "script/registry-transformer.js",
    "content": "let { register } = require('ts-node');\nlet path = require('path');\nlet { createTransformer } = require('static-injector/transform');\nmodule.exports = function registerTsNode() {\n  register({\n    project: path.resolve(__dirname, '../tsconfig.spec.json'),\n    transformers: (program) => {\n      const transformer = createTransformer(program);\n      return {\n        before: [transformer],\n      };\n    },\n  });\n};\n"
  },
  {
    "path": "script/schema-merge.ts",
    "content": "import * as fs from 'fs';\nimport * as path from 'path';\nfunction merge(origin: string, additional: string, output: string) {\n  origin = require.resolve(origin);\n  additional = require.resolve(additional);\n  let originFile = JSON.parse(fs.readFileSync(origin).toString());\n  let additionalFile = JSON.parse(fs.readFileSync(additional).toString());\n  let outputAbsolutePath = path.resolve(path.dirname(additional), output);\n  originFile['properties'] = {\n    ...additionalFile['properties'],\n    ...originFile['properties'],\n  };\n  originFile['definitions'] = {\n    ...originFile['definitions'],\n    ...additionalFile['definitions'],\n  };\n  fs.writeFileSync(\n    outputAbsolutePath,\n    JSON.stringify(originFile, undefined, 2)\n  );\n}\nfunction main() {\n  merge(\n    '@angular-devkit/build-angular/src/browser/schema.json',\n    '../src/builder/application/schema.base.json',\n    './schema.json'\n  );\n}\nmain();\n"
  },
  {
    "path": "script/start-build-library.js",
    "content": "let registerTsNode = require('./registry-transformer');\nregisterTsNode();\nrequire('./build-ng-package');\n"
  },
  {
    "path": "script/startup-jasmine.ts",
    "content": "import { register } from 'ts-node';\nimport { createTransformer } from 'static-injector/transform';\nimport Jasmine from 'jasmine';\nimport path from 'path';\n\nregister({\n  project: path.resolve(__dirname, '../tsconfig.spec.json'),\n  transformers: (program) => {\n    const transformer = createTransformer(program);\n    return {\n      before: [transformer],\n    };\n  },\n  logError: true,\n});\nlet jasmineInstance = new Jasmine();\nlet args = process.argv.slice(2) || [];\njasmineInstance.loadConfigFile(path.resolve(__dirname, '../jasmine.json'));\njasmineInstance.execute(undefined, args[0] || undefined);\n"
  },
  {
    "path": "script/tsconfig.json",
    "content": "{\n  \"extends\": \"../tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"esModuleInterop\": true,\n    \"downlevelIteration\": true\n  },\n  \"include\": [\"**/*.ts\"],\n  \"exclude\": []\n}\n"
  },
  {
    "path": "script/tsconfig.startup-jasmine.json",
    "content": "{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": { \"skipLibCheck\": true, \"outDir\": \".\" },\n  \"files\": [\"./startup-jasmine.ts\"],\n  \"include\": [],\n  \"exclude\": []\n}\n"
  },
  {
    "path": "src/builder/angular-internal/ast.type.ts",
    "content": "import type {\n  TmplAstBoundAttribute,\n  TmplAstBoundEvent,\n  TmplAstBoundText,\n  TmplAstContent,\n  TmplAstElement,\n  TmplAstIcu,\n  TmplAstNode,\n  TmplAstRecursiveVisitor,\n  TmplAstReference,\n  TmplAstTemplate,\n  TmplAstText,\n  TmplAstTextAttribute,\n  TmplAstVariable,\n} from '@angular/compiler';\n\nexport type Element = TmplAstElement;\nexport type Template = TmplAstTemplate;\n\nexport type Content = TmplAstContent;\nexport type Variable = TmplAstVariable;\nexport type Reference = TmplAstReference;\nexport type TextAttribute = TmplAstTextAttribute;\nexport type BoundAttribute = Parameters<\n  TmplAstRecursiveVisitor['visitBoundAttribute']\n>[0];\nexport type BoundEvent = TmplAstBoundEvent;\nexport type Text = TmplAstText;\nexport type BoundText = TmplAstBoundText;\nexport type Icu = TmplAstIcu;\nexport type Node = TmplAstNode;\n"
  },
  {
    "path": "src/builder/angular-internal/selector.ts",
    "content": "/* eslint-disable @typescript-eslint/no-this-alias */\n/* eslint-disable @typescript-eslint/no-explicit-any */\n/* eslint-disable no-useless-escape */\n/* eslint-disable no-irregular-whitespace */\n/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nconst _SELECTOR_REGEXP = new RegExp(\n  '(\\\\:not\\\\()|' + // 1: \":not(\"\n    '(([\\\\.\\\\#]?)[-\\\\w]+)|' + // 2: \"tag\"; 3: \".\"/\"#\";\n    // \"-\" should appear first in the regexp below as FF31 parses \"[.-\\w]\" as a range\n    // 4: attribute; 5: attribute_string; 6: attribute_value\n    '(?:\\\\[([-.\\\\w*\\\\\\\\$]+)(?:=([\"\\']?)([^\\\\]\"\\']*)\\\\5)?\\\\])|' + // \"[name]\", \"[name=value]\",\n    // \"[name=\"value\"]\",\n    // \"[name='value']\"\n    '(\\\\))|' + // 7: \")\"\n    '(\\\\s*,\\\\s*)', // 8: \",\"\n  'g'\n);\n\n/**\n * These offsets should match the match-groups in `_SELECTOR_REGEXP` offsets.\n */\nconst enum SelectorRegexp {\n  ALL = 0, // The whole match\n  NOT = 1,\n  TAG = 2,\n  PREFIX = 3,\n  ATTRIBUTE = 4,\n  ATTRIBUTE_STRING = 5,\n  ATTRIBUTE_VALUE = 6,\n  NOT_END = 7,\n  SEPARATOR = 8,\n}\n/**\n * A css selector contains an element name,\n * css classes and attribute/value pairs with the purpose\n * of selecting subsets out of them.\n */\nexport class CssSelector {\n  element: string | null = null;\n  classNames: string[] = [];\n  /**\n   * The selectors are encoded in pairs where:\n   * - even locations are attribute names\n   * - odd locations are attribute values.\n   *\n   * Example:\n   * Selector: `[key1=value1][key2]` would parse to:\n   * ```\n   * ['key1', 'value1', 'key2', '']\n   * ```\n   */\n  attrs: string[] = [];\n  notSelectors: CssSelector[] = [];\n\n  static parse(selector: string): CssSelector[] {\n    const results: CssSelector[] = [];\n    const _addResult = (res: CssSelector[], cssSel: CssSelector) => {\n      if (\n        cssSel.notSelectors.length > 0 &&\n        !cssSel.element &&\n        cssSel.classNames.length == 0 &&\n        cssSel.attrs.length == 0\n      ) {\n        cssSel.element = '*';\n      }\n      res.push(cssSel);\n    };\n    let cssSelector = new CssSelector();\n    let match: string[] | null;\n    let current = cssSelector;\n    let inNot = false;\n    _SELECTOR_REGEXP.lastIndex = 0;\n    // eslint-disable-next-line no-cond-assign\n    while ((match = _SELECTOR_REGEXP.exec(selector))) {\n      if (match[SelectorRegexp.NOT]) {\n        if (inNot) {\n          throw new Error('Nesting :not in a selector is not allowed');\n        }\n        inNot = true;\n        current = new CssSelector();\n        cssSelector.notSelectors.push(current);\n      }\n      const tag = match[SelectorRegexp.TAG];\n      if (tag) {\n        const prefix = match[SelectorRegexp.PREFIX];\n        if (prefix === '#') {\n          // #hash\n          current.addAttribute('id', tag.substr(1));\n        } else if (prefix === '.') {\n          // Class\n          current.addClassName(tag.substr(1));\n        } else {\n          // Element\n          current.setElement(tag);\n        }\n      }\n      const attribute = match[SelectorRegexp.ATTRIBUTE];\n\n      if (attribute) {\n        current.addAttribute(\n          current.unescapeAttribute(attribute),\n          match[SelectorRegexp.ATTRIBUTE_VALUE]\n        );\n      }\n      if (match[SelectorRegexp.NOT_END]) {\n        inNot = false;\n        current = cssSelector;\n      }\n      if (match[SelectorRegexp.SEPARATOR]) {\n        if (inNot) {\n          throw new Error('Multiple selectors in :not are not supported');\n        }\n        _addResult(results, cssSelector);\n        cssSelector = current = new CssSelector();\n      }\n    }\n    _addResult(results, cssSelector);\n    return results;\n  }\n\n  /**\n   * Unescape `\\$` sequences from the CSS attribute selector.\n   *\n   * This is needed because `$` can have a special meaning in CSS selectors,\n   * but we might want to match an attribute that contains `$`.\n   * [MDN web link for more\n   * info](https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors).\n   * @param attr the attribute to unescape.\n   * @returns the unescaped string.\n   */\n  unescapeAttribute(attr: string): string {\n    let result = '';\n    let escaping = false;\n    for (let i = 0; i < attr.length; i++) {\n      const char = attr.charAt(i);\n      if (char === '\\\\') {\n        escaping = true;\n        continue;\n      }\n      if (char === '$' && !escaping) {\n        throw new Error(\n          `Error in attribute selector \"${attr}\". ` +\n            `Unescaped \"$\" is not supported. Please escape with \"\\\\$\".`\n        );\n      }\n      escaping = false;\n      result += char;\n    }\n    return result;\n  }\n\n  /**\n   * Escape `$` sequences from the CSS attribute selector.\n   *\n   * This is needed because `$` can have a special meaning in CSS selectors,\n   * with this method we are escaping `$` with `\\$'.\n   * [MDN web link for more\n   * info](https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors).\n   * @param attr the attribute to escape.\n   * @returns the escaped string.\n   */\n  escapeAttribute(attr: string): string {\n    return attr.replace(/\\\\/g, '\\\\\\\\').replace(/\\$/g, '\\\\$');\n  }\n\n  hasElementSelector(): boolean {\n    return !!this.element;\n  }\n\n  setElement(element: string | null = null) {\n    this.element = element;\n  }\n\n  addAttribute(name: string, value: string = '') {\n    this.attrs.push(name, (value && value.toLowerCase()) || '');\n  }\n\n  addClassName(name: string) {\n    this.classNames.push(name.toLowerCase());\n  }\n\n  toString(): string {\n    let res: string = this.element || '';\n    if (this.classNames) {\n      this.classNames.forEach((klass) => (res += `.${klass}`));\n    }\n    if (this.attrs) {\n      for (let i = 0; i < this.attrs.length; i += 2) {\n        const name = this.escapeAttribute(this.attrs[i]);\n        const value = this.attrs[i + 1];\n        res += `[${name}${value ? '=' + value : ''}]`;\n      }\n    }\n    this.notSelectors.forEach((notSelector) => (res += `:not(${notSelector})`));\n    return res;\n  }\n}\n\n/**\n * Reads a list of CssSelectors and allows to calculate which ones\n * are contained in a given CssSelector.\n */\nexport class SelectorMatcher<T = any> {\n  static createNotMatcher(notSelectors: CssSelector[]): SelectorMatcher<null> {\n    const notMatcher = new SelectorMatcher<null>();\n    notMatcher.addSelectables(notSelectors, null);\n    return notMatcher;\n  }\n\n  private _elementMap = new Map<string, SelectorContext<T>[]>();\n  private _elementPartialMap = new Map<string, SelectorMatcher<T>>();\n  private _classMap = new Map<string, SelectorContext<T>[]>();\n  private _classPartialMap = new Map<string, SelectorMatcher<T>>();\n  private _attrValueMap = new Map<string, Map<string, SelectorContext<T>[]>>();\n  private _attrValuePartialMap = new Map<\n    string,\n    Map<string, SelectorMatcher<T>>\n  >();\n  private _listContexts: SelectorListContext[] = [];\n\n  addSelectables(cssSelectors: CssSelector[], callbackCtxt?: T) {\n    let listContext: SelectorListContext = null!;\n    if (cssSelectors.length > 1) {\n      listContext = new SelectorListContext(cssSelectors);\n      this._listContexts.push(listContext);\n    }\n    for (let i = 0; i < cssSelectors.length; i++) {\n      this._addSelectable(cssSelectors[i], callbackCtxt as T, listContext);\n    }\n  }\n\n  /**\n   * Add an object that can be found later on by calling `match`.\n   * @param cssSelector A css selector\n   * @param callbackCtxt An opaque object that will be given to the callback of the `match` function\n   */\n  private _addSelectable(\n    cssSelector: CssSelector,\n    callbackCtxt: T,\n    listContext: SelectorListContext\n  ) {\n    let matcher: SelectorMatcher<T> = this;\n    const element = cssSelector.element;\n    const classNames = cssSelector.classNames;\n    const attrs = cssSelector.attrs;\n    const selectable = new SelectorContext(\n      cssSelector,\n      callbackCtxt,\n      listContext\n    );\n\n    if (element) {\n      const isTerminal = attrs.length === 0 && classNames.length === 0;\n      if (isTerminal) {\n        this._addTerminal(matcher._elementMap, element, selectable);\n      } else {\n        matcher = this._addPartial(matcher._elementPartialMap, element);\n      }\n    }\n\n    if (classNames) {\n      for (let i = 0; i < classNames.length; i++) {\n        const isTerminal = attrs.length === 0 && i === classNames.length - 1;\n        const className = classNames[i];\n        if (isTerminal) {\n          this._addTerminal(matcher._classMap, className, selectable);\n        } else {\n          matcher = this._addPartial(matcher._classPartialMap, className);\n        }\n      }\n    }\n\n    if (attrs) {\n      for (let i = 0; i < attrs.length; i += 2) {\n        const isTerminal = i === attrs.length - 2;\n        const name = attrs[i];\n        const value = attrs[i + 1];\n        if (isTerminal) {\n          const terminalMap = matcher._attrValueMap;\n          let terminalValuesMap = terminalMap.get(name);\n          if (!terminalValuesMap) {\n            terminalValuesMap = new Map<string, SelectorContext<T>[]>();\n            terminalMap.set(name, terminalValuesMap);\n          }\n          this._addTerminal(terminalValuesMap, value, selectable);\n        } else {\n          const partialMap = matcher._attrValuePartialMap;\n          let partialValuesMap = partialMap.get(name);\n          if (!partialValuesMap) {\n            partialValuesMap = new Map<string, SelectorMatcher<T>>();\n            partialMap.set(name, partialValuesMap);\n          }\n          matcher = this._addPartial(partialValuesMap, value);\n        }\n      }\n    }\n  }\n\n  private _addTerminal(\n    map: Map<string, SelectorContext<T>[]>,\n    name: string,\n    selectable: SelectorContext<T>\n  ) {\n    let terminalList = map.get(name);\n    if (!terminalList) {\n      terminalList = [];\n      map.set(name, terminalList);\n    }\n    terminalList.push(selectable);\n  }\n\n  private _addPartial(\n    map: Map<string, SelectorMatcher<T>>,\n    name: string\n  ): SelectorMatcher<T> {\n    let matcher = map.get(name);\n    if (!matcher) {\n      matcher = new SelectorMatcher<T>();\n      map.set(name, matcher);\n    }\n    return matcher;\n  }\n\n  /**\n   * Find the objects that have been added via `addSelectable`\n   * whose css selector is contained in the given css selector.\n   * @param cssSelector A css selector\n   * @param matchedCallback This callback will be called with the object handed into `addSelectable`\n   * @return boolean true if a match was found\n   */\n  match(\n    cssSelector: CssSelector,\n    matchedCallback: ((c: CssSelector, a: T) => void) | null\n  ): boolean {\n    let result = false;\n    const element = cssSelector.element!;\n    const classNames = cssSelector.classNames;\n    const attrs = cssSelector.attrs;\n\n    for (let i = 0; i < this._listContexts.length; i++) {\n      this._listContexts[i].alreadyMatched = false;\n    }\n\n    result =\n      this._matchTerminal(\n        this._elementMap,\n        element,\n        cssSelector,\n        matchedCallback\n      ) || result;\n    result =\n      this._matchPartial(\n        this._elementPartialMap,\n        element,\n        cssSelector,\n        matchedCallback\n      ) || result;\n\n    if (classNames) {\n      for (let i = 0; i < classNames.length; i++) {\n        const className = classNames[i];\n        result =\n          this._matchTerminal(\n            this._classMap,\n            className,\n            cssSelector,\n            matchedCallback\n          ) || result;\n        result =\n          this._matchPartial(\n            this._classPartialMap,\n            className,\n            cssSelector,\n            matchedCallback\n          ) || result;\n      }\n    }\n\n    if (attrs) {\n      for (let i = 0; i < attrs.length; i += 2) {\n        const name = attrs[i];\n        const value = attrs[i + 1];\n\n        const terminalValuesMap = this._attrValueMap.get(name)!;\n        if (value) {\n          result =\n            this._matchTerminal(\n              terminalValuesMap,\n              '',\n              cssSelector,\n              matchedCallback\n            ) || result;\n        }\n        result =\n          this._matchTerminal(\n            terminalValuesMap,\n            value,\n            cssSelector,\n            matchedCallback\n          ) || result;\n\n        const partialValuesMap = this._attrValuePartialMap.get(name)!;\n        if (value) {\n          result =\n            this._matchPartial(\n              partialValuesMap,\n              '',\n              cssSelector,\n              matchedCallback\n            ) || result;\n        }\n        result =\n          this._matchPartial(\n            partialValuesMap,\n            value,\n            cssSelector,\n            matchedCallback\n          ) || result;\n      }\n    }\n    return result;\n  }\n\n  /** @internal */\n  _matchTerminal(\n    map: Map<string, SelectorContext<T>[]>,\n    name: string,\n    cssSelector: CssSelector,\n    matchedCallback: ((c: CssSelector, a: any) => void) | null\n  ): boolean {\n    if (!map || typeof name !== 'string') {\n      return false;\n    }\n\n    let selectables: SelectorContext<T>[] = map.get(name) || [];\n    const starSelectables: SelectorContext<T>[] = map.get('*')!;\n    if (starSelectables) {\n      selectables = selectables.concat(starSelectables);\n    }\n    if (selectables.length === 0) {\n      return false;\n    }\n    let selectable: SelectorContext<T>;\n    let result = false;\n    for (let i = 0; i < selectables.length; i++) {\n      selectable = selectables[i];\n      result = selectable.finalize(cssSelector, matchedCallback) || result;\n    }\n    return result;\n  }\n\n  /** @internal */\n  _matchPartial(\n    map: Map<string, SelectorMatcher<T>>,\n    name: string,\n    cssSelector: CssSelector,\n    matchedCallback: ((c: CssSelector, a: any) => void) | null\n  ): boolean {\n    if (!map || typeof name !== 'string') {\n      return false;\n    }\n\n    const nestedSelector = map.get(name);\n    if (!nestedSelector) {\n      return false;\n    }\n    // TODO(perf): get rid of recursion and measure again\n    // TODO(perf): don't pass the whole selector into the recursion,\n    // but only the not processed parts\n    return nestedSelector.match(cssSelector, matchedCallback);\n  }\n}\n\nexport class SelectorListContext {\n  alreadyMatched: boolean = false;\n\n  constructor(public selectors: CssSelector[]) {}\n}\n\n// Store context to pass back selector and context when a selector is matched\nexport class SelectorContext<T = any> {\n  notSelectors: CssSelector[];\n\n  constructor(\n    public selector: CssSelector,\n    public cbContext: T,\n    public listContext: SelectorListContext\n  ) {\n    this.notSelectors = selector.notSelectors;\n  }\n\n  finalize(\n    cssSelector: CssSelector,\n    callback: ((c: CssSelector, a: T) => void) | null\n  ): boolean {\n    let result = true;\n    if (\n      this.notSelectors.length > 0 &&\n      (!this.listContext || !this.listContext.alreadyMatched)\n    ) {\n      const notMatcher = SelectorMatcher.createNotMatcher(this.notSelectors);\n      result = !notMatcher.match(cssSelector, null);\n    }\n    if (\n      result &&\n      callback &&\n      (!this.listContext || !this.listContext.alreadyMatched)\n    ) {\n      if (this.listContext) {\n        this.listContext.alreadyMatched = true;\n      }\n      callback(this.selector, this.cbContext);\n    }\n    return result;\n  }\n}\n"
  },
  {
    "path": "src/builder/angular-internal/tags.ts",
    "content": "/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nexport enum TagContentType {\n  RAW_TEXT,\n  ESCAPABLE_RAW_TEXT,\n  PARSABLE_DATA,\n}\n\nexport interface TagDefinition {\n  closedByParent: boolean;\n  implicitNamespacePrefix: string | null;\n  isVoid: boolean;\n  ignoreFirstLf: boolean;\n  canSelfClose: boolean;\n  preventNamespaceInheritance: boolean;\n\n  isClosedByChild(name: string): boolean;\n  getContentType(prefix?: string): TagContentType;\n}\n\nexport function splitNsName(elementName: string): [string | null, string] {\n  if (elementName[0] != ':') {\n    return [null, elementName];\n  }\n\n  const colonIndex = elementName.indexOf(':', 1);\n\n  if (colonIndex === -1) {\n    throw new Error(\n      `Unsupported format \"${elementName}\" expecting \":namespace:name\"`\n    );\n  }\n\n  return [elementName.slice(1, colonIndex), elementName.slice(colonIndex + 1)];\n}\n\n// `<ng-container>` tags work the same regardless the namespace\nexport function isNgContainer(tagName: string): boolean {\n  return splitNsName(tagName)[1] === 'ng-container';\n}\n\n// `<ng-content>` tags work the same regardless the namespace\nexport function isNgContent(tagName: string): boolean {\n  return splitNsName(tagName)[1] === 'ng-content';\n}\n\n// `<ng-template>` tags work the same regardless the namespace\nexport function isNgTemplate(tagName: string): boolean {\n  return splitNsName(tagName)[1] === 'ng-template';\n}\n\nexport function getNsPrefix(fullName: string): string;\nexport function getNsPrefix(fullName: null): null;\nexport function getNsPrefix(fullName: string | null): string | null {\n  return fullName === null ? null : splitNsName(fullName)[0];\n}\n\nexport function mergeNsAndName(prefix: string, localName: string): string {\n  return prefix ? `:${prefix}:${localName}` : localName;\n}\n"
  },
  {
    "path": "src/builder/angular-internal/template.ts",
    "content": "/* eslint-disable @typescript-eslint/no-explicit-any */\n/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport type { CssSelector as CssSelectorType } from '@angular/compiler';\nimport { CssSelector } from './selector';\nimport { splitNsName } from './tags';\n/**\n * Creates a `CssSelector` given a tag name and a map of attributes\n */\nexport function createCssSelector(\n  elementName: string,\n  attributes: { [name: string]: string }\n): CssSelectorType {\n  const cssSelector = new CssSelector();\n  const elementNameNoNs = splitNsName(elementName)[1];\n\n  cssSelector.setElement(elementNameNoNs);\n\n  Object.getOwnPropertyNames(attributes).forEach((name) => {\n    const nameNoNs = splitNsName(name)[1];\n    const value = attributes[name];\n\n    cssSelector.addAttribute(nameNoNs, value);\n    if (name.toLowerCase() === 'class') {\n      const classes = value.trim().split(/\\s+/);\n      classes.forEach((className) => cssSelector.addClassName(className));\n    }\n  });\n\n  return cssSelector as any;\n}\n"
  },
  {
    "path": "src/builder/angular-internal/util.ts",
    "content": "/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport type * as t from './ast.type';\n\n/**\n * Extract a map of properties to values for a given element or template node, which can be used\n * by the directive matching machinery.\n *\n * @param elOrTpl the element or template in question\n * @return an object set up for directive matching. For attributes on the element/template, this\n * object maps a property name to its (static) value. For any bindings, this map simply maps the\n * property name to an empty string.\n */\nexport function getAttrsForDirectiveMatching(elOrTpl: t.Element): {\n  [name: string]: string;\n} {\n  const attributesMap: { [name: string]: string } = {};\n\n  elOrTpl.attributes.forEach((a: { name: string; value: string }) => {\n    if (!isI18nAttribute(a.name)) {\n      attributesMap[a.name] = a.value;\n    }\n  });\n\n  elOrTpl.inputs.forEach((i: { name: string | number }) => {\n    attributesMap[i.name] = '';\n  });\n  elOrTpl.outputs.forEach((o: { name: string | number }) => {\n    attributesMap[o.name] = '';\n  });\n\n  return attributesMap;\n}\n\n/** Name of the i18n attributes **/\nexport const I18N_ATTR = 'i18n';\nexport const I18N_ATTR_PREFIX = 'i18n-';\n\nexport function isI18nAttribute(name: string): boolean {\n  return name === I18N_ATTR || name.startsWith(I18N_ATTR_PREFIX);\n}\n"
  },
  {
    "path": "src/builder/application/const.ts",
    "content": "export const ExportMiniProgramAssetsPluginSymbol = Symbol.for(\n  'ExportMiniProgramAssetsPluginSymbol'\n);\nexport const LibrarySymbol = Symbol.for('LibrarySymbol');\nexport const InjectorSymbol = Symbol.for('InjectorSymbol');\nexport const TemplateScopeSymbol = Symbol.for('TemplateScopeSymbol');\n"
  },
  {
    "path": "src/builder/application/index.ts",
    "content": "import type { BuilderContext } from '@angular-devkit/architect';\nimport { createBuilder } from '@angular-devkit/architect';\nimport type {\n  AssetPattern,\n  BrowserBuilderOptions,\n} from '@angular-devkit/build-angular';\nimport { executeBrowserBuilder } from '@angular-devkit/build-angular';\nimport { Injector } from 'static-injector';\nimport * as webpack from 'webpack';\nimport { PlatformType } from '../platform/platform';\nimport { getBuildPlatformInjectConfig } from '../platform/platform-inject-config';\nimport { WebpackConfigurationChangeService } from './webpack-configuration-change.service';\n\nexport default createBuilder(\n  (\n    angularOptions: BrowserBuilderOptions & {\n      pages: AssetPattern[];\n      components: AssetPattern[];\n      platform: PlatformType;\n    },\n    context: BuilderContext\n  ): ReturnType<typeof executeBrowserBuilder> => {\n    return runBuilder(angularOptions, context);\n  }\n);\n\nexport function runBuilder(\n  angularOptions: BrowserBuilderOptions & {\n    pages: AssetPattern[];\n    components: AssetPattern[];\n    platform: PlatformType;\n  },\n  context: BuilderContext\n): ReturnType<typeof executeBrowserBuilder> {\n  return executeBrowserBuilder(angularOptions, context, {\n    webpackConfiguration: async (options: webpack.Configuration) => {\n      const injector = Injector.create({\n        providers: [\n          ...getBuildPlatformInjectConfig(angularOptions.platform),\n          {\n            provide: WebpackConfigurationChangeService,\n            useFactory: (injector: Injector) => {\n              return new WebpackConfigurationChangeService(\n                angularOptions,\n                context,\n                options,\n                injector\n              );\n            },\n            deps: [Injector],\n          },\n        ],\n      });\n      const config = injector.get(WebpackConfigurationChangeService);\n      config.init();\n      await config.change();\n      return options;\n    },\n  });\n}\n"
  },
  {
    "path": "src/builder/application/library-template-scope.service.ts",
    "content": "/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { Injectable } from 'static-injector';\nimport * as webpack from 'webpack';\nimport { TemplateScopeSymbol } from './const';\n\nexport type TemplateScopeOutside = Omit<\n  LibraryTemplateScopeService,\n  Exclude<\n    keyof LibraryTemplateScopeService,\n    'setScopeLibraryUseComponents' | 'setScopeExtraUseComponents'\n  >\n>;\nexport interface ExtraTemplateData {\n  useComponents: Record<string, string>;\n  templateList: string[];\n  configPath?: string;\n  templatePath?: string;\n}\n\n@Injectable()\nexport class LibraryTemplateScopeService {\n  private scopeExtraUseComponentsMap = new Map<string, ExtraTemplateData>();\n  private scopeLibraryUseComponentsMap = new Map<string, ExtraTemplateData[]>();\n  // 追加模板\n  constructor() {}\n  register(compilation: webpack.Compilation) {\n    (compilation as any)[TemplateScopeSymbol] = {\n      setScopeExtraUseComponents: this.setScopeExtraUseComponents,\n      setScopeLibraryUseComponents: this.setScopeLibraryUseComponents,\n    } as TemplateScopeOutside;\n  }\n\n  exportLibraryComponentConfig() {\n    const list: {\n      filePath: string;\n      content: { component: boolean; usingComponents: Record<string, string> };\n    }[] = [];\n    this.scopeLibraryUseComponentsMap.forEach((obj, libraryScope) => {\n      const extraData = this.scopeExtraUseComponentsMap.get(libraryScope) || {\n        useComponents: {},\n      };\n      // if (!extraData) {\n      //   throw new Error(`没有找到${libraryScope}对应的配置`);\n      // }\n      for (const item of obj) {\n        const configPath = item.configPath!;\n        const usingComponents = {\n          ...item.useComponents,\n          ...extraData.useComponents,\n        };\n        list.push({\n          filePath: configPath,\n          content: { component: true, usingComponents: usingComponents },\n        });\n      }\n    });\n    return list;\n  }\n  exportLibraryTemplate() {\n    const fileGroup: Record<string, string> = {};\n    this.scopeLibraryUseComponentsMap.forEach((obj, libraryScope) => {\n      const extraData = this.scopeExtraUseComponentsMap.get(libraryScope) || {\n        templateList: [],\n      };\n      // if (!extraData) {\n      //   throw new Error(`没有找到${libraryScope}对应的配置`);\n      // }\n      for (const item of obj) {\n        if (fileGroup[item.templatePath!]) {\n          continue;\n        }\n        fileGroup[item.templatePath!] = extraData.templateList.join('');\n      }\n    });\n    return fileGroup;\n  }\n  setScopeExtraUseComponents = (\n    libraryScope: string,\n    extraData: ExtraTemplateData\n  ) => {\n    const data: ExtraTemplateData = this.scopeExtraUseComponentsMap.get(\n      libraryScope\n    ) || { useComponents: {}, templateList: [] };\n    this.scopeExtraUseComponentsMap.set(libraryScope, {\n      useComponents: { ...data.useComponents, ...extraData.useComponents },\n      templateList: [...data.templateList, ...extraData.templateList],\n    });\n  };\n\n  setScopeLibraryUseComponents = (\n    libraryScope: string,\n    libraryUseComponents: ExtraTemplateData[]\n  ) => {\n    this.scopeLibraryUseComponentsMap.set(libraryScope, libraryUseComponents);\n  };\n}\n"
  },
  {
    "path": "src/builder/application/loader/component-template.loader.ts",
    "content": "import * as webpack from 'webpack';\nimport { changeComponent } from '../../component-template-inject/change-component';\n\nexport default async function (\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  this: webpack.LoaderContext<any>,\n  data: string,\n  map: string\n) {\n  const callback = this.async();\n  const changeData = changeComponent(data)!;\n\n  if (typeof data === 'undefined' || typeof changeData === 'undefined') {\n    callback(undefined, data, map);\n    return;\n  }\n\n  callback(undefined, changeData.content);\n}\n"
  },
  {
    "path": "src/builder/application/loader/library-template.loader.ts",
    "content": "/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { createCssSelectorForTs } from 'cyia-code-util';\nimport { Injector } from 'static-injector';\nimport { VariableDeclaration } from 'typescript';\nimport * as webpack from 'webpack';\nimport { TemplateScopeOutside } from '../../application/library-template-scope.service';\nimport { GLOBAL_TEMPLATE_SUFFIX } from '../../library';\nimport { ExtraTemplateData } from '../../library/type';\nimport { BuildPlatform } from '../../platform/platform';\nimport { literalResolve } from '../../util';\nimport { InjectorSymbol, TemplateScopeSymbol } from '../const';\nimport { LibraryTemplateLiteralConvertOptions } from '../type';\n\nexport default async function (\n  this: webpack.LoaderContext<any>,\n  data: string,\n  map: string\n) {\n  const callback = this.async();\n  const selector = createCssSelectorForTs(data);\n  const injector: Injector = (this._compilation! as any)[InjectorSymbol];\n  const buildPlatform = injector.get(BuildPlatform);\n  const templateScopeOutside = (this._compilation as any)[\n    TemplateScopeSymbol\n  ] as TemplateScopeOutside;\n  const selfTemplateNode = selector.queryOne(\n    `VariableDeclaration[name=\"$self_${GLOBAL_TEMPLATE_SUFFIX}\"]`\n  ) as VariableDeclaration;\n  if (selfTemplateNode) {\n    const content = selfTemplateNode.initializer!.getText();\n    const config: ExtraTemplateData = literalResolve(content);\n\n    this.emitFile(\n      config.outputPath + buildPlatform.fileExtname.contentTemplate,\n      literalResolve<LibraryTemplateLiteralConvertOptions>(\n        `\\`${config.template}\\``,\n        {\n          directivePrefix:\n            buildPlatform.templateTransform.getData().directivePrefix,\n          eventListConvert: buildPlatform.templateTransform.eventListConvert,\n          templateInterpolation:\n            buildPlatform.templateTransform.templateInterpolation,\n          fileExtname: buildPlatform.fileExtname,\n        }\n      )\n    );\n  }\n  const libraryTemplateNode = selector.queryOne(\n    `VariableDeclaration[name=\"library_${GLOBAL_TEMPLATE_SUFFIX}\"]`\n  ) as VariableDeclaration;\n  if (libraryTemplateNode) {\n    const content = libraryTemplateNode.initializer!.getText();\n    const config: Record<string, ExtraTemplateData> = literalResolve(content);\n\n    for (const key in config) {\n      if (Object.prototype.hasOwnProperty.call(config, key)) {\n        const element = config[key];\n        templateScopeOutside.setScopeExtraUseComponents(key, {\n          useComponents: element.useComponents!,\n          templateList: [element.template],\n        });\n      }\n    }\n  }\n  callback(undefined, data, map);\n}\n"
  },
  {
    "path": "src/builder/application/loader/library.loader.ts",
    "content": "/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { dirname, join, normalize, strings } from '@angular-devkit/core';\n\nimport { createCssSelectorForTs } from 'cyia-code-util';\nimport ts from 'typescript';\nimport * as webpack from 'webpack';\nimport {\n  ExtraTemplateData,\n  TemplateScopeOutside,\n} from '../../application/library-template-scope.service';\nimport {\n  LIBRARY_COMPONENT_METADATA_SUFFIX,\n  LIBRARY_OUTPUT_ROOTDIR,\n} from '../../library';\nimport type { ExportLibraryComponentMeta } from '../../library';\nimport { libraryTemplateScopeName, literalResolve } from '../../util';\nimport {\n  ExportMiniProgramAssetsPluginSymbol,\n  LibrarySymbol,\n  TemplateScopeSymbol,\n} from '../const';\nimport type { LibraryLoaderContext } from '../type';\nimport { LibraryTemplateLiteralConvertOptions } from '../type';\nimport { ComponentTemplateLoaderContext } from './type';\n\nexport default async function (\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  this: webpack.LoaderContext<any>,\n  data: string,\n  map: string\n) {\n  const callback = this.async();\n  const selector = createCssSelectorForTs(data);\n  const list = selector.queryAll(\n    `PropertyAccessExpression[name=ɵɵdefineComponent]~SyntaxList ObjectLiteralExpression PropertyAssignment[name=type]::initializer`\n  );\n  if (!list.length) {\n    callback(undefined, data, map);\n    return;\n  }\n  const context: ComponentTemplateLoaderContext = (this._compilation! as any)[\n    ExportMiniProgramAssetsPluginSymbol\n  ];\n  const templateScopeOutside = (this._compilation as any)[\n    TemplateScopeSymbol\n  ] as TemplateScopeOutside;\n  const scopeLibraryObj: Record<string, ExtraTemplateData[]> = {};\n  for (let i = 0; i < list.length; i++) {\n    const element = list[i] as ts.BinaryExpression;\n    const componentName = element.getText();\n    const extraNode = selector.queryOne(\n      `VariableDeclaration[name=\"${componentName}_${LIBRARY_COMPONENT_METADATA_SUFFIX}\"]`\n    ) as ts.VariableDeclaration;\n    if (!extraNode) {\n      continue;\n    }\n    const content = extraNode.initializer!.getText();\n    const meta: ExportLibraryComponentMeta = literalResolve(content);\n    (this._compilation as any)[LibrarySymbol] =\n      (this._compilation as any)[LibrarySymbol] || {};\n    const libraryLoaderContext: LibraryLoaderContext = (\n      this._compilation as any\n    )[LibrarySymbol];\n    libraryLoaderContext.libraryMetaList =\n      libraryLoaderContext.libraryMetaList || [];\n    libraryLoaderContext.libraryMetaList.push({\n      ...meta,\n      context: this.context,\n      importPath: this.resourcePath,\n      contextPath: this.utils.contextify(this.rootContext, this.resourcePath),\n    });\n    const fileExtname = libraryLoaderContext.buildPlatform.fileExtname;\n    libraryLoaderContext.libraryMetaList.forEach((item) => {\n      const globalTemplatePath = join(\n        normalize('/library-template'),\n        strings.classify(item.moduleId) +\n          libraryLoaderContext.buildPlatform.fileExtname.contentTemplate\n      );\n      const LIBRARY_SCOPE_ID = libraryTemplateScopeName(item.moduleId);\n      const configPath = join(\n        normalize(LIBRARY_OUTPUT_ROOTDIR),\n        item.libraryPath + fileExtname.config\n      );\n      const list = scopeLibraryObj[LIBRARY_SCOPE_ID] || [];\n      list.push({\n        configPath: configPath,\n        useComponents: item.useComponents,\n        templateList: [],\n        templatePath: globalTemplatePath,\n      });\n\n      scopeLibraryObj[LIBRARY_SCOPE_ID] = list;\n      const libraryTemplateLiteralConvertOptions: LibraryTemplateLiteralConvertOptions =\n        {\n          directivePrefix:\n            libraryLoaderContext.buildPlatform.templateTransform.getData()\n              .directivePrefix,\n          eventListConvert:\n            libraryLoaderContext.buildPlatform.templateTransform\n              .eventListConvert,\n          templateInterpolation:\n            libraryLoaderContext.buildPlatform.templateTransform\n              .templateInterpolation,\n          fileExtname: libraryLoaderContext.buildPlatform.fileExtname,\n        };\n      this.emitFile(\n        join(\n          normalize(LIBRARY_OUTPUT_ROOTDIR),\n          item.libraryPath + fileExtname.content\n        ),\n        `<import src=\"${globalTemplatePath}\"/>` +\n          literalResolve(\n            `\\`${item.content}\\``,\n            libraryTemplateLiteralConvertOptions\n          )\n      );\n      if (item.contentTemplate) {\n        this.emitFile(\n          join(\n            normalize(LIBRARY_OUTPUT_ROOTDIR),\n            dirname(normalize(item.libraryPath)),\n            'template' + fileExtname.contentTemplate\n          ),\n          `<import src=\"${globalTemplatePath}\"/>` +\n            literalResolve(\n              `\\`${item.contentTemplate}\\``,\n              libraryTemplateLiteralConvertOptions\n            )\n        );\n      }\n      if (item.style) {\n        this.emitFile(\n          join(\n            normalize(LIBRARY_OUTPUT_ROOTDIR),\n            item.libraryPath + fileExtname.style\n          ),\n          item.style\n        );\n      }\n    });\n  }\n  for (const key in scopeLibraryObj) {\n    if (Object.prototype.hasOwnProperty.call(scopeLibraryObj, key)) {\n      const element = scopeLibraryObj[key];\n      templateScopeOutside.setScopeLibraryUseComponents(key, element);\n    }\n  }\n  callback(undefined, data, map);\n}\n"
  },
  {
    "path": "src/builder/application/loader/type.ts",
    "content": "import { MetaCollection } from '../../mini-program-compiler';\nimport type { BuildPlatform } from '../../platform/platform';\n\nexport interface ComponentTemplateLoaderContext {\n  buildPlatform: BuildPlatform;\n  otherMetaGroupPromise: Promise<Record<string, MetaCollection>>;\n}\n"
  },
  {
    "path": "src/builder/application/mini-program-application-analysis.service.ts",
    "content": "import type { NgtscProgram, ParsedConfiguration } from '@angular/compiler-cli';\nimport type { NgCompiler } from '@angular/compiler-cli/src/ngtsc/core';\nimport { join, normalize, resolve } from '@angular-devkit/core';\nimport { externalizePath } from '@ngtools/webpack/src/ivy/paths';\nimport { createHash } from 'crypto';\nimport { createCssSelectorForTs } from 'cyia-code-util';\nimport * as path from 'path';\nimport { Inject, Injectable, Injector } from 'static-injector';\nimport ts from 'typescript';\nimport type { CompilerOptions } from 'typescript';\nimport { Compilation, Compiler } from 'webpack';\nimport { LIBRARY_OUTPUT_ROOTDIR } from '../library';\nimport { MiniProgramCompilerService } from '../mini-program-compiler';\nimport { BuildPlatform } from '../platform/platform';\nimport { angularCompilerCliPromise } from '../util/load_esm';\nimport {\n  OLD_BUILDER,\n  PAGE_PATTERN_TOKEN,\n  TS_CONFIG_TOKEN,\n  TS_SYSTEM,\n  WEBPACK_COMPILATION,\n  WEBPACK_COMPILER,\n} from './token';\nimport type { PagePattern } from './type';\n\n@Injectable()\nexport class MiniProgramApplicationAnalysisService {\n  private dependencyUseModule = new Map<string, string[]>();\n  private cleanDependencyFileCacheSet = new Set<string>();\n  builder!: ts.BuilderProgram | ts.EmitAndSemanticDiagnosticsBuilderProgram;\n  private ngTscProgram!: NgtscProgram;\n  private tsProgram!: ts.Program;\n  private ngCompiler!: NgCompiler;\n  private typeChecker!: ts.TypeChecker;\n  constructor(\n    private injector: Injector,\n    @Inject(WEBPACK_COMPILATION) private compilation: Compilation,\n    @Inject(TS_SYSTEM) private system: ts.System,\n    @Inject(WEBPACK_COMPILER) private compiler: Compiler,\n    @Inject(TS_CONFIG_TOKEN) private tsConfig: string,\n    @Inject(OLD_BUILDER)\n    private oldBuilder: ts.EmitAndSemanticDiagnosticsBuilderProgram | undefined,\n    @Inject(PAGE_PATTERN_TOKEN) private pagePatternList: PagePattern[],\n    private buildPlatform: BuildPlatform\n  ) {}\n\n  async exportComponentBuildMetaMap() {\n    const injector = Injector.create({\n      providers: [\n        {\n          provide: MiniProgramCompilerService,\n          useFactory: (injector: Injector, buildPlatform: BuildPlatform) => {\n            return new MiniProgramCompilerService(\n              this.ngTscProgram,\n              injector,\n              buildPlatform\n            );\n          },\n          deps: [Injector, BuildPlatform],\n        },\n      ],\n      parent: this.injector,\n    });\n    const miniProgramCompilerService = injector.get(MiniProgramCompilerService);\n    miniProgramCompilerService.init();\n    const metaMap =\n      await miniProgramCompilerService.exportComponentBuildMetaMap();\n\n    const selfMetaCollection = metaMap.otherMetaCollectionGroup['$self'];\n    const selfTemplate: Record<string, string> = {};\n    if (selfMetaCollection) {\n      const importSelfTemplatePath = `/self-template/self${this.buildPlatform.fileExtname.contentTemplate}`;\n      const importSelfTemplate = `<import src=\"${importSelfTemplatePath}\"/>`;\n      metaMap.outputContent.forEach((value, key) => {\n        value = `${importSelfTemplate}${value}`;\n        metaMap.outputContent.set(key, value);\n      });\n\n      metaMap.useComponentPath.forEach((value, key) => {\n        value.libraryPath.push(...selfMetaCollection.libraryPath);\n        value.localPath.push(...selfMetaCollection.localPath);\n      });\n      selfTemplate[importSelfTemplatePath] = selfMetaCollection.templateList\n        .map((item) => item.content)\n        .join('');\n      delete metaMap.otherMetaCollectionGroup['$self'];\n    }\n    metaMap.useComponentPath.forEach((value, key) => {\n      value.libraryPath = Array.from(new Set(value.libraryPath));\n      value.localPath = Array.from(new Set(value.localPath));\n    });\n    const styleMap = new Map<string, string[]>();\n    metaMap.style.forEach((value, key) => {\n      const entryPattern = this.getComponentPagePattern(key);\n      styleMap.set(entryPattern.outputFiles.style, value);\n    });\n    const contentMap = new Map<string, string>();\n    metaMap.outputContent.forEach((value, key) => {\n      const entryPattern = this.getComponentPagePattern(key);\n      contentMap.set(entryPattern.outputFiles.content, value);\n    });\n\n    metaMap.style = styleMap;\n    const config = new Map<\n      string,\n      {\n        component: true | undefined;\n        usingComponents: { selector: string; path: string }[];\n        existConfig: string;\n      }\n    >();\n    metaMap.useComponentPath.forEach((value, key) => {\n      const entryPattern = this.getComponentPagePattern(key);\n      const list = [\n        ...value.libraryPath.map((item) => {\n          item.path = resolve(\n            normalize('/'),\n            join(normalize(LIBRARY_OUTPUT_ROOTDIR), item.path)\n          );\n          return item;\n        }),\n      ];\n      list.push(\n        ...value.localPath.map((item) => ({\n          selector: item.selector,\n          path: resolve(\n            normalize('/'),\n            normalize(this.getComponentPagePattern(item.path).outputFiles.path)\n          ),\n          className: item.className,\n        }))\n      );\n      config.set(entryPattern.outputFiles.config, {\n        component: entryPattern.type === 'component' || undefined,\n        usingComponents: list,\n        existConfig: entryPattern.inputFiles.config,\n      });\n    });\n\n    for (const key in metaMap.otherMetaCollectionGroup) {\n      if (\n        Object.prototype.hasOwnProperty.call(\n          metaMap.otherMetaCollectionGroup,\n          key\n        )\n      ) {\n        const element = metaMap.otherMetaCollectionGroup[key];\n        element.libraryPath.forEach((item) => {\n          item.path = resolve(\n            normalize('/'),\n            join(normalize(LIBRARY_OUTPUT_ROOTDIR), item.path)\n          );\n        });\n        element.localPath.forEach((item) => {\n          item.path = resolve(\n            normalize('/'),\n            normalize(this.getComponentPagePattern(item.path).outputFiles.path)\n          );\n        });\n      }\n    }\n    return {\n      style: styleMap,\n      outputContent: contentMap,\n      config: config,\n      otherMetaCollectionGroup: metaMap.otherMetaCollectionGroup,\n      selfTemplate,\n    };\n  }\n\n  private initHost(config: ParsedConfiguration) {\n    const host = ts.createIncrementalCompilerHost(config.options, this.system);\n    this.augmentResolveModuleNames(host, config.options);\n    this.addCleanDependency(host);\n    return host;\n  }\n  private async initTscProgram() {\n    const { readConfiguration, NgtscProgram } = await angularCompilerCliPromise;\n    const config = readConfiguration(this.tsConfig, undefined);\n    const host = this.initHost(config);\n    this.ngTscProgram = new NgtscProgram(\n      config.rootNames,\n      config.options,\n      host\n    );\n    this.tsProgram = this.ngTscProgram.getTsProgram();\n    this.typeChecker = this.tsProgram.getTypeChecker();\n    this.augmentProgramWithVersioning(this.tsProgram);\n    if (this.compiler.watchMode) {\n      this.builder = this.oldBuilder =\n        ts.createEmitAndSemanticDiagnosticsBuilderProgram(\n          this.tsProgram,\n          host,\n          this.oldBuilder\n        );\n    } else {\n      this.builder = ts.createAbstractBuilder(this.tsProgram, host);\n    }\n    this.ngCompiler = this.ngTscProgram.compiler;\n  }\n  /** 获得组件/页面的入口 */\n  private getComponentPagePattern(fileName: string) {\n    const findList = [fileName];\n    let maybeEntryPath: PagePattern | undefined;\n\n    while (findList.length) {\n      const module = findList.shift();\n      const moduleList = this.dependencyUseModule.get(path.normalize(module!));\n      if (moduleList && moduleList.length) {\n        findList.push(...moduleList);\n      } else {\n        maybeEntryPath = this.pagePatternList.find(\n          (item) => path.normalize(item.src) === path.normalize(module!)\n        );\n        if (maybeEntryPath) {\n          const sourceFile = this.tsProgram.getSourceFile(maybeEntryPath.src)!;\n          const selector = createCssSelectorForTs(sourceFile);\n          let importComponent: ts.Expression;\n          if (maybeEntryPath.type === 'page') {\n            const node = selector.queryOne(\n              `CallExpression[expression=pageStartup]`\n            ) as ts.CallExpression;\n            importComponent = node.arguments[1];\n          } else {\n            const node = selector.queryOne(\n              `CallExpression[expression=componentRegistry]`\n            ) as ts.CallExpression;\n            importComponent = node.arguments[0];\n          }\n          const symbol = this.typeChecker.getSymbolAtLocation(importComponent);\n          const node = symbol?.getDeclarations()?.[0];\n          const importDeclaration = node?.parent.parent\n            .parent as ts.ImportDeclaration;\n          const relativeImportComponentPath = importDeclaration.moduleSpecifier\n            .getText()\n            .slice(1, -1);\n\n          const importComponentPath =\n            path.resolve(\n              path.dirname(maybeEntryPath.src),\n              path.normalize(relativeImportComponentPath)\n            ) + '.ts';\n          if (importComponentPath === path.normalize(fileName)) {\n            break;\n          }\n\n          maybeEntryPath = undefined;\n        }\n      }\n    }\n    if (!maybeEntryPath) {\n      throw new Error(`没有找到组件[${fileName}]对应的入口点`);\n    }\n    return maybeEntryPath;\n  }\n\n  private addCleanDependency(host: ts.CompilerHost) {\n    const oldReadFile = host.readFile;\n    const _this = this;\n    host.readFile = function (fileName) {\n      if (fileName.includes('node_modules')) {\n        _this.cleanDependencyFileCacheSet.add(externalizePath(fileName));\n      }\n      return oldReadFile.call(this, fileName);\n    };\n  }\n  private saveModuleDependency(\n    filePath: string,\n    moduleName: string,\n    module: ts.ResolvedModule\n  ) {\n    if (!module) {\n      throw new Error(`模块未被解析,文件名${filePath},模块名${moduleName}`);\n    }\n    const useList =\n      this.dependencyUseModule.get(path.normalize(module.resolvedFileName)) ||\n      [];\n    useList.push(filePath);\n    this.dependencyUseModule.set(\n      path.normalize(module.resolvedFileName),\n      useList\n    );\n  }\n  private augmentResolveModuleNames(\n    host: ts.CompilerHost,\n    compilerOptions: CompilerOptions\n  ) {\n    const moduleResolutionCache = ts.createModuleResolutionCache(\n      host.getCurrentDirectory(),\n      host.getCanonicalFileName.bind(host),\n      compilerOptions\n    );\n    const oldResolveModuleNames = host.resolveModuleNames;\n    if (oldResolveModuleNames) {\n      // eslint-disable-next-line @typescript-eslint/no-explicit-any\n      host.resolveModuleNames = (moduleNames: string[], ...args: any[]) => {\n        return moduleNames.map((name) => {\n          // eslint-disable-next-line @typescript-eslint/no-explicit-any\n          const result = (oldResolveModuleNames! as any).call(\n            host,\n            [name],\n            ...args\n          );\n          this.saveModuleDependency(args[0], name, result);\n\n          return result;\n        });\n      };\n    } else {\n      host.resolveModuleNames = (\n        moduleNames: string[],\n        containingFile: string,\n        _reusedNames: string[] | undefined,\n        redirectedReference: ts.ResolvedProjectReference | undefined,\n        options: ts.CompilerOptions\n      ) => {\n        return moduleNames.map((name) => {\n          const result = ts.resolveModuleName(\n            name,\n            containingFile,\n            options,\n            host,\n            moduleResolutionCache,\n            redirectedReference\n          ).resolvedModule;\n          if (!containingFile.includes('node_modules')) {\n            this.saveModuleDependency(containingFile, name, result!);\n          }\n          return result;\n        });\n      };\n    }\n  }\n\n  async analyzeAsync() {\n    await this.initTscProgram();\n    await this.ngCompiler.analyzeAsync();\n  }\n  getBuilder() {\n    return this.builder;\n  }\n  cleanDependencyFileCache() {\n    this.cleanDependencyFileCacheSet.forEach((filePath) => {\n      try {\n        this.compiler.inputFileSystem.purge!(filePath);\n      } catch (error) {}\n    });\n  }\n  private augmentProgramWithVersioning(program: ts.Program): void {\n    const baseGetSourceFiles = program.getSourceFiles;\n    program.getSourceFiles = function (...parameters) {\n      const files: readonly (ts.SourceFile & { version?: string })[] =\n        baseGetSourceFiles(...parameters);\n\n      for (const file of files) {\n        if (file.version === undefined) {\n          file.version = createHash('sha256').update(file.text).digest('hex');\n        }\n      }\n\n      return files;\n    };\n  }\n}\n"
  },
  {
    "path": "src/builder/application/plugin/dynamic-library-entry.plugin.ts",
    "content": "/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { join, normalize } from '@angular-devkit/core';\nimport path from 'path';\nimport { Injectable } from 'static-injector';\nimport * as webpack from 'webpack';\nimport { LIBRARY_OUTPUT_ROOTDIR } from '../../library';\nimport type { LibraryComponentEntryMeta } from '../../library';\nimport { BuildPlatform } from '../../platform/platform';\nimport { LibrarySymbol } from '../const';\nimport type { LibraryLoaderContext } from '../type';\n\nconst CUSTOM_URI = 'dynamic';\nconst CUSTOM_URI_REG = /^dynamic:\\/\\/__license(?:\\/|\\\\)(.*)\\.ts$/;\n@Injectable()\nexport class DynamicLibraryComponentEntryPlugin {\n  private libraryComponentMap = new Map<string, LibraryComponentEntryMeta>();\n  constructor(private buildPlatform: BuildPlatform) {}\n  apply(compiler: webpack.Compiler) {\n    compiler.hooks.thisCompilation.tap(\n      'DynamicLibraryEntryPlugin',\n      (thisCompilation) => {\n        (thisCompilation as any)[LibrarySymbol] = (thisCompilation as any)[\n          LibrarySymbol\n        ] || { buildPlatform: this.buildPlatform };\n        const hooks = webpack.NormalModule.getCompilationHooks(thisCompilation);\n        hooks.readResource\n          .for(CUSTOM_URI)\n          .tapAsync(\n            'DynamicLibraryEntryPlugin',\n            (loaderContext: any, callback) => {\n              const resourcePath: string = loaderContext.resourcePath;\n              const id = resourcePath.match(CUSTOM_URI_REG)![1];\n              const libraryMeta = this.libraryComponentMap.get(id);\n\n              callback(\n                undefined,\n                `\n            import * as amp from 'angular-miniprogram';\n            import * as library from '${libraryMeta?.contextPath}';\n            amp.componentRegistry(library.${libraryMeta?.className});\n            `\n              );\n              return;\n            }\n          );\n        compiler.hooks.finishMake.tapAsync(\n          'DynamicLibraryEntryPlugin',\n          (compilation, callback) => {\n            const libraryLoaderContext: LibraryLoaderContext = (\n              compilation as any\n            )[LibrarySymbol];\n            if (compilation !== thisCompilation) {\n              callback(undefined);\n              return;\n            }\n            if (libraryLoaderContext.libraryMetaList) {\n              libraryLoaderContext.libraryMetaList.forEach((item) => {\n                this.libraryComponentMap.set(item.id, item);\n              });\n            }\n\n            if (this.libraryComponentMap.size === 0) {\n              callback(undefined);\n              return;\n            }\n            let j = 0;\n            this.libraryComponentMap.forEach((meta) => {\n              const entry = join(\n                normalize(LIBRARY_OUTPUT_ROOTDIR),\n                meta.libraryPath\n              );\n              const dep = webpack.EntryPlugin.createDependency(\n                `${CUSTOM_URI}://${path.join('__license', meta.id)}.ts`,\n                entry\n              );\n              compilation.addEntry(\n                compiler.context,\n                dep,\n                entry,\n                (err, result) => {\n                  j++;\n                  if (j === this.libraryComponentMap.size) {\n                    callback(undefined);\n                  }\n                }\n              );\n            });\n          }\n        );\n      }\n    );\n  }\n}\n"
  },
  {
    "path": "src/builder/application/plugin/dynamic-watch-entry.plugin.ts",
    "content": "import type { BuilderContext } from '@angular-devkit/architect';\nimport type { AssetPattern } from '@angular-devkit/build-angular';\nimport { normalizeAssetPatterns } from '@angular-devkit/build-angular/src/utils';\nimport { Path, getSystemPath, normalize, resolve } from '@angular-devkit/core';\nimport * as glob from 'glob';\nimport * as path from 'path';\nimport { BehaviorSubject, firstValueFrom } from 'rxjs';\nimport { filter, take } from 'rxjs/operators';\nimport { Injectable } from 'static-injector';\nimport * as webpack from 'webpack';\nimport { BuildPlatform } from '../../platform/platform';\nimport type { PagePattern } from '../type';\n\nfunction globAsync(pattern: string, options: glob.IOptions) {\n  return new Promise<string[]>((resolve, reject) =>\n    glob.default(pattern, options, (e, m) => (e ? reject(e) : resolve(m)))\n  );\n}\n@Injectable()\nexport class DynamicWatchEntryPlugin {\n  pageList!: PagePattern[];\n  componentList!: PagePattern[];\n  entryPattern$ = new BehaviorSubject<\n    | {\n        pageList: PagePattern[];\n        componentList: PagePattern[];\n      }\n    | undefined\n  >(undefined);\n  private first = true;\n  absoluteProjectRoot!: Path;\n  absoluteProjectSourceRoot!: Path;\n  constructor(\n    private options: {\n      pages: AssetPattern[];\n      components: AssetPattern[];\n      workspaceRoot: Path;\n      context: BuilderContext;\n      config: webpack.Configuration;\n    },\n    private buildPlatform: BuildPlatform\n  ) {}\n  async init() {\n    const projectName =\n      this.options.context.target && this.options.context.target.project;\n    if (!projectName) {\n      throw new Error('The builder requires a target.');\n    }\n    const projectMetadata = await this.options.context.getProjectMetadata(\n      projectName\n    );\n    this.absoluteProjectRoot = normalize(\n      getSystemPath(\n        resolve(\n          this.options.workspaceRoot,\n          normalize((projectMetadata.root as string) || '')\n        )\n      )\n    );\n    const relativeSourceRoot = projectMetadata.sourceRoot as string | undefined;\n    const absoluteSourceRootPath =\n      typeof relativeSourceRoot === 'string'\n        ? resolve(this.options.workspaceRoot, normalize(relativeSourceRoot))\n        : undefined;\n    if (relativeSourceRoot) {\n      this.absoluteProjectSourceRoot = normalize(\n        getSystemPath(absoluteSourceRootPath!)\n      )!;\n    }\n  }\n  apply(compiler: webpack.Compiler) {\n    let rootCompilation: boolean = false;\n    compiler.hooks.beforeCompile.tapPromise(\n      'DynamicWatchEntryPlugin',\n      async (compilationParams) => {\n        if (rootCompilation) {\n          return;\n        }\n\n        this.entryPattern$.next({\n          pageList: await this.generateModuleInfo(\n            this.options.pages || [],\n            'page'\n          ),\n          componentList: await this.generateModuleInfo(\n            this.options.components || [],\n            'component'\n          ),\n        });\n      }\n    );\n    compiler.hooks.thisCompilation.tap(\n      'DynamicWatchEntryPlugin',\n      (compilation) => {\n        rootCompilation = true;\n        if (this.first) {\n          this.first = false;\n          const patternList = normalizeAssetPatterns(\n            [...(this.options.pages || []), ...(this.options.components || [])],\n            this.options.workspaceRoot,\n            this.absoluteProjectRoot,\n            this.absoluteProjectSourceRoot\n          );\n          for (const pattern of patternList) {\n            const cwd = path.resolve(\n              this.options.context.workspaceRoot,\n              pattern.input\n            );\n            compilation.fileDependencies.add(cwd);\n          }\n        }\n      }\n    );\n    // 因为监听更新的时候beforeCompile会拦截所有的,所以这么实现(因为还有一次性构建不触发watchRun,所以不能代替)\n    compiler.hooks.watchRun.tap('DynamicWatchEntryPlugin', async () => {\n      rootCompilation = false;\n    });\n    // 入口移动到这里是因为ng新增了一个插件也同时修改了入口,\n    compiler.hooks.environment.tap(\n      { name: `DynamicWatchEntryPlugin`, stage: 9999 },\n      () => {\n        const originEntryConfig = compiler.options.entry;\n        compiler.options.entry = async () => {\n          await firstValueFrom(\n            this.entryPattern$.pipe(filter(Boolean), take(1))\n          );\n          const entryPattern = this.entryPattern$.value!;\n          const list = [\n            ...entryPattern.pageList,\n            ...entryPattern.componentList,\n          ];\n          const result = (await (typeof originEntryConfig === 'function'\n            ? originEntryConfig()\n            : originEntryConfig))!;\n          if (result['app']) {\n            throw new Error(\n              '资源文件不能指定为app文件名或bundleName,请重新修改(不影响导出)'\n            );\n          }\n          return {\n            ...result,\n            ...list.reduce((pre, cur) => {\n              pre[cur.entryName] = { import: [cur.src] };\n              return pre;\n            }, {} as Record<string, Exclude<webpack.EntryNormalized, Function>[string]>),\n          };\n        };\n      }\n    );\n  }\n  private async generateModuleInfo(\n    list: AssetPattern[],\n    type: 'page' | 'component'\n  ) {\n    const patternList = normalizeAssetPatterns(\n      list,\n      this.options.workspaceRoot,\n      this.absoluteProjectRoot,\n      this.absoluteProjectSourceRoot\n    );\n    const moduleList: PagePattern[] = [];\n    for (const pattern of patternList) {\n      const cwd = path.resolve(\n        this.options.context.workspaceRoot,\n        pattern.input\n      );\n      /** 当前匹配匹配到的文件 */\n      const files = await globAsync(pattern.glob, {\n        cwd,\n        dot: true,\n        nodir: true,\n        ignore: pattern.ignore || [],\n        follow: pattern.followSymlinks,\n      });\n\n      moduleList.push(\n        ...files.map((file) => {\n          const object: Partial<PagePattern> = {\n            entryName: path.basename(file, '.ts').replace(/\\./g, '-'),\n            fileName: file,\n            src: path.join(cwd, file),\n            ...pattern,\n            // eslint-disable-next-line @typescript-eslint/no-explicit-any\n            outputFiles: {} as any,\n            // eslint-disable-next-line @typescript-eslint/no-explicit-any\n            inputFiles: {} as any,\n          };\n          object.inputFiles!.config = object.src!.replace(\n            /\\.ts$/,\n            this.buildPlatform.fileExtname.config!\n          );\n          const outputFileName =\n            object.fileName!.replace(/\\.ts$/, '').replace(/\\./g, '-') + '.ts';\n          object.outputFiles!.path = path\n            .join(pattern.output, outputFileName)\n            .replace(/\\.ts$/, '');\n          object.outputFiles!.logic =\n            object.outputFiles!.path + this.buildPlatform.fileExtname.logic;\n          object.outputFiles!.style =\n            object.outputFiles!.path + this.buildPlatform.fileExtname.style;\n          object.outputFiles!.content =\n            object.outputFiles!.path + this.buildPlatform.fileExtname.content;\n          object.outputFiles!.config =\n            object.outputFiles!.path + this.buildPlatform.fileExtname.config;\n          object.type = type;\n          return object as PagePattern;\n        })\n      );\n    }\n    return moduleList;\n  }\n}\n"
  },
  {
    "path": "src/builder/application/plugin/export-mini-program-assets.plugin.ts",
    "content": "/* eslint-disable @typescript-eslint/no-explicit-any */\n/* eslint-disable no-console */\nimport { normalizePath } from '@ngtools/webpack/src/ivy/paths';\nimport {\n  InputFileSystemSync,\n  createWebpackSystem,\n} from '@ngtools/webpack/src/ivy/system';\nimport * as path from 'path';\nimport { Inject, Injectable, Injector } from 'static-injector';\nimport ts from 'typescript';\nimport { sources } from 'webpack';\nimport * as webpack from 'webpack';\nimport { BuildPlatform } from '../../platform/platform';\nimport { literalResolve } from '../../util';\nimport { ExportMiniProgramAssetsPluginSymbol, InjectorSymbol } from '../const';\nimport { LibraryTemplateScopeService } from '../library-template-scope.service';\nimport type { ComponentTemplateLoaderContext } from '../loader/type';\nimport { MiniProgramApplicationAnalysisService } from '../mini-program-application-analysis.service';\nimport {\n  OLD_BUILDER,\n  PAGE_PATTERN_TOKEN,\n  TS_CONFIG_TOKEN,\n  TS_SYSTEM,\n  WEBPACK_COMPILATION,\n  WEBPACK_COMPILER,\n} from '../token';\nimport type { PagePattern } from '../type';\nimport { LibraryTemplateLiteralConvertOptions } from '../type';\nimport { setCompilationAsset } from '../util';\n\n@Injectable()\nexport class ExportMiniProgramAssetsPlugin {\n  private pageList!: PagePattern[];\n  private componentList!: PagePattern[];\n  private system!: ts.System;\n  constructor(\n    @Inject(TS_CONFIG_TOKEN) tsConfig: string,\n    private buildPlatform: BuildPlatform,\n    private injector: Injector,\n    private libraryTemplateScopeService: LibraryTemplateScopeService\n  ) {}\n  apply(compiler: webpack.Compiler) {\n    const ifs = compiler.inputFileSystem as InputFileSystemSync;\n    let oldBuilder: ts.EmitAndSemanticDiagnosticsBuilderProgram | undefined =\n      undefined;\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\n    const styleAssets = new Map<string, sources.Source>();\n    compiler.hooks.compilation.tap(\n      'ExportMiniProgramAssetsPlugin',\n      (compilation) => {\n        compilation.hooks.processAssets.tap(\n          'ExportMiniProgramAssetsPlugin',\n          () => {\n            for (const stylePath in compilation.assets) {\n              if (\n                Object.prototype.hasOwnProperty.call(\n                  compilation.assets,\n                  stylePath\n                )\n              ) {\n                const data = compilation.getAsset(stylePath)!;\n                if (/\\.(scss|css|sass|less|styl)$/.test(stylePath)) {\n                  styleAssets.set(path.normalize(stylePath), data.source);\n                  setCompilationAsset(\n                    compilation,\n                    stylePath,\n                    new sources.RawSource(' ')\n                  );\n                }\n              }\n            }\n          }\n        );\n      }\n    );\n    compiler.hooks.thisCompilation.tap(\n      'ExportMiniProgramAssetsPlugin',\n      (compilation) => {\n        this.system = createWebpackSystem(\n          compiler.inputFileSystem as InputFileSystemSync,\n          normalizePath(compiler.context)\n        );\n        this.libraryTemplateScopeService.register(compilation);\n        (compilation as any)[InjectorSymbol] = this.injector;\n        const injector = Injector.create({\n          providers: [\n            { provide: MiniProgramApplicationAnalysisService },\n            { provide: WEBPACK_COMPILATION, useValue: compilation },\n            { provide: WEBPACK_COMPILER, useValue: compiler },\n            { provide: OLD_BUILDER, useValue: oldBuilder },\n            {\n              provide: TS_SYSTEM,\n              useValue: this.system,\n            },\n            {\n              provide: PAGE_PATTERN_TOKEN,\n              useValue: [...this.pageList, ...this.componentList],\n            },\n          ],\n          parent: this.injector,\n        });\n        const templateService = injector.get(\n          MiniProgramApplicationAnalysisService\n        );\n        oldBuilder =\n          templateService.getBuilder() as ts.EmitAndSemanticDiagnosticsBuilderProgram;\n        const buildTemplatePromise = this.buildTemplate(templateService);\n        // eslint-disable-next-line @typescript-eslint/no-explicit-any\n        (compilation as any)[ExportMiniProgramAssetsPluginSymbol] = {\n          buildPlatform: this.buildPlatform,\n          otherMetaGroupPromise: buildTemplatePromise.then(\n            (item) => item.otherMetaCollectionGroup\n          ),\n        } as ComponentTemplateLoaderContext;\n\n        compilation.hooks.processAssets.tapAsync(\n          'ExportMiniProgramAssetsPlugin',\n          async (assets, cb) => {\n            const metaMap = await buildTemplatePromise;\n\n            metaMap.outputContent.forEach((value, key) => {\n              setCompilationAsset(\n                compilation,\n                key,\n                new sources.RawSource(value)\n              );\n            });\n\n            metaMap.style.forEach((value, outputPath) => {\n              setCompilationAsset(\n                compilation,\n                outputPath,\n                new sources.ConcatSource(\n                  ...value.map((item) => styleAssets.get(item)!)\n                )\n              );\n            });\n            metaMap.config.forEach((value, key) => {\n              // eslint-disable-next-line @typescript-eslint/no-explicit-any\n              let config: Record<string, any>;\n              // eslint-disable-next-line @typescript-eslint/no-explicit-any\n              if ((ifs as any).fileSystem.existsSync(value.existConfig)) {\n                config = JSON.parse(\n                  ifs.readFileSync(value.existConfig).toString()\n                );\n              } else {\n                config = {};\n              }\n              config.component ??= value.component;\n              config.usingComponents = config.usingComponents || {};\n              config.usingComponents = {\n                ...config.usingComponents,\n                ...value.usingComponents.reduce((pre, cur) => {\n                  pre[cur.selector] = cur.path;\n                  return pre;\n                }, {} as Record<string, string>),\n              };\n              setCompilationAsset(\n                compilation,\n                key,\n                new sources.RawSource(JSON.stringify(config))\n              );\n            });\n            for (const key in metaMap.otherMetaCollectionGroup) {\n              if (\n                Object.prototype.hasOwnProperty.call(\n                  metaMap.otherMetaCollectionGroup,\n                  key\n                )\n              ) {\n                const element = metaMap.otherMetaCollectionGroup[key];\n                this.libraryTemplateScopeService.setScopeExtraUseComponents(\n                  key,\n                  {\n                    useComponents: {\n                      ...[...element.localPath, ...element.libraryPath].reduce(\n                        (pre, cur) => {\n                          pre[cur.selector] = cur.path;\n                          return pre;\n                        },\n                        {} as Record<string, string>\n                      ),\n                    },\n                    templateList: element.templateList.map(\n                      (item) => item.content\n                    ),\n                  }\n                );\n              }\n            }\n            const componentConfigGroup =\n              this.libraryTemplateScopeService.exportLibraryComponentConfig();\n            for (const item of componentConfigGroup) {\n              setCompilationAsset(\n                compilation,\n                item.filePath,\n                new sources.RawSource(JSON.stringify(item.content))\n              );\n            }\n            const templateGroup =\n              this.libraryTemplateScopeService.exportLibraryTemplate();\n            for (const key in templateGroup) {\n              if (Object.prototype.hasOwnProperty.call(templateGroup, key)) {\n                const element = templateGroup[key];\n                setCompilationAsset(\n                  compilation,\n                  key,\n                  new sources.RawSource(\n                    literalResolve<LibraryTemplateLiteralConvertOptions>(\n                      `\\`${element}\\``,\n                      {\n                        directivePrefix:\n                          this.buildPlatform.templateTransform.getData()\n                            .directivePrefix,\n                        eventListConvert:\n                          this.buildPlatform.templateTransform.eventListConvert,\n                        templateInterpolation:\n                          this.buildPlatform.templateTransform\n                            .templateInterpolation,\n                        fileExtname: this.buildPlatform.fileExtname,\n                      }\n                    )\n                  )\n                );\n              }\n            }\n\n            for (const key in metaMap.selfTemplate) {\n              if (\n                Object.prototype.hasOwnProperty.call(metaMap.selfTemplate, key)\n              ) {\n                const element = metaMap.selfTemplate[key];\n                setCompilationAsset(\n                  compilation,\n                  key,\n                  new sources.RawSource(element)\n                );\n              }\n            }\n            cb();\n          }\n        );\n        templateService.cleanDependencyFileCache();\n      }\n    );\n  }\n\n  public setEntry(pageList: PagePattern[], componentList: PagePattern[]) {\n    this.pageList = pageList;\n    this.componentList = componentList;\n  }\n  async buildTemplate(service: MiniProgramApplicationAnalysisService) {\n    try {\n      await service.analyzeAsync();\n      const result = await service.exportComponentBuildMetaMap();\n      return result;\n    } catch (error) {\n      console.error(error);\n      throw error;\n    }\n  }\n}\n"
  },
  {
    "path": "src/builder/application/schema.base.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/schema\",\n  \"title\": \"Webpack browser schema for Build Facade.\",\n  \"description\": \"Browser target options\",\n  \"type\": \"object\",\n  \"properties\": {\n    \"pages\": {\n      \"type\": \"array\",\n      \"description\": \"页面配置\",\n      \"default\": [],\n      \"items\": {\n        \"$ref\": \"#/definitions/assetPattern\"\n      }\n    },\n    \"components\": {\n      \"type\": \"array\",\n      \"description\": \"组件配置\",\n      \"default\": [],\n      \"items\": {\n        \"$ref\": \"#/definitions/assetPattern\"\n      }\n    },\n    \"platform\": {\n      \"type\": \"string\",\n      \"description\": \"小程序平台\",\n      \"default\": \"wx\"\n    }\n  },\n  \"definitions\": {\n    \"assetPattern\": {\n      \"oneOf\": [\n        {\n          \"type\": \"object\",\n          \"properties\": {\n            \"followSymlinks\": {\n              \"type\": \"boolean\",\n              \"default\": false,\n              \"description\": \"Allow glob patterns to follow symlink directories. This allows subdirectories of the symlink to be searched.\"\n            },\n            \"glob\": {\n              \"type\": \"string\",\n              \"description\": \"The pattern to match.\"\n            },\n            \"input\": {\n              \"type\": \"string\",\n              \"description\": \"The input directory path in which to apply 'glob'. Defaults to the project root.\"\n            },\n            \"ignore\": {\n              \"description\": \"An array of globs to ignore.\",\n              \"type\": \"array\",\n              \"items\": {\n                \"type\": \"string\"\n              }\n            },\n            \"output\": {\n              \"type\": \"string\",\n              \"description\": \"Absolute path within the output.\"\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\"glob\", \"input\", \"output\"]\n        },\n        {\n          \"type\": \"string\"\n        }\n      ]\n    }\n  },\n  \"additionalProperties\": false\n}\n"
  },
  {
    "path": "src/builder/application/schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema\",\n  \"title\": \"Webpack browser schema for Build Facade.\",\n  \"description\": \"Browser target options\",\n  \"type\": \"object\",\n  \"properties\": {\n    \"pages\": {\n      \"type\": \"array\",\n      \"description\": \"页面配置\",\n      \"default\": [],\n      \"items\": {\n        \"$ref\": \"#/definitions/assetPattern\"\n      }\n    },\n    \"components\": {\n      \"type\": \"array\",\n      \"description\": \"组件配置\",\n      \"default\": [],\n      \"items\": {\n        \"$ref\": \"#/definitions/assetPattern\"\n      }\n    },\n    \"platform\": {\n      \"type\": \"string\",\n      \"description\": \"小程序平台\",\n      \"default\": \"wx\"\n    },\n    \"assets\": {\n      \"type\": \"array\",\n      \"description\": \"List of static application assets.\",\n      \"default\": [],\n      \"items\": {\n        \"$ref\": \"#/definitions/assetPattern\"\n      }\n    },\n    \"main\": {\n      \"type\": \"string\",\n      \"description\": \"The full path for the main entry point to the app, relative to the current workspace.\"\n    },\n    \"polyfills\": {\n      \"type\": \"string\",\n      \"description\": \"The full path for the polyfills file, relative to the current workspace.\"\n    },\n    \"tsConfig\": {\n      \"type\": \"string\",\n      \"description\": \"The full path for the TypeScript configuration file, relative to the current workspace.\"\n    },\n    \"scripts\": {\n      \"description\": \"Global scripts to be included in the build.\",\n      \"type\": \"array\",\n      \"default\": [],\n      \"items\": {\n        \"$ref\": \"#/definitions/extraEntryPoint\"\n      }\n    },\n    \"styles\": {\n      \"description\": \"Global styles to be included in the build.\",\n      \"type\": \"array\",\n      \"default\": [],\n      \"items\": {\n        \"$ref\": \"#/definitions/extraEntryPoint\"\n      }\n    },\n    \"inlineStyleLanguage\": {\n      \"description\": \"The stylesheet language to use for the application's inline component styles.\",\n      \"type\": \"string\",\n      \"default\": \"css\",\n      \"enum\": [\"css\", \"less\", \"sass\", \"scss\"]\n    },\n    \"stylePreprocessorOptions\": {\n      \"description\": \"Options to pass to style preprocessors.\",\n      \"type\": \"object\",\n      \"properties\": {\n        \"includePaths\": {\n          \"description\": \"Paths to include. Paths will be resolved to workspace root.\",\n          \"type\": \"array\",\n          \"items\": {\n            \"type\": \"string\"\n          },\n          \"default\": []\n        }\n      },\n      \"additionalProperties\": false\n    },\n    \"optimization\": {\n      \"description\": \"Enables optimization of the build output. Including minification of scripts and styles, tree-shaking, dead-code elimination, inlining of critical CSS and fonts inlining. For more information, see https://angular.io/guide/workspace-config#optimization-configuration.\",\n      \"x-user-analytics\": 16,\n      \"default\": true,\n      \"oneOf\": [\n        {\n          \"type\": \"object\",\n          \"properties\": {\n            \"scripts\": {\n              \"type\": \"boolean\",\n              \"description\": \"Enables optimization of the scripts output.\",\n              \"default\": true\n            },\n            \"styles\": {\n              \"description\": \"Enables optimization of the styles output.\",\n              \"default\": true,\n              \"oneOf\": [\n                {\n                  \"type\": \"object\",\n                  \"properties\": {\n                    \"minify\": {\n                      \"type\": \"boolean\",\n                      \"description\": \"Minify CSS definitions by removing extraneous whitespace and comments, merging identifiers and minimizing values.\",\n                      \"default\": true\n                    },\n                    \"inlineCritical\": {\n                      \"type\": \"boolean\",\n                      \"description\": \"Extract and inline critical CSS definitions to improve first paint time.\",\n                      \"default\": true\n                    }\n                  },\n                  \"additionalProperties\": false\n                },\n                {\n                  \"type\": \"boolean\"\n                }\n              ]\n            },\n            \"fonts\": {\n              \"description\": \"Enables optimization for fonts. This option requires internet access. `HTTPS_PROXY` environment variable can be used to specify a proxy server.\",\n              \"default\": true,\n              \"oneOf\": [\n                {\n                  \"type\": \"object\",\n                  \"properties\": {\n                    \"inline\": {\n                      \"type\": \"boolean\",\n                      \"description\": \"Reduce render blocking requests by inlining external Google fonts and icons CSS definitions in the application's HTML index file. This option requires internet access. `HTTPS_PROXY` environment variable can be used to specify a proxy server.\",\n                      \"default\": true\n                    }\n                  },\n                  \"additionalProperties\": false\n                },\n                {\n                  \"type\": \"boolean\"\n                }\n              ]\n            }\n          },\n          \"additionalProperties\": false\n        },\n        {\n          \"type\": \"boolean\"\n        }\n      ]\n    },\n    \"fileReplacements\": {\n      \"description\": \"Replace compilation source files with other compilation source files in the build.\",\n      \"type\": \"array\",\n      \"items\": {\n        \"$ref\": \"#/definitions/fileReplacement\"\n      },\n      \"default\": []\n    },\n    \"outputPath\": {\n      \"type\": \"string\",\n      \"description\": \"The full path for the new output directory, relative to the current workspace.\\n\\nBy default, writes output to a folder named dist/ in the current project.\"\n    },\n    \"resourcesOutputPath\": {\n      \"type\": \"string\",\n      \"description\": \"The path where style resources will be placed, relative to outputPath.\",\n      \"default\": \"\"\n    },\n    \"aot\": {\n      \"type\": \"boolean\",\n      \"description\": \"Build using Ahead of Time compilation.\",\n      \"x-user-analytics\": 13,\n      \"default\": true\n    },\n    \"sourceMap\": {\n      \"description\": \"Output source maps for scripts and styles. For more information, see https://angular.io/guide/workspace-config#source-map-configuration.\",\n      \"default\": false,\n      \"oneOf\": [\n        {\n          \"type\": \"object\",\n          \"properties\": {\n            \"scripts\": {\n              \"type\": \"boolean\",\n              \"description\": \"Output source maps for all scripts.\",\n              \"default\": true\n            },\n            \"styles\": {\n              \"type\": \"boolean\",\n              \"description\": \"Output source maps for all styles.\",\n              \"default\": true\n            },\n            \"hidden\": {\n              \"type\": \"boolean\",\n              \"description\": \"Output source maps used for error reporting tools.\",\n              \"default\": false\n            },\n            \"vendor\": {\n              \"type\": \"boolean\",\n              \"description\": \"Resolve vendor packages source maps.\",\n              \"default\": false\n            }\n          },\n          \"additionalProperties\": false\n        },\n        {\n          \"type\": \"boolean\"\n        }\n      ]\n    },\n    \"vendorChunk\": {\n      \"type\": \"boolean\",\n      \"description\": \"Generate a seperate bundle containing only vendor libraries. This option should only used for development.\",\n      \"default\": false\n    },\n    \"commonChunk\": {\n      \"type\": \"boolean\",\n      \"description\": \"Generate a seperate bundle containing code used across multiple bundles.\",\n      \"default\": true\n    },\n    \"baseHref\": {\n      \"type\": \"string\",\n      \"description\": \"Base url for the application being built.\"\n    },\n    \"deployUrl\": {\n      \"type\": \"string\",\n      \"description\": \"URL where files will be deployed.\"\n    },\n    \"verbose\": {\n      \"type\": \"boolean\",\n      \"description\": \"Adds more details to output logging.\",\n      \"default\": false\n    },\n    \"progress\": {\n      \"type\": \"boolean\",\n      \"description\": \"Log progress to the console while building.\",\n      \"default\": true\n    },\n    \"i18nMissingTranslation\": {\n      \"type\": \"string\",\n      \"description\": \"How to handle missing translations for i18n.\",\n      \"enum\": [\"warning\", \"error\", \"ignore\"],\n      \"default\": \"warning\"\n    },\n    \"localize\": {\n      \"description\": \"Translate the bundles in one or more locales.\",\n      \"oneOf\": [\n        {\n          \"type\": \"boolean\",\n          \"description\": \"Translate all locales.\"\n        },\n        {\n          \"type\": \"array\",\n          \"description\": \"List of locales ID's to translate.\",\n          \"minItems\": 1,\n          \"items\": {\n            \"type\": \"string\",\n            \"pattern\": \"^[a-zA-Z]{2,3}(-[a-zA-Z]{4})?(-([a-zA-Z]{2}|[0-9]{3}))?(-[a-zA-Z]{5,8})?(-x(-[a-zA-Z0-9]{1,8})+)?$\"\n          }\n        }\n      ]\n    },\n    \"extractCss\": {\n      \"type\": \"boolean\",\n      \"description\": \"Extract CSS from global styles into '.css' files instead of '.js'.\",\n      \"default\": true,\n      \"x-deprecated\": \"Deprecated since version 11.0. No longer required to disable CSS extraction for HMR.\"\n    },\n    \"watch\": {\n      \"type\": \"boolean\",\n      \"description\": \"Run build when files change.\",\n      \"default\": false\n    },\n    \"outputHashing\": {\n      \"type\": \"string\",\n      \"description\": \"Define the output filename cache-busting hashing mode.\",\n      \"default\": \"none\",\n      \"enum\": [\"none\", \"all\", \"media\", \"bundles\"]\n    },\n    \"poll\": {\n      \"type\": \"number\",\n      \"description\": \"Enable and define the file watching poll time period in milliseconds.\"\n    },\n    \"deleteOutputPath\": {\n      \"type\": \"boolean\",\n      \"description\": \"Delete the output path before building.\",\n      \"default\": true\n    },\n    \"preserveSymlinks\": {\n      \"type\": \"boolean\",\n      \"description\": \"Do not use the real path when resolving modules. If unset then will default to `true` if NodeJS option --preserve-symlinks is set.\"\n    },\n    \"extractLicenses\": {\n      \"type\": \"boolean\",\n      \"description\": \"Extract all licenses in a separate file.\",\n      \"default\": true\n    },\n    \"showCircularDependencies\": {\n      \"type\": \"boolean\",\n      \"description\": \"Show circular dependency warnings on builds.\",\n      \"default\": false,\n      \"x-deprecated\": \"The recommended method to detect circular dependencies in project code is to use either a lint rule or other external tooling.\"\n    },\n    \"buildOptimizer\": {\n      \"type\": \"boolean\",\n      \"description\": \"Enables '@angular-devkit/build-optimizer' optimizations when using the 'aot' option.\",\n      \"default\": true\n    },\n    \"namedChunks\": {\n      \"type\": \"boolean\",\n      \"description\": \"Use file name for lazy loaded chunks.\",\n      \"default\": false\n    },\n    \"subresourceIntegrity\": {\n      \"type\": \"boolean\",\n      \"description\": \"Enables the use of subresource integrity validation.\",\n      \"default\": false\n    },\n    \"serviceWorker\": {\n      \"type\": \"boolean\",\n      \"description\": \"Generates a service worker config for production builds.\",\n      \"default\": false\n    },\n    \"ngswConfigPath\": {\n      \"type\": \"string\",\n      \"description\": \"Path to ngsw-config.json.\"\n    },\n    \"index\": {\n      \"description\": \"Configures the generation of the application's HTML index.\",\n      \"oneOf\": [\n        {\n          \"type\": \"string\",\n          \"description\": \"The path of a file to use for the application's HTML index. The filename of the specified path will be used for the generated file and will be created in the root of the application's configured output path.\"\n        },\n        {\n          \"type\": \"object\",\n          \"description\": \"\",\n          \"properties\": {\n            \"input\": {\n              \"type\": \"string\",\n              \"minLength\": 1,\n              \"description\": \"The path of a file to use for the application's generated HTML index.\"\n            },\n            \"output\": {\n              \"type\": \"string\",\n              \"minLength\": 1,\n              \"default\": \"index.html\",\n              \"description\": \"The output path of the application's generated HTML index file. The full provided path will be used and will be considered relative to the application's configured output path.\"\n            }\n          },\n          \"required\": [\"input\"]\n        }\n      ]\n    },\n    \"statsJson\": {\n      \"type\": \"boolean\",\n      \"description\": \"Generates a 'stats.json' file which can be analyzed using tools such as 'webpack-bundle-analyzer'.\",\n      \"default\": false\n    },\n    \"budgets\": {\n      \"description\": \"Budget thresholds to ensure parts of your application stay within boundaries which you set.\",\n      \"type\": \"array\",\n      \"items\": {\n        \"$ref\": \"#/definitions/budget\"\n      },\n      \"default\": []\n    },\n    \"webWorkerTsConfig\": {\n      \"type\": \"string\",\n      \"description\": \"TypeScript configuration for Web Worker modules.\"\n    },\n    \"crossOrigin\": {\n      \"type\": \"string\",\n      \"description\": \"Define the crossorigin attribute setting of elements that provide CORS support.\",\n      \"default\": \"none\",\n      \"enum\": [\"none\", \"anonymous\", \"use-credentials\"]\n    },\n    \"allowedCommonJsDependencies\": {\n      \"description\": \"A list of CommonJS packages that are allowed to be used without a build time warning.\",\n      \"type\": \"array\",\n      \"items\": {\n        \"type\": \"string\"\n      },\n      \"default\": []\n    }\n  },\n  \"additionalProperties\": false,\n  \"required\": [\"outputPath\", \"index\", \"main\", \"tsConfig\"],\n  \"definitions\": {\n    \"assetPattern\": {\n      \"oneOf\": [\n        {\n          \"type\": \"object\",\n          \"properties\": {\n            \"followSymlinks\": {\n              \"type\": \"boolean\",\n              \"default\": false,\n              \"description\": \"Allow glob patterns to follow symlink directories. This allows subdirectories of the symlink to be searched.\"\n            },\n            \"glob\": {\n              \"type\": \"string\",\n              \"description\": \"The pattern to match.\"\n            },\n            \"input\": {\n              \"type\": \"string\",\n              \"description\": \"The input directory path in which to apply 'glob'. Defaults to the project root.\"\n            },\n            \"ignore\": {\n              \"description\": \"An array of globs to ignore.\",\n              \"type\": \"array\",\n              \"items\": {\n                \"type\": \"string\"\n              }\n            },\n            \"output\": {\n              \"type\": \"string\",\n              \"description\": \"Absolute path within the output.\"\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\"glob\", \"input\", \"output\"]\n        },\n        {\n          \"type\": \"string\"\n        }\n      ]\n    },\n    \"fileReplacement\": {\n      \"oneOf\": [\n        {\n          \"type\": \"object\",\n          \"properties\": {\n            \"src\": {\n              \"type\": \"string\",\n              \"pattern\": \"\\\\.(([cm]?j|t)sx?|json)$\"\n            },\n            \"replaceWith\": {\n              \"type\": \"string\",\n              \"pattern\": \"\\\\.(([cm]?j|t)sx?|json)$\"\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\"src\", \"replaceWith\"]\n        },\n        {\n          \"type\": \"object\",\n          \"properties\": {\n            \"replace\": {\n              \"type\": \"string\",\n              \"pattern\": \"\\\\.(([cm]?j|t)sx?|json)$\"\n            },\n            \"with\": {\n              \"type\": \"string\",\n              \"pattern\": \"\\\\.(([cm]?j|t)sx?|json)$\"\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\"replace\", \"with\"]\n        }\n      ]\n    },\n    \"extraEntryPoint\": {\n      \"oneOf\": [\n        {\n          \"type\": \"object\",\n          \"properties\": {\n            \"input\": {\n              \"type\": \"string\",\n              \"description\": \"The file to include.\"\n            },\n            \"bundleName\": {\n              \"type\": \"string\",\n              \"pattern\": \"^[\\\\w\\\\-.]*$\",\n              \"description\": \"The bundle name for this extra entry point.\"\n            },\n            \"inject\": {\n              \"type\": \"boolean\",\n              \"description\": \"If the bundle will be referenced in the HTML file.\",\n              \"default\": true\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\"input\"]\n        },\n        {\n          \"type\": \"string\",\n          \"description\": \"The file to include.\"\n        }\n      ]\n    },\n    \"budget\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"type\": \"string\",\n          \"description\": \"The type of budget.\",\n          \"enum\": [\n            \"all\",\n            \"allScript\",\n            \"any\",\n            \"anyScript\",\n            \"anyComponentStyle\",\n            \"bundle\",\n            \"initial\"\n          ]\n        },\n        \"name\": {\n          \"type\": \"string\",\n          \"description\": \"The name of the bundle.\"\n        },\n        \"baseline\": {\n          \"type\": \"string\",\n          \"description\": \"The baseline size for comparison.\"\n        },\n        \"maximumWarning\": {\n          \"type\": \"string\",\n          \"description\": \"The maximum threshold for warning relative to the baseline.\"\n        },\n        \"maximumError\": {\n          \"type\": \"string\",\n          \"description\": \"The maximum threshold for error relative to the baseline.\"\n        },\n        \"minimumWarning\": {\n          \"type\": \"string\",\n          \"description\": \"The minimum threshold for warning relative to the baseline.\"\n        },\n        \"minimumError\": {\n          \"type\": \"string\",\n          \"description\": \"The minimum threshold for error relative to the baseline.\"\n        },\n        \"warning\": {\n          \"type\": \"string\",\n          \"description\": \"The threshold for warning relative to the baseline (min & max).\"\n        },\n        \"error\": {\n          \"type\": \"string\",\n          \"description\": \"The threshold for error relative to the baseline (min & max).\"\n        }\n      },\n      \"additionalProperties\": false,\n      \"required\": [\"type\"]\n    }\n  }\n}\n"
  },
  {
    "path": "src/builder/application/token.ts",
    "content": "import { InjectionToken } from 'static-injector';\n\nexport const TS_CONFIG_TOKEN = new InjectionToken('TS_CONFIG_TOKEN');\nexport const PAGE_PATTERN_TOKEN = new InjectionToken('PAGE_PATTERN_TOKEN');\nexport const OLD_BUILDER = new InjectionToken('OLD_BUILDER');\nexport const TS_SYSTEM = new InjectionToken('TS_SYSTEM');\nexport const WEBPACK_COMPILATION = new InjectionToken('WEBPACK_COMPILATION');\nexport const WEBPACK_COMPILER = new InjectionToken('WEBPACK_COMPILER');\n"
  },
  {
    "path": "src/builder/application/type.ts",
    "content": "import type { AssetPattern } from '@angular-devkit/build-angular';\nimport { LibraryComponentEntryMeta } from '../library';\nimport { BuildPlatform, PlatformFileExtname } from '../platform';\n\nexport interface LibraryTemplateLiteralConvertOptions {\n  directivePrefix: string;\n  eventListConvert: (name: string[]) => string;\n  templateInterpolation: [string, string];\n  fileExtname: PlatformFileExtname;\n}\n\nexport interface PagePattern extends Exclude<AssetPattern, string> {\n  /** 入口名 */\n  entryName: string;\n  /** 匹配文件,相对于input */\n  fileName: string;\n  /** 要输出的js出口 */\n  output: string;\n  /** 绝对路径,path.join */\n  src: string;\n  outputFiles: {\n    content: string;\n    style: string;\n    logic: string;\n    path: string;\n    config: string;\n  };\n  inputFiles: {\n    config: string;\n  };\n  type: 'component' | 'page';\n}\n\nexport interface LibraryLoaderContext {\n  libraryMetaList: LibraryComponentEntryMeta[];\n  buildPlatform: BuildPlatform;\n}\n"
  },
  {
    "path": "src/builder/application/util/index.ts",
    "content": "export * from './set-compilation-asset';\n"
  },
  {
    "path": "src/builder/application/util/set-compilation-asset.ts",
    "content": "import * as webpack from 'webpack';\n\nexport function setCompilationAsset(\n  compilation: webpack.Compilation,\n  key: string,\n  content: webpack.sources.Source\n) {\n  if (compilation.getAsset(key)) {\n    compilation.updateAsset(key, content, {});\n  } else {\n    compilation.emitAsset(key, content, {});\n  }\n}\n"
  },
  {
    "path": "src/builder/application/webpack-configuration-change.service.ts",
    "content": "import type { BuilderContext } from '@angular-devkit/architect';\nimport {\n  AssetPattern,\n  BrowserBuilderOptions,\n  KarmaBuilderOptions,\n} from '@angular-devkit/build-angular';\nimport { normalize } from '@angular-devkit/core';\nimport * as path from 'path';\nimport { filter } from 'rxjs/operators';\nimport { Injectable, Injector } from 'static-injector';\nimport * as webpack from 'webpack';\nimport { DefinePlugin } from 'webpack';\nimport { BootstrapAssetsPlugin } from 'webpack-bootstrap-assets-plugin';\nimport { LIBRARY_OUTPUT_ROOTDIR } from '../library';\nimport { BuildPlatform } from '../platform/platform';\nimport type { PlatformType } from '../platform/platform';\nimport { LibraryTemplateScopeService } from './library-template-scope.service';\nimport { DynamicLibraryComponentEntryPlugin } from './plugin/dynamic-library-entry.plugin';\nimport { DynamicWatchEntryPlugin } from './plugin/dynamic-watch-entry.plugin';\nimport { ExportMiniProgramAssetsPlugin } from './plugin/export-mini-program-assets.plugin';\nimport { TS_CONFIG_TOKEN } from './token';\nimport type { PagePattern } from './type';\n\ntype OptimizationOptions = NonNullable<webpack.Configuration['optimization']>;\ntype OptimizationSplitChunksOptions = Exclude<\n  OptimizationOptions['splitChunks'],\n  false | undefined\n>;\ntype OptimizationSplitChunksCacheGroup = Exclude<\n  NonNullable<OptimizationSplitChunksOptions['cacheGroups']>[''],\n  false | string | Function | RegExp\n>;\n@Injectable()\nexport class WebpackConfigurationChangeService {\n  exportMiniProgramAssetsPluginInstance!: ExportMiniProgramAssetsPlugin;\n  private buildPlatform!: BuildPlatform;\n  private entryList!: PagePattern[];\n  constructor(\n    private options: (BrowserBuilderOptions | KarmaBuilderOptions) & {\n      pages: AssetPattern[];\n      components: AssetPattern[];\n      platform: PlatformType;\n    },\n    private context: BuilderContext,\n    private config: webpack.Configuration,\n    private injector: Injector\n  ) {}\n  init() {\n    this.injector = Injector.create({\n      parent: this.injector,\n      providers: [\n        { provide: ExportMiniProgramAssetsPlugin },\n        { provide: LibraryTemplateScopeService },\n        {\n          provide: TS_CONFIG_TOKEN,\n          useValue: path.resolve(\n            this.context.workspaceRoot,\n            this.options.tsConfig\n          ),\n        },\n        {\n          provide: DynamicWatchEntryPlugin,\n          deps: [BuildPlatform],\n          useFactory: (buildPlatform: BuildPlatform) => {\n            return new DynamicWatchEntryPlugin(\n              {\n                pages: this.options.pages,\n                components: this.options.components,\n                workspaceRoot: normalize(this.context.workspaceRoot),\n                context: this.context,\n                config: this.config,\n              },\n              buildPlatform\n            );\n          },\n        },\n        { provide: DynamicLibraryComponentEntryPlugin },\n      ],\n    });\n    this.buildPlatform = this.injector.get(BuildPlatform);\n    this.buildPlatform.fileExtname.config =\n      this.buildPlatform.fileExtname.config || '.json';\n    this.config.output!.globalObject = this.buildPlatform.globalObject;\n  }\n  async change() {\n    this.buildPlatformCompatible();\n    this.exportAssets();\n    await this.pageHandle();\n    this.addLoader();\n    this.globalVariableChange();\n    this.changeStylesExportSuffix();\n    this.config.plugins?.push(\n      this.injector.get(DynamicLibraryComponentEntryPlugin)\n    );\n    this.config.plugins?.push(\n      new webpack.NormalModuleReplacementPlugin(\n        /^angular-miniprogram\\/platform\\/wx$/,\n        `angular-miniprogram/platform/${this.buildPlatform.packageName}`\n      )\n    );\n  }\n  private buildPlatformCompatible() {\n    if (this.buildPlatform.packageName == 'zfb') {\n      this.config.resolve?.conditionNames?.shift();\n      this.config.resolve?.mainFields?.shift();\n    }\n  }\n  private async pageHandle() {\n    const dynamicWatchEntryInstance = this.injector.get(\n      DynamicWatchEntryPlugin\n    );\n    await dynamicWatchEntryInstance.init();\n    dynamicWatchEntryInstance.entryPattern$\n      .pipe(filter((item) => !!item))\n      .subscribe((result) => {\n        this.entryList = [...result!.pageList, ...result!.componentList];\n        this.exportMiniProgramAssetsPluginInstance.setEntry(\n          result!.pageList,\n          result!.componentList\n        );\n      });\n    this.config.plugins?.push(dynamicWatchEntryInstance);\n    // 出口\n    const oldFileName = this.config.output!.filename as string;\n    this.config.output!.filename = (chunkData) => {\n      const page = this.entryList.find(\n        (item) => item.entryName === chunkData.chunk!.name\n      );\n      if (page) {\n        return page.outputFiles.logic;\n      }\n      return oldFileName;\n    };\n    // 共享依赖\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\n    const oldChunks = (this.config.optimization!.splitChunks as any).cacheGroups\n      .defaultVendors.chunks;\n    (\n      (\n        this.config.optimization!\n          .splitChunks! as unknown as OptimizationSplitChunksOptions\n      ).cacheGroups!.defaultVendors as OptimizationSplitChunksCacheGroup\n    ).chunks = (chunk) => {\n      if (\n        this.entryList.find((item) => item.entryName === chunk.name) ||\n        chunk.name!.startsWith(`${LIBRARY_OUTPUT_ROOTDIR}/`)\n      ) {\n        return true;\n      }\n      return oldChunks(chunk);\n    };\n    ((this.config.optimization!.splitChunks as OptimizationSplitChunksOptions)\n      .cacheGroups!['moduleChunks'] as OptimizationSplitChunksCacheGroup) = {\n      test: (module: webpack.NormalModule) => {\n        const name = module.nameForCondition();\n        return (\n          (name &&\n            name.endsWith('.ts') &&\n            !/[\\\\/]node_modules[\\\\/]/.test(name)) ||\n          name?.includes('angular-miniprogram\\\\dist')\n        );\n      },\n      minChunks: 2,\n      minSize: 0,\n      name: 'module-chunk',\n      chunks: 'all',\n    };\n    // 出口保留必要加载\n    const assetsPlugin = new BootstrapAssetsPlugin();\n    assetsPlugin.hooks.removeChunk.tap('pageHandle', (chunk) => {\n      if (\n        this.entryList.some((page) => page.entryName === chunk.name) ||\n        [...chunk.files].some((file) =>\n          file.endsWith(this.buildPlatform.fileExtname.style)\n        ) ||\n        chunk.name!.startsWith(`${LIBRARY_OUTPUT_ROOTDIR}/`)\n      ) {\n        return true;\n      }\n      return false;\n    });\n    assetsPlugin.hooks.emitAssets.tap('pageHandle', (object, json) => {\n      return {\n        'app.js':\n          this.buildPlatform.importTemplate +\n          json.scripts.map((item) => `require('./${item.src}')`).join(';'),\n      };\n    });\n    this.config.plugins!.push(assetsPlugin);\n  }\n  private exportAssets() {\n    this.exportMiniProgramAssetsPluginInstance = this.injector.get(\n      ExportMiniProgramAssetsPlugin\n    );\n    this.config.plugins!.unshift(this.exportMiniProgramAssetsPluginInstance);\n  }\n\n  private addLoader() {\n    this.config.module!.rules!.unshift({\n      test: /\\.ts$/,\n      loader: require.resolve(\n        path.join(__dirname, './loader/component-template.loader')\n      ),\n    });\n    this.config.module?.rules?.unshift({\n      test: /\\.mjs$/,\n      loader: require.resolve(path.join(__dirname, './loader/library.loader')),\n    });\n    this.config.module?.rules?.unshift({\n      test: /\\.mjs$/,\n      loader: require.resolve(\n        path.join(__dirname, './loader/library-template.loader')\n      ),\n    });\n  }\n  private globalVariableChange() {\n    const defineObject: Record<string, string> = {\n      global: `${this.buildPlatform.globalObject}.__global`,\n      window: `${this.buildPlatform.globalVariablePrefix}`,\n      globalThis: `${this.buildPlatform.globalVariablePrefix}`,\n      Zone: `${this.buildPlatform.globalVariablePrefix}.Zone`,\n      setTimeout: `${this.buildPlatform.globalVariablePrefix}.setTimeout`,\n      clearTimeout: `${this.buildPlatform.globalVariablePrefix}.clearTimeout`,\n      setInterval: `${this.buildPlatform.globalVariablePrefix}.setInterval`,\n      clearInterval: `${this.buildPlatform.globalVariablePrefix}.clearInterval`,\n      Promise: `${this.buildPlatform.globalVariablePrefix}.Promise`,\n      Reflect: `${this.buildPlatform.globalVariablePrefix}.Reflect`,\n      requestAnimationFrame: `${this.buildPlatform.globalVariablePrefix}.requestAnimationFrame`,\n      cancelAnimationFrame: `${this.buildPlatform.globalVariablePrefix}.cancelAnimationFrame`,\n      performance: `${this.buildPlatform.globalVariablePrefix}.performance`,\n      navigator: `${this.buildPlatform.globalVariablePrefix}.navigator`,\n      wx: this.buildPlatform.globalObject,\n      miniProgramPlatform: `\"${this.buildPlatform.globalObject}\"`,\n      queueMicrotask:`${this.buildPlatform.globalVariablePrefix}.queueMicrotask`\n    };\n    if (this.config.mode === 'development') {\n      defineObject[\n        'ngDevMode'\n      ] = `${this.buildPlatform.globalObject}.__global.ngDevMode`;\n    }\n    this.config.plugins!.push(new DefinePlugin(defineObject));\n  }\n  private changeStylesExportSuffix() {\n    const index = this.config.plugins!.findIndex(\n      (plugin) =>\n        Object.getPrototypeOf(plugin).constructor.name ===\n        'MiniCssExtractPlugin'\n    );\n    if (index > -1) {\n      // eslint-disable-next-line @typescript-eslint/no-explicit-any\n      const pluginInstance = this.config.plugins![index] as any;\n      const pluginPrototype = Object.getPrototypeOf(pluginInstance);\n      this.config.plugins?.splice(\n        index,\n        1,\n        new pluginPrototype.constructor({\n          filename: 'app' + this.buildPlatform.fileExtname.style,\n        })\n      );\n    } else {\n      throw new Error('没有找到MiniCssExtractPlugin插件,无法修改生成style');\n    }\n  }\n}\n"
  },
  {
    "path": "src/builder/builder.prod.spec.ts",
    "content": "import { join, normalize } from '@angular-devkit/core';\nimport {\n  MyTestProjectHost,\n  describeBuilder,\n  setWorkspaceRoot,\n} from '../../test/plugin-describe-builder';\nimport {\n  BROWSER_BUILDER_INFO,\n  DEFAULT_ANGULAR_CONFIG,\n} from '../../test/test-builder';\nimport {\n  ALL_COMPONENT_NAME_LIST,\n  ALL_PAGE_NAME_LIST,\n} from '../../test/util/file';\nimport { runBuilder } from './application';\nimport { PlatformType } from './platform/platform';\n\nconst angularConfig = {\n  ...DEFAULT_ANGULAR_CONFIG,\n  platform: PlatformType.wx,\n  buildOptimizer: true,\n  optimization: true,\n  extractLicenses: true,\n};\n\ndescribeBuilder(runBuilder, BROWSER_BUILDER_INFO, (harness) => {\n  describe('builder-prod', () => {\n    it('运行', async () => {\n      const root = harness.host.root();\n      const myTestProjectHost = new MyTestProjectHost(harness.host);\n\n      const list = await myTestProjectHost.getFileList(\n        normalize(join(root, 'src', '__pages'))\n      );\n      list.push(\n        ...(await myTestProjectHost.getFileList(\n          normalize(join(root, 'src', '__components'))\n        ))\n      );\n      await myTestProjectHost.importPathRename(list);\n      await myTestProjectHost.moveDir(ALL_PAGE_NAME_LIST, '__pages', 'pages');\n      await myTestProjectHost.moveDir(\n        ALL_COMPONENT_NAME_LIST,\n        '__components',\n        'components'\n      );\n      await myTestProjectHost.addPageEntry(ALL_PAGE_NAME_LIST);\n      harness.useTarget('build', angularConfig);\n      const result = await harness.executeOnce();\n      expect(result).toBeTruthy();\n      expect(result.error).toBeFalsy();\n      expect(result.logs[0].level !== 'error').toBeTruthy();\n      expect(result.result?.success).toBeTruthy();\n    });\n  });\n});\n"
  },
  {
    "path": "src/builder/builder.spec.ts",
    "content": "import { join, normalize } from '@angular-devkit/core';\nimport * as fs from 'fs-extra';\nimport * as path from 'path';\nimport { Injector } from 'static-injector';\nimport {\n  MyTestProjectHost,\n  describeBuilder,\n  setWorkspaceRoot,\n} from '../../test/plugin-describe-builder';\nimport {\n  BROWSER_BUILDER_INFO,\n  DEFAULT_ANGULAR_CONFIG,\n} from '../../test/test-builder';\nimport {\n  ALL_COMPONENT_NAME_LIST,\n  ALL_PAGE_NAME_LIST,\n  TEST_LIBRARY_COMPONENT_LIST,\n} from '../../test/util/file';\nimport { runBuilder } from './application';\nimport { LIBRARY_OUTPUT_ROOTDIR } from './library';\nimport { BuildPlatform, PlatformType } from './platform/platform';\nimport { getBuildPlatformInjectConfig } from './platform/platform-inject-config';\n\nconst angularConfig = {\n  ...DEFAULT_ANGULAR_CONFIG,\n  platform: PlatformType.wx,\n  sourceMap: false,\n  // buildOptimizer: true,\n  // optimization: true,\n};\ndescribeBuilder(runBuilder, BROWSER_BUILDER_INFO, (harness) => {\n  describe('builder-dev', () => {\n    for (const platform of [\n      PlatformType.wx,\n      PlatformType.bdzn,\n      PlatformType.dd,\n      PlatformType.jd,\n      PlatformType.qq,\n      PlatformType.zfb,\n      PlatformType.zj,\n    ]) {\n      it(`运行${PlatformType[platform]}`, async () => {\n        angularConfig.platform = platform;\n        const root = harness.host.root();\n        const myTestProjectHost = new MyTestProjectHost(harness.host);\n        const list = await myTestProjectHost.getFileList(\n          normalize(join(root, 'src', '__pages'))\n        );\n        list.push(\n          ...(await myTestProjectHost.getFileList(\n            normalize(join(root, 'src', '__components'))\n          ))\n        );\n        await myTestProjectHost.importPathRename(list);\n        await myTestProjectHost.moveDir(ALL_PAGE_NAME_LIST, '__pages', 'pages');\n        await myTestProjectHost.moveDir(\n          ALL_COMPONENT_NAME_LIST,\n          '__components',\n          'components'\n        );\n        await myTestProjectHost.addPageEntry(ALL_PAGE_NAME_LIST);\n        harness.useTarget('build', angularConfig);\n        const result = await harness.executeOnce();\n        expect(result).toBeTruthy();\n        expect(result.error).toBeFalsy();\n        expect(result.logs[0].level !== 'error').toBeTruthy();\n        expect(result.result?.success).toBeTruthy();\n        const injectList = getBuildPlatformInjectConfig(angularConfig.platform);\n        const injector = Injector.create({ providers: injectList });\n        const buildPlatform = injector.get(BuildPlatform);\n        harness\n          .expectFile(\n            join(\n              normalize(DEFAULT_ANGULAR_CONFIG.outputPath),\n              `app${buildPlatform.fileExtname.style}`\n            )\n          )\n          .toExist();\n        const libraryPath = join(\n          normalize(DEFAULT_ANGULAR_CONFIG.outputPath),\n          LIBRARY_OUTPUT_ROOTDIR,\n          'test-library'\n        );\n        const librarySelfTemplateFile = harness.expectFile(\n          join(libraryPath, `self${buildPlatform.fileExtname.contentTemplate}`)\n        );\n        librarySelfTemplateFile.toExist();\n        librarySelfTemplateFile.content.toContain(`$$mp$$__self__$$`);\n        TEST_LIBRARY_COMPONENT_LIST.forEach((item) => {\n          const componentPath = join(libraryPath, item, item);\n          harness\n            .expectFile(componentPath + buildPlatform.fileExtname.logic)\n            .toExist();\n          harness\n            .expectFile(\n              componentPath + (buildPlatform.fileExtname.config || '.json')\n            )\n            .toExist();\n          harness\n            .expectFile(componentPath + buildPlatform.fileExtname.content)\n            .toExist();\n        });\n        const realTestPath: string = result.result?.baseOutputPath as string;\n        const appTestPath = path.resolve(process.cwd(), '__test-app');\n        fs.copySync(realTestPath, path.resolve(process.cwd(), '__test-app'));\n        // ('等待断点放开');\n        fs.removeSync(appTestPath);\n      });\n    }\n  });\n});\n"
  },
  {
    "path": "src/builder/builder.watch.spec.ts",
    "content": "import { join, normalize } from '@angular-devkit/core';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { of } from 'rxjs';\nimport { concatMap, skip, take } from 'rxjs/operators';\nimport {\n  MyTestProjectHost,\n  describeBuilder,\n  setWorkspaceRoot,\n} from '../../test/plugin-describe-builder';\nimport {\n  BROWSER_BUILDER_INFO,\n  DEFAULT_ANGULAR_CONFIG,\n} from '../../test/test-builder';\nimport {\n  ALL_COMPONENT_NAME_LIST,\n  ALL_PAGE_NAME_LIST,\n} from '../../test/util/file';\nimport { runBuilder } from './application';\nimport { PlatformType } from './platform/platform';\n\nconst angularConfig = {\n  ...DEFAULT_ANGULAR_CONFIG,\n  platform: PlatformType.wx,\n  watch: true,\n};\ndescribeBuilder(\n  runBuilder,\n  { ...BROWSER_BUILDER_INFO, name: 'test-builder:watch' },\n  (harness) => {\n    describe('builder-watch-dev', () => {\n      it('运行', async () => {\n        const root = harness.host.root();\n        const myTestProjectHost = new MyTestProjectHost(harness.host);\n\n        const list = await myTestProjectHost.getFileList(\n          normalize(join(root, 'src', '__pages'))\n        );\n        list.push(\n          ...(await myTestProjectHost.getFileList(\n            normalize(join(root, 'src', '__components'))\n          ))\n        );\n        await myTestProjectHost.importPathRename(list);\n        await myTestProjectHost.moveDir(ALL_PAGE_NAME_LIST, '__pages', 'pages');\n        await myTestProjectHost.moveDir(\n          ALL_COMPONENT_NAME_LIST,\n          '__components',\n          'components'\n        );\n        await myTestProjectHost.addPageEntry(ALL_PAGE_NAME_LIST);\n        let finish: Function;\n        const waitFinish = new Promise((res) => {\n          finish = res;\n        });\n        harness.useTarget('build', angularConfig);\n        harness\n          .execute()\n          .pipe(\n            concatMap((result, index) => {\n              if (index) {\n                return of(result);\n              }\n              const value = JSON.parse(harness.readFile('src/app.json'));\n              value.pages.push(`pages/sub3/sub3-entry`);\n              const data = readFixture('watch/sub3', 'src/pages/sub3');\n              harness\n                .writeFiles({\n                  'src/app.json': JSON.stringify(value),\n                  ...data,\n                })\n                .then(\n                  (res) => {},\n                  (rej) => {\n                    throw rej;\n                  }\n                );\n              return of(result);\n            }),\n            take(2),\n            skip(1)\n          )\n          .subscribe((result) => {\n            expect(result.logs[0].level !== 'error').toBeTruthy();\n            expect(result).toBeTruthy();\n            expect(result.error).toBeFalsy();\n            expect(result.result?.success).toBeTruthy();\n            expect(result.logs[0].message).toContain('sub3-entry.js');\n            harness\n              .expectFile(\n                join(\n                  normalize(DEFAULT_ANGULAR_CONFIG.outputPath),\n                  'pages/sub3/sub3-entry.js'\n                )\n              )\n              .toExist();\n            harness\n              .expectFile(\n                join(\n                  normalize(DEFAULT_ANGULAR_CONFIG.outputPath),\n                  'pages/sub3/sub3-entry.json'\n                )\n              )\n              .toExist();\n            harness\n              .expectFile(\n                join(\n                  normalize(DEFAULT_ANGULAR_CONFIG.outputPath),\n                  'pages/sub3/sub3-entry.wxml'\n                )\n              )\n              .toExist();\n            harness\n              .expectFile(\n                join(\n                  normalize(DEFAULT_ANGULAR_CONFIG.outputPath),\n                  'pages/sub3/sub3-entry.wxss'\n                )\n              )\n              .toExist();\n            harness\n              .expectFile(\n                join(\n                  normalize(DEFAULT_ANGULAR_CONFIG.outputPath),\n                  'library/test-library/lib-comp1-component/lib-comp1-component.js'\n                )\n              )\n              .toExist();\n            finish();\n          });\n        await waitFinish;\n      });\n    });\n  }\n);\nfunction readFixture(dir: string, to: string) {\n  const dirPath = path.resolve(__dirname, 'test/fixture', dir);\n  const list = fs.readdirSync(dirPath);\n  const fileObject: Record<string, string> = {};\n  for (const item of list) {\n    const filePath = path.resolve(dirPath, item);\n    const content = fs.readFileSync(filePath, { encoding: 'utf8' });\n    fileObject[`${path.posix.join(to, item)}`] = content;\n  }\n  return fileObject;\n}\n"
  },
  {
    "path": "src/builder/builders.json",
    "content": "{\n  \"$schema\": \"../../node_modules/@angular-devkit/architect/src/builders-schema.json\",\n  \"builders\": {\n    \"application\": {\n      \"implementation\": \"./application\",\n      \"schema\": \"./application/schema.json\",\n      \"description\": \"小程序构建builder\"\n    },\n    \"library\": {\n      \"implementation\": \"./library/builder\",\n      \"schema\": \"./library/schema.json\",\n      \"description\": \"小程序构建library\"\n    },\n    \"karma\": {\n      \"implementation\": \"./karma\",\n      \"schema\": \"./karma/schema.json\",\n      \"description\": \"小程序测试\"\n    }\n  }\n}\n"
  },
  {
    "path": "src/builder/component-template-inject/change-component.ts",
    "content": "import {\n  Change,\n  InsertChange,\n  TsChange,\n  createCssSelectorForTs,\n} from 'cyia-code-util';\nimport * as ts from 'typescript';\nimport { RawUpdater } from '../util';\n\nexport function changeComponent(data: string) {\n  const sf = ts.createSourceFile('', data, ts.ScriptTarget.Latest, true);\n  const selector = createCssSelectorForTs(sf);\n\n  const ɵcmpNodeList = selector.queryAll(\n    `PropertyAccessExpression[name=ɵɵdefineComponent]~SyntaxList ObjectLiteralExpression`\n  ) as ts.BinaryExpression[];\n  if (!ɵcmpNodeList.length) {\n    return undefined;\n  }\n  const changeList: Change[] = [];\n  for (const componentNode of ɵcmpNodeList) {\n    const ɵcmpNode = componentNode;\n\n    const templateNode = selector.queryOne(\n      ɵcmpNode,\n      `PropertyAssignment[name=template]::initializer`\n    ) as ts.PropertyAssignment;\n    const initIfNode = selector.queryOne(\n      templateNode,\n      `IfStatement[expression=\"rf & 1\"]`\n    ) as ts.IfStatement;\n    if (!initIfNode) {\n      continue;\n    }\n    const change = new TsChange(sf);\n\n    let updateInsertChange: InsertChange;\n    changeList.push(\n      new InsertChange(0, `import * as amp from 'angular-miniprogram';\\n`)\n    );\n    changeList.push(\n      new InsertChange(0, `import * as ampNgCore from '@angular/core';\\n`)\n    );\n    const updateIfNode = selector.queryOne(\n      templateNode,\n      `IfStatement[expression=\"rf & 2\"]`\n    ) as ts.IfStatement;\n    const updateContent = `amp.propertyChange(ampNgCore.ɵɵgetCurrentView());`;\n    if (updateIfNode) {\n      const updateBlock = updateIfNode.thenStatement as ts.Block;\n      updateInsertChange = change.insertNode(\n        updateBlock.statements[updateBlock.statements.length - 1],\n        `;${updateContent}`,\n        'end'\n      );\n    } else {\n      updateInsertChange = change.insertNode(\n        initIfNode,\n        `if(rf & 2){${updateContent}}`,\n        'end'\n      );\n    }\n    changeList.push(updateInsertChange);\n  }\n  return {\n    content: RawUpdater.update(data, changeList),\n    // todo library可否支持同文件多组件\n    componentName: selector\n      .queryOne(ɵcmpNodeList[0], 'PropertyAssignment[name=type]::initializer')\n      .getText(),\n  };\n}\n"
  },
  {
    "path": "src/builder/karma/client/adapter.ts",
    "content": "import { KarmaClient } from './karma';\n\n// Save link to native Date object\n// before it might be mocked by the user\nconst _Date = Date;\n\n/**\n * Decision maker for whether a stack entry is considered external to jasmine and karma.\n * @param  {String}  entry Error stack entry.\n * @return {Boolean}       True if external, False otherwise.\n */\nfunction isExternalStackEntry(entry: string) {\n  return (\n    !!entry &&\n    // entries related to jasmine and karma-jasmine:\n    !/\\/(jasmine-core|karma-jasmine)\\//.test(entry) &&\n    // karma specifics, e.g. \"at http://localhost:7018/karma.js:185\"\n    !/\\/(karma.js|context.html):/.test(entry)\n  );\n}\n\n/**\n * Returns relevant stack entries.\n * @param  {Array} stack frames\n * @return {Array}        A list of relevant stack entries.\n */\nfunction getRelevantStackFrom(stack: string[]): string[] {\n  let filteredStack: string[] = [];\n  const relevantStack: string[] = [];\n\n  for (let i = 0; i < stack.length; i += 1) {\n    if (isExternalStackEntry(stack[i])) {\n      filteredStack.push(stack[i]);\n    }\n  }\n\n  // If the filtered stack is empty, i.e. the error originated entirely from within jasmine or karma, then the whole stack\n  // should be relevant.\n  if (filteredStack.length === 0) {\n    filteredStack = stack;\n  }\n\n  for (let i = 0; i < filteredStack.length; i += 1) {\n    if (filteredStack[i]) {\n      relevantStack.push(filteredStack[i]);\n    }\n  }\n\n  return relevantStack;\n}\n\n/**\n * Custom formatter for a failed step.\n *\n * Different browsers report stack trace in different ways. This function\n * attempts to provide a concise, relevant error message by removing the\n * unnecessary stack traces coming from the testing framework itself as well\n * as possible repetition.\n *\n * @see    https://github.com/karma-runner/karma-jasmine/issues/60\n * @param  {Object} step Step object with stack and message properties.\n * @return {String}      Formatted step.\n */\nfunction formatFailedStep(step: Record<string, any>): string {\n  const relevantMessage: string[] = [];\n  const relevantStack: string[] = [];\n\n  // Safari/Firefox seems to have no stack trace,\n  // so we just return the error message and if available\n  // construct a stacktrace out of filename and lineno:\n  if (!step.stack) {\n    if (step.filename) {\n      let stackframe: string = step.filename;\n      if (step.lineno) {\n        stackframe = stackframe + ':' + step.lineno;\n      }\n      relevantStack.push(stackframe);\n    }\n    relevantMessage.push(step.message);\n    return relevantMessage.concat(relevantStack).join('\\n');\n  }\n\n  // Remove the message prior to processing the stack to prevent issues like\n  // https://github.com/karma-runner/karma-jasmine/issues/79\n  const stackframes = step.stack.split('\\n');\n  let messageOnStack = null;\n  if (stackframes[0].indexOf(step.message) !== -1) {\n    // Remove the message if it is in the stack string (eg Chrome)\n    messageOnStack = stackframes.shift();\n  }\n  // Filter frames\n  const relevantStackFrames = getRelevantStackFrom(stackframes);\n  if (messageOnStack) {\n    // Put the message back if we removed it.\n    relevantStackFrames.unshift(messageOnStack);\n  } else {\n    // The stack did not have the step.message so add it.\n    relevantStackFrames.unshift(step.message);\n  }\n\n  return relevantStackFrames.join('\\n');\n}\n\nclass SuiteNode {\n  constructor(public name?: string, public parent?: SuiteNode) {}\n  description!: string;\n  children: any[] = [];\n\n  addChild(name: string) {\n    const suite = new SuiteNode(name, this);\n    this.children.push(suite);\n    return suite;\n  }\n}\n\nfunction processSuite(suite: SuiteNode, pointer: Record<string, any>) {\n  let child;\n  let childPointer;\n\n  for (let i = 0; i < suite.children.length; i++) {\n    child = suite.children[i];\n\n    if (child.children) {\n      childPointer = pointer[child.description] = { _: [] };\n      processSuite(child, childPointer);\n    } else {\n      if (!pointer._) {\n        pointer._ = [];\n      }\n      pointer._.push(child.description);\n    }\n  }\n}\n\nfunction getAllSpecNames(topSuite: SuiteNode) {\n  const specNames = {};\n\n  processSuite(topSuite, specNames);\n\n  return specNames;\n}\n\n/**\n * Very simple reporter for Jasmine.\n */\nclass KarmaReporter implements jasmine.CustomReporter {\n  currentSuite = new SuiteNode();\n\n  startTimeCurrentSpec = new _Date().getTime();\n\n  constructor(private tc: KarmaClient, private jasmineEnv: jasmine.Env) {}\n  handleGlobalErrors(result: Record<string, any>) {\n    if (result.failedExpectations && result.failedExpectations.length) {\n      let message: string = 'An error was thrown in afterAll';\n      const steps = result.failedExpectations;\n      for (let i = 0, l = steps.length; i < l; i++) {\n        message += '\\n' + formatFailedStep(steps[i]);\n      }\n\n      this.tc.error(message);\n    }\n  }\n\n  /**\n   * Jasmine 2.0 dispatches the following events:\n   *\n   *  - jasmineStarted\n   *  - jasmineDone\n   *  - suiteStarted\n   *  - suiteDone\n   *  - specStarted\n   *  - specDone\n   */\n\n  jasmineStarted(data: Record<string, any>) {\n    // TODO(vojta): Do not send spec names when polling.\n    this.tc.info({\n      event: 'jasmineStarted',\n      total: data.totalSpecsDefined,\n      specs: getAllSpecNames(this.jasmineEnv.topSuite() as any),\n    });\n  }\n\n  jasmineDone(result: Record<string, any>) {\n    result = result || {};\n\n    // Any errors in top-level afterAll blocks are given here.\n    this.handleGlobalErrors(result);\n\n    // Remove functions from called back results to avoid IPC errors in Electron\n    // https://github.com/twolfson/karma-electron/issues/47\n    let cleanedOrder!: Record<string, any>;\n    if (result.order) {\n      cleanedOrder = {};\n      const orderKeys = Object.getOwnPropertyNames(result.order);\n      for (let i = 0; i < orderKeys.length; i++) {\n        const orderKey = orderKeys[i];\n        if (typeof result.order[orderKey] !== 'function') {\n          cleanedOrder[orderKey] = result.order[orderKey];\n        }\n      }\n    }\n    // todo 单元测试覆盖率移除\n    this.tc.complete({\n      order: cleanedOrder,\n      coverage: undefined,\n    });\n  }\n\n  suiteStarted(result: Record<string, any>) {\n    this.currentSuite = this.currentSuite.addChild(result.description);\n    this.tc.info({\n      event: 'suiteStarted',\n      result: result,\n    });\n  }\n\n  suiteDone(result: Record<string, any>) {\n    // In the case of xdescribe, only \"suiteDone\" is fired.\n    // We need to skip that.\n    if (result.description !== this.currentSuite.name) {\n      return;\n    }\n\n    // Any errors in afterAll blocks are given here, except for top-level\n    // afterAll blocks.\n    this.handleGlobalErrors(result);\n\n    this.currentSuite = this.currentSuite.parent!;\n\n    this.tc.info({\n      event: 'suiteDone',\n      result: result,\n    });\n  }\n\n  specStarted() {\n    this.startTimeCurrentSpec = new _Date().getTime();\n  }\n\n  specDone(specResult: Record<string, any>) {\n    const skipped =\n      specResult.status === 'disabled' ||\n      specResult.status === 'pending' ||\n      specResult.status === 'excluded';\n    const result = {\n      fullName: specResult.fullName,\n      description: specResult.description,\n      id: specResult.id,\n      log: [] as string[],\n      skipped: skipped,\n      disabled:\n        specResult.status === 'disabled' || specResult.status === 'excluded',\n      pending: specResult.status === 'pending',\n      success: specResult.failedExpectations.length === 0,\n      suite: [] as string[],\n      time: skipped ? 0 : new _Date().getTime() - this.startTimeCurrentSpec,\n      executedExpectationsCount:\n        specResult.failedExpectations.length +\n        specResult.passedExpectations.length,\n      passedExpectations: specResult.passedExpectations,\n      properties: specResult.properties,\n    };\n\n    // generate ordered list of (nested) suite names\n    let suitePointer = this.currentSuite;\n    while (suitePointer.parent) {\n      result.suite.unshift(suitePointer.name!);\n      suitePointer = suitePointer.parent;\n    }\n\n    if (!result.success) {\n      const steps = specResult.failedExpectations;\n      for (let i = 0, l = steps.length; i < l; i++) {\n        result.log.push(formatFailedStep(steps[i]));\n      }\n\n      // todo 永远不可能赋值当前\n      // Report the name of fhe failing spec so the reporter can emit a debug url.\n      // (result as any).debug_url = debugUrl(specResult.fullName);\n    }\n\n    // When failSpecWithNoExpectations is true, Jasmine will report specs without expectations as failed\n    if (\n      result.executedExpectationsCount === 0 &&\n      specResult.status === 'failed'\n    ) {\n      result.success = false;\n      result.log.push('Spec has no expectations');\n    }\n\n    this.tc.result(result);\n    delete specResult.startTime;\n  }\n}\n\n/**\n * Extract grep option from karma config\n * @param {[Array|string]} clientArguments The karma client arguments\n * @return {string} The value of grep option by default empty string\n */\nconst getGrepOption = function (clientArguments: any[] | string) {\n  const grepRegex = /^--grep=(.*)$/;\n\n  if (Object.prototype.toString.call(clientArguments) === '[object Array]') {\n    const indexOfGrep = indexOf(clientArguments as any[], '--grep');\n\n    if (indexOfGrep !== -1) {\n      return clientArguments[indexOfGrep + 1];\n    }\n\n    return (\n      map(\n        filter(clientArguments as any[], function (arg: string) {\n          return grepRegex.test(arg);\n        }),\n        function (arg) {\n          return arg.replace(grepRegex, '$1');\n        }\n      )[0] || ''\n    );\n  } else if (typeof clientArguments === 'string') {\n    const match = /--grep=([^=]+)/.exec(clientArguments);\n\n    return match ? match[1] : '';\n  }\n};\n\nconst createRegExp = function (filter: string) {\n  filter = filter || '';\n  if (filter === '') {\n    return new RegExp(''); // to match all\n  }\n\n  const regExp = /^[/](.*)[/]([gmixXsuUAJD]*)$/; // pattern to check whether the string is RegExp pattern\n\n  const parts = regExp.exec(filter);\n  if (parts === null) {\n    return new RegExp(filter.replace(/[-[\\]{}()*+?.,\\\\^$|#\\s]/g, '\\\\$&')); // escape functional symbols\n  }\n\n  const patternExpression = parts[1];\n  const patternSwitches = parts[2];\n  return new RegExp(patternExpression, patternSwitches);\n};\n\nfunction getGrepSpecsToRun(clientConfig: Record<string, any>, specs: any[]) {\n  const grepOption = getGrepOption(clientConfig.args);\n  if (grepOption) {\n    const regExp = createRegExp(grepOption);\n    return filter(specs, function specFilter(spec: any) {\n      return regExp.test(spec.getFullName());\n    });\n  }\n}\n\nfunction parseQueryParams(location: Record<string, any>) {\n  const params: Record<string, any> = {};\n  if (location && Object.prototype.hasOwnProperty.call(location, 'search')) {\n    const pairs = location.search.substr(1).split('&');\n    for (let i = 0; i < pairs.length; i++) {\n      const keyValue = pairs[i].split('=');\n      params[decodeURIComponent(keyValue[0])] = decodeURIComponent(keyValue[1]);\n    }\n  }\n  return params;\n}\n\nfunction getId(s: { id: any }) {\n  return s.id;\n}\n\nfunction getSpecsByName(specs: any[], name: string) {\n  specs = specs.filter(function (s) {\n    return s.name.indexOf(name) !== -1;\n  });\n  if (specs.length === 0) {\n    throw new Error('No spec found with name: \"' + name + '\"');\n  }\n  return specs;\n}\n\nfunction getDebugSpecToRun(location: Record<string, any>, specs: any[]) {\n  const queryParams: Record<string, any> = parseQueryParams(location);\n  const spec = queryParams.spec;\n  if (spec) {\n    // A single spec has been requested by name for debugging.\n    return getSpecsByName(specs, spec);\n  }\n}\n\nfunction getSpecsToRunForCurrentShard(\n  specs: any[],\n  shardIndex: number,\n  totalShards: number\n) {\n  if (specs.length < totalShards) {\n    throw new Error(\n      'More shards (' + totalShards + ') than test specs (' + specs.length + ')'\n    );\n  }\n\n  // Just do a simple sharding strategy of dividing the number of specs\n  // equally.\n  const firstSpec = Math.floor((specs.length * shardIndex) / totalShards);\n  const lastSpec = Math.floor((specs.length * (shardIndex + 1)) / totalShards);\n  return specs.slice(firstSpec, lastSpec);\n}\n\nfunction getShardedSpecsToRun(specs: any[], clientConfig: Record<string, any>) {\n  const shardIndex = clientConfig.shardIndex;\n  const totalShards = clientConfig.totalShards;\n  if (shardIndex != null && totalShards != null) {\n    // Sharded mode - Run only the subset of the specs corresponding to the\n    // current shard.\n    return getSpecsToRunForCurrentShard(\n      specs,\n      Number(shardIndex),\n      Number(totalShards)\n    );\n  }\n}\n\n/**\n * Create jasmine spec filter\n * @param {Object} clientConfig karma config\n * @param {!Object} jasmineEnv\n */\nclass KarmaSpecFilter {\n  specIdsToRun: any[];\n  constructor(\n    private clientConfig: Record<string, any>,\n    private jasmineEnv: jasmine.Env\n  ) {\n    this.specIdsToRun = this.getSpecsToRun(\n      undefined as any,\n      this.clientConfig,\n      this.jasmineEnv\n    ).map(getId);\n  }\n  /**\n   * Walk the test suite tree depth first and collect all test specs\n   * @param {!Object} jasmineEnv\n   * @return {!Array<string>} All possible tests.\n   */\n  getAllSpecs(jasmineEnv: jasmine.Env) {\n    const specs: (jasmine.Suite | jasmine.Spec)[] = [];\n    let stack = [jasmineEnv.topSuite()];\n    let currentNode: jasmine.Suite;\n    while ((currentNode = stack.pop()!)) {\n      if (currentNode.children) {\n        // jasmine.Suite\n        stack = stack.concat(currentNode.children as jasmine.Suite[]);\n      } else if (currentNode.id) {\n        // jasmine.Spec\n        specs.unshift(currentNode);\n      }\n    }\n\n    return specs;\n  }\n\n  /**\n   * Filter the specs with URL search params and config.\n   * @param {!Object} location property 'search' from URL.\n   * @param {!Object} clientConfig karma client config\n   * @param {!Object} jasmineEnv\n   * @return {!Array<string>}\n   */\n  getSpecsToRun(\n    location: Record<string, any>,\n    clientConfig: Record<string, any>,\n    jasmineEnv: jasmine.Env\n  ) {\n    const specs = this.getAllSpecs(jasmineEnv).map(function (spec) {\n      (spec as any).name = spec.getFullName();\n      return spec;\n    });\n\n    if (!specs || !specs.length) {\n      return [];\n    }\n\n    return (\n      getGrepSpecsToRun(clientConfig, specs) ||\n      getDebugSpecToRun(location, specs) ||\n      getShardedSpecsToRun(specs, clientConfig) ||\n      specs\n    );\n  }\n\n  matches(spec: jasmine.Suite) {\n    return this.specIdsToRun.indexOf(spec.id) !== -1;\n  }\n}\n\n/**\n * Configure jasmine specFilter\n *\n * This function is invoked from the wrapper.\n * @see  adapter.wrapper\n *\n * @param {Object} config The karma config\n * @param {Object} jasmineEnv jasmine environment object\n */\nconst createSpecFilter = function (\n  config: Record<string, any>,\n  jasmineEnv: jasmine.Env\n) {\n  const karmaSpecFilter = new KarmaSpecFilter(config, jasmineEnv);\n\n  const specFilter = function (spec: jasmine.Suite) {\n    return karmaSpecFilter.matches(spec);\n  };\n\n  return specFilter;\n};\n\n/**\n * Karma starter function factory.\n *\n * This function is invoked from the wrapper.\n * @see  adapter.wrapper\n *\n * @param  {Object}   karma        Karma runner instance.\n * @param  {Object}   [jasmineEnv] Optional Jasmine environment for testing.\n * @return {Function}              Karma starter function.\n */\nexport function createStartFn(karma: KarmaClient, jasmineEnv: jasmine.Env) {\n  // This function will be assigned to `window.__karma__.start`:\n  return function () {\n    const clientConfig = {\n      args: [],\n      useIframe: true,\n      runInParent: false,\n      captureConsole: true,\n      clearContext: false,\n      jasmine: {},\n      originalArgs: [],\n    };\n    const jasmineConfig = clientConfig.jasmine || {};\n\n    jasmineEnv = jasmineEnv || jasmine.getEnv();\n\n    (jasmineConfig as any).specFilter = createSpecFilter(\n      clientConfig,\n      jasmineEnv\n    );\n\n    jasmineEnv.configure(jasmineConfig);\n\n    jasmine.DEFAULT_TIMEOUT_INTERVAL =\n      (jasmineConfig as any).timeoutInterval ||\n      jasmine.DEFAULT_TIMEOUT_INTERVAL;\n    jasmineEnv.addReporter(new KarmaReporter(karma, jasmineEnv));\n    jasmineEnv.execute();\n  };\n}\n\nfunction indexOf(collection: any[], find: any, i?: number /* opt */) {\n  if (collection.indexOf) {\n    return collection.indexOf(find, i);\n  }\n\n  if (i === undefined) {\n    i = 0;\n  }\n  if (i < 0) {\n    i += collection.length;\n  }\n  if (i < 0) {\n    i = 0;\n  }\n  for (let n = collection.length; i < n; i++) {\n    if (i in collection && collection[i] === find) {\n      return i;\n    }\n  }\n  return -1;\n}\n\nfunction filter(collection: any[], filter: any, that?: any /* opt */) {\n  if (collection.filter) {\n    return collection.filter(filter, that);\n  }\n\n  const other: any[] = [];\n  let v: any;\n  for (let i = 0, n = collection.length; i < n; i++) {\n    if (\n      i in collection &&\n      filter.call(that, (v = collection[i]), i, collection)\n    ) {\n      other.push(v);\n    }\n  }\n  return other;\n}\n\nfunction map(\n  collection: any[],\n  mapper: (value: any, index: number, array: any[]) => any,\n  that?: any /* opt */\n) {\n  if (collection.map) {\n    return collection.map(mapper, that);\n  }\n\n  const other = new Array(collection.length);\n  for (let i = 0, n = collection.length; i < n; i++) {\n    if (i in collection) {\n      other[i] = mapper.call(that, collection[i], i, collection);\n    }\n  }\n  return other;\n}\n"
  },
  {
    "path": "src/builder/karma/client/index.ts",
    "content": "export * from './main';\n"
  },
  {
    "path": "src/builder/karma/client/karma.ts",
    "content": "import { IO } from './platform';\nimport { StatusUpdater } from './updater';\n\nexport class KarmaClient {\n  /** 是否正式发射判断? */\n  private startEmitted = false;\n\n  public config: Record<string, any> = {};\n  /** socket重连接标记 */\n  private socketReconnect = false;\n  private resultsBufferLimit = 50;\n  private resultsBuffer: any[] = [];\n  private returnUrl!: string;\n  readonly id: string = 'miniprogram';\n  constructor(private updater: StatusUpdater, private socket: IO) {\n    socket.on('execute', (cfg) => {\n      this.updater.updateTestStatus('execute');\n      // reset startEmitted and reload the iframe\n      this.startEmitted = false;\n      this.config = cfg;\n    });\n    socket.on('stop', () => {\n      this.complete();\n    });\n\n    // 初始化的时候自动有这个.\n    socket.on('connect', () => {\n      socket.emit('register', {\n        name: '小程序',\n        id: this.id,\n        isSocketReconnect: this.socketReconnect,\n      });\n      this.socketReconnect = true;\n    });\n  }\n  private navigateContextTo(url: string) {}\n  log(type: string, args: any[]) {\n    const values: any[] = [];\n\n    for (let i = 0; i < args.length; i++) {\n      values.push(JSON.stringify(args[i]));\n    }\n\n    this.info({ log: values.join(', '), type: type });\n  }\n\n  private getLocation(url?: string, lineno?: string, colno?: string) {\n    let location = '';\n\n    if (url !== undefined) {\n      location += url;\n    }\n\n    if (lineno !== undefined) {\n      location += ':' + lineno;\n    }\n\n    if (colno !== undefined) {\n      location += ':' + colno;\n    }\n\n    return location;\n  }\n\n  error(\n    messageOrEvent: string | Error,\n    source?: string,\n    lineno?: string,\n    colno?: string,\n    error?: Error\n  ) {\n    let message: string | Record<string, any>;\n    if (typeof messageOrEvent === 'string') {\n      message = messageOrEvent;\n\n      const location = this.getLocation(source, lineno, colno);\n      if (location !== '') {\n        message += '\\nat ' + location;\n      }\n      if (error && error.stack) {\n        message += '\\n\\n' + error.stack;\n      }\n    } else {\n      // create an object with the string representation of the message to\n      // ensure all its content is properly transferred to the console log\n      message = { message: messageOrEvent, str: messageOrEvent.toString() };\n    }\n\n    this.socket.emit('karma_error', message);\n    this.updater.updateTestStatus('karma_error ' + message);\n    this.complete();\n    return false;\n  }\n  result(originalResult: Record<string, any>) {\n    const convertedResult: Record<string, any> = {};\n\n    // Convert all array-like objects to real arrays.\n    for (const propertyName in originalResult) {\n      if (Object.prototype.hasOwnProperty.call(originalResult, propertyName)) {\n        const propertyValue = originalResult[propertyName];\n\n        if (\n          Object.prototype.toString.call(propertyValue) === '[object Array]'\n        ) {\n          convertedResult[propertyName] =\n            Array.prototype.slice.call(propertyValue);\n        } else {\n          convertedResult[propertyName] = propertyValue;\n        }\n      }\n    }\n\n    if (!this.startEmitted) {\n      this.socket.emit('start', { total: null });\n      this.updater.updateTestStatus('start');\n      this.startEmitted = true;\n    }\n\n    if (this.resultsBufferLimit === 1) {\n      this.updater.updateTestStatus('result');\n      return this.socket.emit('result', convertedResult);\n    }\n\n    this.resultsBuffer.push(convertedResult);\n\n    if (this.resultsBuffer.length === this.resultsBufferLimit) {\n      this.socket.emit('result', this.resultsBuffer);\n      this.updater.updateTestStatus('result');\n      this.resultsBuffer = [];\n    }\n  }\n\n  complete(result?: Record<string, any>) {\n    if (this.resultsBuffer.length) {\n      this.socket.emit('result', this.resultsBuffer);\n      this.resultsBuffer = [];\n    }\n\n    this.socket.emit('complete', result || {});\n    if (this.config.clearContext) {\n      this.navigateContextTo('about:blank');\n    } else {\n      this.updater.updateTestStatus('complete');\n    }\n    if (this.returnUrl) {\n      let isReturnUrlAllowed = false;\n      for (let i = 0; i < this.config.allowedReturnUrlPatterns.length; i++) {\n        const allowedReturnUrlPattern = new RegExp(\n          this.config.allowedReturnUrlPatterns[i]\n        );\n        if (allowedReturnUrlPattern.test(this.returnUrl)) {\n          isReturnUrlAllowed = true;\n          break;\n        }\n      }\n      if (!isReturnUrlAllowed) {\n        throw new Error(\n          'Security: Navigation to '.concat(\n            this.returnUrl,\n            ' was blocked to prevent malicious exploits.'\n          )\n        );\n      }\n    }\n  }\n  /** 可以直接使用 */\n  info(info: any) {\n    // TODO(vojta): introduce special API for this\n    if (!this.startEmitted && info.total) {\n      this.socket.emit('start', info);\n      this.startEmitted = true;\n    } else {\n      this.socket.emit('info', info);\n    }\n  }\n}\n"
  },
  {
    "path": "src/builder/karma/client/main.ts",
    "content": "import { createStartFn } from './adapter';\nimport { KarmaClient } from './karma';\nimport { IO } from './platform';\nimport { StatusUpdater } from './updater';\n\ndeclare const KARMA_CLIENT_CONFIG: any;\nexport function startupTest() {\n  const socket = new IO();\n  const updater = new StatusUpdater(socket);\n  const karmaClient = new KarmaClient(updater, socket);\n  if (KARMA_CLIENT_CONFIG.captureConsole) {\n    // patch the console\n    const localConsole = console || {\n      log: function () {},\n      info: function () {},\n      warn: function () {},\n      error: function () {},\n      debug: function () {},\n    };\n    const logMethods: (keyof Console)[] = [\n      'log',\n      'info',\n      'warn',\n      'error',\n      'debug',\n    ];\n    const patchConsoleMethod = function (method: keyof Console) {\n      const orig = localConsole[method];\n      if (!orig) {\n        return;\n      }\n      localConsole[method] = function () {\n        try {\n          return Function.prototype.apply.call(orig, localConsole, arguments);\n        } catch (error) {\n          karmaClient.log('warn', [\n            'Console method ' + method + ' threw: ' + error,\n          ]);\n        }\n        karmaClient.log(method, Array.from(arguments));\n      } as any;\n    };\n    for (let i = 0; i < logMethods.length; i++) {\n      patchConsoleMethod(logMethods[i]);\n    }\n  }\n  createStartFn(karmaClient, jasmine.getEnv())();\n}\n"
  },
  {
    "path": "src/builder/karma/client/platform/index.ts",
    "content": "export * from './wx';\n"
  },
  {
    "path": "src/builder/karma/client/platform/wx/index.ts",
    "content": "/// <reference types=\"miniprogram-api-typings\" />\n\nimport type { Socket } from 'socket.io-client';\n\nconst io = require('weapp.socket.io/lib/weapp.socket.io');\n\ndeclare const KARMA_PORT: number;\nexport class IO {\n  instance: Socket;\n  constructor() {\n    this.instance = io(`http://localhost:${KARMA_PORT}`);\n  }\n  on(data: string, callback: (...args: any[]) => void) {\n    this.instance.on(data, (...args) => {\n      callback(...args);\n    });\n  }\n  emit(type: string, data: any) {\n    this.instance.emit(type, data);\n  }\n}\n"
  },
  {
    "path": "src/builder/karma/client/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"outDir\": \"../../../../dist/karma/client\",\n    \"strict\": false,\n    \"strictNullChecks\": false,\n    \"allowUnreachableCode\": true,\n    \"noUnusedParameters\": false,\n    \"sourceMap\": true,\n    \"declaration\": true,\n    \"target\": \"ES2021\",\n    \"module\": \"CommonJS\",\n    \"lib\": [\"ES2021\"],\n    \"skipLibCheck\": true\n  },\n  \"files\": [\"index.ts\"]\n}\n"
  },
  {
    "path": "src/builder/karma/client/updater.ts",
    "content": "import { IO } from './platform';\n\nexport class StatusUpdater {\n  private connectionText = 'never-connected';\n  private testText = 'loading';\n  private pingText = '';\n  constructor(private socket: IO) {\n    socket.on('connect', () => {\n      this.updateConnectionStatus('connected');\n    });\n    socket.on('disconnect', () => {\n      this.updateConnectionStatus('disconnected');\n    });\n    socket.on('reconnecting', (sec) => {\n      this.updateConnectionStatus('reconnecting in ' + sec + ' seconds');\n    });\n    socket.on('reconnect', () => {\n      this.updateConnectionStatus('reconnected');\n    });\n    socket.on('reconnect_failed', () => {\n      this.updateConnectionStatus('reconnect_failed');\n    });\n\n    socket.on('info', () => this.updateBrowsersInfo([]));\n    socket.on('disconnect', () => {\n      this.updateBrowsersInfo([]);\n    });\n\n    socket.on('ping', () => {\n      this.updatePingStatus('ping...');\n    });\n    socket.on('pong', (latency) => {\n      this.updatePingStatus('ping ' + latency + 'ms');\n    });\n  }\n  private updateBrowsersInfo(browsers: any[]) {}\n  private updateBanner() {}\n\n  private updateConnectionStatus(connectionStatus: string) {\n    this.connectionText = connectionStatus || this.connectionText;\n    this.updateBanner();\n  }\n  updateTestStatus(testStatus: string) {\n    this.testText = testStatus || this.testText;\n    this.updateBanner();\n  }\n  private updatePingStatus(pingStatus: string) {\n    this.pingText = pingStatus || this.pingText;\n    this.updateBanner();\n  }\n}\n"
  },
  {
    "path": "src/builder/karma/index.origin.ts",
    "content": "/* eslint-disable @typescript-eslint/no-explicit-any */\n/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {\n  BuilderContext,\n  BuilderOutput,\n  createBuilder,\n} from '@angular-devkit/architect';\nimport {\n  BrowserBuilderOptions,\n  OutputHashing,\n} from '@angular-devkit/build-angular';\nimport type {\n  ExecutionTransformer,\n  KarmaBuilderOptions,\n} from '@angular-devkit/build-angular';\nimport { FindTestsPlugin } from '@angular-devkit/build-angular/src/builders/karma/find-tests-plugin';\nimport {\n  getCommonConfig,\n  getStylesConfig,\n} from '@angular-devkit/build-angular/src/tools/webpack/configs';\nimport { purgeStaleBuildCache } from '@angular-devkit/build-angular/src/utils/purge-cache';\nimport { assertCompatibleAngularVersion } from '@angular-devkit/build-angular/src/utils/version';\nimport { generateBrowserWebpackConfigFromContext } from '@angular-devkit/build-angular/src/utils/webpack-browser-config';\n\nimport { Config, ConfigOptions } from 'karma';\nimport * as path from 'path';\nimport { dirname, resolve } from 'path';\nimport { Observable, from } from 'rxjs';\nimport { defaultIfEmpty, switchMap } from 'rxjs/operators';\nimport type { Configuration } from 'webpack';\n\nexport type KarmaConfigOptions = ConfigOptions & {\n  buildWebpack?: unknown;\n  configFile?: string;\n};\n\nasync function initialize(\n  options: KarmaBuilderOptions,\n  context: BuilderContext,\n  webpackConfigurationTransformer?: ExecutionTransformer<Configuration>\n): Promise<[typeof import('karma'), Configuration]> {\n  // Purge old build disk cache.\n  await purgeStaleBuildCache(context);\n  const { config } = await generateBrowserWebpackConfigFromContext(\n    // only two properties are missing:\n    // * `outputPath` which is fixed for tests\n    // * `budgets` which might be incorrect due to extra dev libs\n    {\n      ...(options as unknown as BrowserBuilderOptions),\n      outputPath: '',\n      budgets: undefined,\n      optimization: false,\n      buildOptimizer: false,\n      aot: true,\n      vendorChunk: true,\n      namedChunks: true,\n      extractLicenses: false,\n      outputHashing: OutputHashing.None,\n      // The webpack tier owns the watch behavior so we want to force it in the config.\n      // When not in watch mode, webpack-dev-middleware will call `compiler.watch` anyway.\n      // https://github.com/webpack/webpack-dev-middleware/blob/698c9ae5e9bb9a013985add6189ff21c1a1ec185/src/index.js#L65\n      // https://github.com/webpack/webpack/blob/cde1b73e12eb8a77eb9ba42e7920c9ec5d29c2c9/lib/Compiler.js#L379-L388\n      watch: true,\n    },\n    context,\n    (wco) => [\n      getCommonConfig(wco),\n      // getBrowserConfig(wco),\n      getStylesConfig(wco),\n      // getTypeScriptConfig(wco),\n    ]\n  );\n\n  const karma = await import('karma');\n\n  return [\n    karma,\n    webpackConfigurationTransformer\n      ? await webpackConfigurationTransformer(config)\n      : config,\n  ];\n}\n\n/**\n * @experimental Direct usage of this function is considered experimental.\n */\nexport function execute(\n  options: KarmaBuilderOptions,\n  context: BuilderContext,\n  transforms: {\n    webpackConfiguration?: ExecutionTransformer<Configuration>;\n    // The karma options transform cannot be async without a refactor of the builder implementation\n    karmaOptions?: (options: KarmaConfigOptions) => KarmaConfigOptions;\n  } = {}\n): Observable<BuilderOutput> {\n  // Check Angular version.\n  assertCompatibleAngularVersion(context.workspaceRoot);\n\n  let singleRun: boolean | undefined;\n  if (options.watch !== undefined) {\n    singleRun = !options.watch;\n  }\n\n  return from(\n    initialize(options, context, transforms.webpackConfiguration)\n  ).pipe(\n    switchMap(async ([karma, webpackConfig]) => {\n      const karmaOptions: KarmaConfigOptions = {\n        singleRun,\n      };\n\n      // Convert browsers from a string to an array\n      if (options.browsers) {\n        karmaOptions.browsers = (options.browsers as string)!.split(',');\n      }\n\n      if (options.reporters) {\n        // Split along commas to make it more natural, and remove empty strings.\n        const reporters = options.reporters\n          .reduce<string[]>((acc, curr) => acc.concat(curr.split(',')), [])\n          .filter((x) => !!x);\n\n        if (reporters.length > 0) {\n          karmaOptions.reporters = reporters;\n        }\n      }\n\n      const projectName = context.target?.project;\n      if (!projectName) {\n        throw new Error('The builder requires a target.');\n      }\n      const projectMetadata = await context.getProjectMetadata(projectName);\n      const sourceRoot = (projectMetadata.sourceRoot ??\n        projectMetadata.root ??\n        '') as string;\n\n      webpackConfig.plugins ??= [];\n      webpackConfig.plugins.push(\n        new FindTestsPlugin({\n          // include: options.include,\n          workspaceRoot: context.workspaceRoot,\n          projectSourceRoot: path.join(context.workspaceRoot, sourceRoot),\n        })\n      );\n      karmaOptions.buildWebpack = {\n        options,\n        webpackConfig,\n        logger: context.logger,\n      };\n\n      const config = await karma.config.parseConfig(\n        resolve(context.workspaceRoot, options.karmaConfig!),\n        transforms.karmaOptions\n          ? transforms.karmaOptions(karmaOptions)\n          : karmaOptions,\n        { promiseConfig: true, throwErrors: true }\n      );\n\n      return [karma, config] as [typeof karma, KarmaConfigOptions];\n    }),\n    switchMap(\n      ([karma, karmaConfig]) =>\n        new Observable<BuilderOutput>((subscriber) => {\n          // Pass onto Karma to emit BuildEvents.\n          karmaConfig.buildWebpack ??= {};\n          if (typeof karmaConfig.buildWebpack === 'object') {\n            (karmaConfig.buildWebpack as any).failureCb ??= () =>\n              subscriber.next({ success: false });\n            (karmaConfig.buildWebpack as any).successCb ??= () =>\n              subscriber.next({ success: true });\n            (karmaConfig.buildWebpack as any).testContext = (\n              context as any\n            ).testContext;\n          }\n\n          // Complete the observable once the Karma server returns.\n          const karmaServer = new karma.Server(\n            karmaConfig as Config,\n            (exitCode) => {\n              subscriber.next({ success: exitCode === 0 });\n              subscriber.complete();\n            }\n          );\n\n          const karmaStart = karmaServer.start();\n\n          // Cleanup, signal Karma to exit.\n          return () => karmaStart.then(() => karmaServer.stop());\n        })\n    ),\n    defaultIfEmpty({ success: false })\n  );\n}\n\nexport { KarmaBuilderOptions };\nexport default createBuilder<Record<string, string> & KarmaBuilderOptions>(\n  execute\n);\n"
  },
  {
    "path": "src/builder/karma/index.spec.ts",
    "content": "import { BuilderOutput } from '@angular-devkit/architect';\nimport { join, normalize } from '@angular-devkit/core';\nimport * as fs from 'fs-extra';\nimport * as path from 'path';\nimport {\n  BuilderHarnessExecutionResult,\n  MyTestProjectHost,\n  describeBuilder,\n} from '../../../test/plugin-describe-builder';\nimport {\n  DEFAULT_ANGULAR_KARMA_CONFIG,\n  KARMA_BUILDER_INFO,\n} from '../../../test/test-builder';\nimport { runBuilder } from './index';\n\nconst angularConfig = {\n  ...DEFAULT_ANGULAR_KARMA_CONFIG,\n  watch: true,\n};\ndescribeBuilder(runBuilder, KARMA_BUILDER_INFO, (harness) => {\n  // 此测试仅能本地使用,并且只能一个测试用例单独开启\n  xdescribe('karma', () => {\n    it('运行', async () => {\n      const root = harness.host.root();\n      const myTestProjectHost = new MyTestProjectHost(harness.host);\n      await myTestProjectHost.addSpecEntry([\n        'empty',\n        'tag-view-convert-spec',\n        'style-class-spec',\n        'life-time-spec',\n        'ng-if-spec',\n        'http-spec',\n        'ng-content-spec',\n        'ng-for-spec',\n        'ng-library-import-spec',\n        'ng-switch-spec',\n        'ng-template-outlet-spec',\n        'self-template-spec',\n      ]);\n      harness.useTarget('build', angularConfig);\n      let appTestPath: string;\n      const result = new Promise<BuilderHarnessExecutionResult<BuilderOutput>>(\n        (res) => {\n          let result;\n          harness\n            .execute({\n              testContext: {\n                buildSuccess: async (webpackConfig) => {\n                  const realTestPath: string = webpackConfig.output!\n                    .path as string;\n                  appTestPath = path.resolve(process.cwd(), '__test-app');\n                  fs.removeSync(appTestPath);\n                  fs.copySync(realTestPath, appTestPath);\n                },\n              },\n            })\n            .subscribe({\n              next: (value) => (result = value),\n              complete: () => res(result),\n            });\n        }\n      );\n      await result;\n      expect((await result).error).toBe(undefined);\n      expect((await result).result.success).toBe(true);\n      fs.removeSync(appTestPath);\n    });\n\n    xit('watch', async () => {\n      const root = harness.host.root();\n      const myTestProjectHost = new MyTestProjectHost(harness.host);\n      await myTestProjectHost.addSpecEntry([\n        'empty',\n        'tag-view-convert-spec',\n        'style-class-spec',\n        'life-time-spec',\n        'ng-if-spec',\n        'http-spec',\n        'ng-content-spec',\n        'ng-for-spec',\n        'ng-library-import-spec',\n        'ng-switch-spec',\n        'ng-template-outlet-spec',\n        'self-template-spec',\n      ]);\n      harness.useTarget('build', { ...angularConfig, watch: true });\n      let appTestPath: string;\n      const result = new Promise<BuilderHarnessExecutionResult<BuilderOutput>>(\n        (res) => {\n          let first = true;\n          harness\n            .execute({\n              testContext: {\n                buildSuccess: async (webpackConfig) => {\n                  const realTestPath: string = webpackConfig.output!\n                    .path as string;\n                  appTestPath = path.resolve(process.cwd(), '__test-app');\n                  if (!first) {\n                    fs.removeSync(appTestPath);\n                    fs.copySync(realTestPath, appTestPath);\n                    return;\n                  }\n                  first = false;\n                  fs.removeSync(appTestPath);\n                  fs.copySync(realTestPath, appTestPath);\n                  setTimeout(async () => {\n                    await writeFile();\n                  }, 0);\n                },\n              },\n            })\n            .subscribe({\n              next: (value) => res(value),\n            });\n        }\n      );\n      await result;\n      expect((await result).error).toBe(undefined);\n      expect((await result).result.success).toBe(true);\n      fs.removeSync(appTestPath);\n    });\n  });\n\n  function writeFile() {\n    const fileContent = harness.readFile('src/spec/ng-if-spec/ng-if.spec.ts');\n\n    return harness.writeFiles({\n      'src/spec/ng-if-spec/ng-if.spec.ts': `${fileContent}\n      describe('test-add',()=>{it('main',()=>{expect(true).toBe(true)})});`,\n    });\n  }\n});\n"
  },
  {
    "path": "src/builder/karma/index.ts",
    "content": "import { BuilderContext, createBuilder } from '@angular-devkit/architect';\nimport {\n  AssetPattern,\n  KarmaBuilderOptions,\n} from '@angular-devkit/build-angular';\nimport { Injector } from 'static-injector';\nimport * as webpack from 'webpack';\nimport { WebpackConfigurationChangeService } from '../application/webpack-configuration-change.service';\nimport {\n  BuildPlatform,\n  PlatformType,\n  getBuildPlatformInjectConfig,\n} from '../platform';\nimport { execute } from './index.origin';\n\nexport default createBuilder(\n  (\n    angularOptions: KarmaBuilderOptions & {\n      pages: AssetPattern[];\n      components: AssetPattern[];\n      platform: PlatformType;\n    },\n    context: BuilderContext\n  ): ReturnType<typeof execute> => {\n    return runBuilder(angularOptions, context);\n  }\n);\n\nexport function runBuilder(\n  angularOptions: KarmaBuilderOptions & {\n    pages: AssetPattern[];\n    components: AssetPattern[];\n    platform: PlatformType;\n  },\n  context: BuilderContext\n): ReturnType<typeof execute> {\n  return execute(angularOptions, context, {\n    webpackConfiguration: async (options: webpack.Configuration) => {\n      const injector = Injector.create({\n        providers: [\n          ...getBuildPlatformInjectConfig(PlatformType.wx),\n          {\n            provide: WebpackConfigurationChangeService,\n            useFactory: (injector: Injector) => {\n              return new WebpackConfigurationChangeService(\n                angularOptions,\n                context,\n                options,\n                injector\n              );\n            },\n            deps: [Injector],\n          },\n        ],\n      });\n      const config = injector.get(WebpackConfigurationChangeService);\n      config.init();\n      await config.change();\n      const buildPlatform = injector.get(BuildPlatform);\n      options.plugins!.push(\n        new webpack.DefinePlugin({\n          describe: `${buildPlatform.globalVariablePrefix}.describe`,\n          xdescribe: `${buildPlatform.globalVariablePrefix}.xdescribe`,\n          fdescribe: `${buildPlatform.globalVariablePrefix}.fdescribe`,\n          it: `${buildPlatform.globalVariablePrefix}.it`,\n          xit: `${buildPlatform.globalVariablePrefix}.xit`,\n          fit: `${buildPlatform.globalVariablePrefix}.fit`,\n          beforeEach: `${buildPlatform.globalVariablePrefix}.beforeEach`,\n          afterEach: `${buildPlatform.globalVariablePrefix}.afterEach`,\n          beforeAll: `${buildPlatform.globalVariablePrefix}.beforeAll`,\n          afterAll: `${buildPlatform.globalVariablePrefix}.afterAll`,\n          setSpecProperty: `${buildPlatform.globalVariablePrefix}.setSpecProperty`,\n          setSuiteProperty: `${buildPlatform.globalVariablePrefix}.setSuiteProperty`,\n          expect: `${buildPlatform.globalVariablePrefix}.expect`,\n          expectAsync: `${buildPlatform.globalVariablePrefix}.expectAsync`,\n          pending: `${buildPlatform.globalVariablePrefix}.pending`,\n          fail: `${buildPlatform.globalVariablePrefix}.fail`,\n          spyOn: `${buildPlatform.globalVariablePrefix}.spyOn`,\n          spyOnProperty: `${buildPlatform.globalVariablePrefix}.spyOnProperty`,\n          spyOnAllFunctions: `${buildPlatform.globalVariablePrefix}.spyOnAllFunctions`,\n          jsApiReporter: `${buildPlatform.globalVariablePrefix}.jsApiReporter`,\n          jasmine: `${buildPlatform.globalVariablePrefix}.jasmine`,\n        })\n      );\n      options.output!.path += '/dist';\n      return options;\n    },\n  });\n}\n"
  },
  {
    "path": "src/builder/karma/plugin/index.js",
    "content": "require('ts-node').register({\n  /* options */\n  scope: true,\n  cwd: __dirname,\n});\nlet obj = require('./launcher');\nobj = { ...obj.default, ...require('./karma').default };\nmodule.exports = obj;\n"
  },
  {
    "path": "src/builder/karma/plugin/index.ts",
    "content": "import config from './karma';\nimport launcher from './launcher';\nmodule.exports = { ...config, ...launcher };\n"
  },
  {
    "path": "src/builder/karma/plugin/karma.ts",
    "content": "// import { statsErrorsToString } from '@angular-devkit/build-angular/src/webpack/utils/stats';\nimport { logging } from '@angular-devkit/core';\nimport { createConsoleLogger } from '@angular-devkit/core/node';\nimport { ConfigOptions, launcher } from 'karma';\nimport * as webpack from 'webpack';\n\nlauncher.Launcher.generateId = () => {\n  return 'miniprogram';\n};\nlet blocked: any[] = [];\nlet isBlocked = false;\nlet successCb: () => void;\nlet failureCb: () => void;\n\nfunction init(\n  config: ConfigOptions & {\n    buildWebpack: {\n      logger: logging.Logger;\n      failureCb: () => void;\n      successCb: () => void;\n      testContext: { buildSuccess: (arg: webpack.Configuration) => void };\n      webpackConfig: webpack.Configuration;\n    };\n    configFile?: string;\n    webpack?: webpack.Configuration;\n  },\n  emitter: any\n) {\n  if (!config.buildWebpack) {\n    throw new Error(\n      `The '@angular-devkit/build-angular/plugins/karma' karma plugin is meant to` +\n        ` be used from within Angular CLI and will not work correctly outside of it.`\n    );\n  }\n  // const options = config.buildWebpack.options as BuildOptions;\n  const logger: logging.Logger =\n    config.buildWebpack.logger || createConsoleLogger();\n  successCb = config.buildWebpack.successCb;\n  failureCb = config.buildWebpack.failureCb;\n\n  config.reporters?.unshift('@angular-devkit/build-angular--event-reporter');\n  // todo 可能用不上,因为时本地\n  // When using code-coverage, auto-add karma-coverage.\n  // if (\n  //   options!.codeCoverage &&\n  //   !config.reporters.some((r: string) => r === 'coverage' || r === 'coverage-istanbul')\n  // ) {\n  //   config.reporters.push('coverage');\n  // }\n\n  // Add webpack config.\n  const webpackConfig = config.buildWebpack\n    .webpackConfig as webpack.Configuration;\n\n  // Use existing config if any.\n  config.webpack = { ...webpackConfig, ...config.webpack };\n\n  // Our custom context and debug files list the webpack bundles directly instead of using\n  // the karma files array.\n\n  if (config.singleRun) {\n    // There's no option to turn off file watching in webpack-dev-server, but\n    // we can override the file watcher instead.\n    (webpackConfig.plugins as any[]).unshift({\n      apply: (compiler: any) => {\n        compiler.hooks.afterEnvironment.tap('karma', () => {\n          compiler.watchFileSystem = { watch: () => {} };\n        });\n      },\n    });\n  }\n  webpackConfig.plugins!.push(\n    new webpack.DefinePlugin({\n      KARMA_CLIENT_CONFIG: JSON.stringify(config.client),\n      KARMA_PORT: config.port,\n    })\n  );\n  // Files need to be served from a custom path for Karma.\n  const compiler = webpack.webpack(webpackConfig, (error, stats) => {\n    if (error) {\n      throw error;\n    }\n\n    if (stats?.hasErrors()) {\n      // Only generate needed JSON stats and when needed.\n      const statsJson = stats?.toJson({\n        all: false,\n        children: true,\n        errors: true,\n        warnings: true,\n      });\n\n      logger.error(JSON.stringify(statsJson));\n\n      // Notify potential listeners of the compile error.\n      emitter.emit('compile_error', {\n        errors: statsJson.errors?.map((e) => e.message),\n      });\n\n      // Finish Karma run early in case of compilation error.\n      emitter.emit('run_complete', [], { exitCode: 1 });\n\n      // Emit a failure build event if there are compilation errors.\n      failureCb();\n      return;\n    }\n    // 仅测试时使用\n    if (config.buildWebpack.testContext) {\n      config.buildWebpack.testContext.buildSuccess(webpackConfig);\n    }\n  });\n\n  function handler(callback?: () => void): void {\n    isBlocked = true;\n    callback?.();\n  }\n\n  compiler.hooks.invalid.tap('karma', () => handler(() => {}));\n  compiler.hooks.watchRun.tapAsync('karma', (_: any, callback: () => void) =>\n    handler(callback)\n  );\n  compiler.hooks.run.tapAsync('karma', (_: any, callback: () => void) =>\n    handler(callback)\n  );\n\n  function unblock() {\n    isBlocked = false;\n    blocked.forEach((cb) => cb());\n    blocked = [];\n  }\n\n  let lastCompilationHash: string | undefined;\n  compiler.hooks.done.tap('karma', (stats) => {\n    if (stats.hasErrors()) {\n      lastCompilationHash = undefined;\n    } else if (stats.hash != lastCompilationHash) {\n      // Refresh karma only when there are no webpack errors, and if the compilation changed.\n      lastCompilationHash = stats.hash;\n      emitter.refreshFiles();\n    }\n    unblock();\n  });\n\n  emitter.on('exit', (done: any) => {\n    done();\n  });\n}\n\ninit.$inject = ['config', 'emitter'];\n\n// Block requests until the Webpack compilation is done.\nfunction requestBlocker() {\n  return function (_request: any, _response: any, next: () => void) {\n    if (isBlocked) {\n      blocked.push(next);\n    } else {\n      next();\n    }\n  };\n}\n\n// Copied from \"karma-jasmine-diff-reporter\" source code:\n// In case, when multiple reporters are used in conjunction\n// with initSourcemapReporter, they both will show repetitive log\n// messages when displaying everything that supposed to write to terminal.\n// So just suppress any logs from initSourcemapReporter by doing nothing on\n// browser log, because it is an utility reporter,\n// unless it's alone in the \"reporters\" option and base reporter is used.\nfunction muteDuplicateReporterLogging(context: any, config: any) {\n  context.writeCommonMsg = () => {};\n  const reporterName = '@angular/cli';\n  const hasTrailingReporters =\n    config.reporters.slice(-1).pop() !== reporterName;\n\n  if (hasTrailingReporters) {\n    context.writeCommonMsg = () => {};\n  }\n}\n\n// Emits builder events.\nconst eventReporter: any = function (\n  this: any,\n  baseReporterDecorator: any,\n  config: any\n) {\n  baseReporterDecorator(this);\n\n  muteDuplicateReporterLogging(this, config);\n\n  this.onRunComplete = function (_browsers: any, results: any) {\n    if (results.exitCode === 0) {\n      successCb();\n    } else {\n      failureCb();\n    }\n  };\n\n  // avoid duplicate failure message\n  this.specFailure = () => {};\n};\n\neventReporter.$inject = ['baseReporterDecorator', 'config'];\n\n// When a request is not found in the karma server, try looking for it from the webpack server root.\n\nexport default {\n  'framework:@angular-devkit/build-angular': ['factory', init],\n  'reporter:@angular-devkit/build-angular--event-reporter': [\n    'type',\n    eventReporter,\n  ],\n};\n"
  },
  {
    "path": "src/builder/karma/plugin/launcher.ts",
    "content": "const miniProgram = function (\n  this: any,\n  baseBrowserDecorator: any,\n  config: any\n) {\n  baseBrowserDecorator(this);\n  const self = this;\n  this.name = 'miniprogram';\n  this._start = function (url: string) {};\n  this.on('kill', function (done: any) {\n    self.emit('done');\n    process.nextTick(done);\n  });\n};\n\nminiProgram.$inject = ['baseBrowserDecorator', 'config.jsdomLauncher'];\n\nexport default {\n  'launcher:miniprogram': ['type', miniProgram],\n};\n"
  },
  {
    "path": "src/builder/karma/plugin/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"outDir\": \"../../../../dist/karma/plugin\",\n    \"strict\": false,\n    \"strictNullChecks\": false,\n    \"allowUnreachableCode\": true,\n    \"noUnusedParameters\": false,\n    \"sourceMap\": true,\n    \"declaration\": true,\n    \"esModuleInterop\": true,\n    \"target\": \"ES2021\",\n    \"module\": \"CommonJS\",\n    \"lib\": [\n      \"ES2021\"\n    ],\n    \"skipLibCheck\": true\n  },\n  \"files\": [\n    \"./index.ts\"\n  ]\n}"
  },
  {
    "path": "src/builder/karma/schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema\",\n  \"title\": \"Karma Target\",\n  \"description\": \"Karma target options for Build Facade.\",\n  \"type\": \"object\",\n  \"properties\": {\n    \"pages\": {\n      \"type\": \"array\",\n      \"description\": \"页面配置\",\n      \"default\": [],\n      \"items\": {\n        \"$ref\": \"#/definitions/assetPattern\"\n      }\n    },\n    \"components\": {\n      \"type\": \"array\",\n      \"description\": \"组件配置\",\n      \"default\": [],\n      \"items\": {\n        \"$ref\": \"#/definitions/assetPattern\"\n      }\n    },\n    \"platform\": {\n      \"type\": \"string\",\n      \"description\": \"小程序平台\",\n      \"default\": \"wx\"\n    },\n    \"main\": {\n      \"type\": \"string\",\n      \"description\": \"The name of the main entry-point file.\"\n    },\n    \"tsConfig\": {\n      \"type\": \"string\",\n      \"description\": \"The name of the TypeScript configuration file.\"\n    },\n    \"karmaConfig\": {\n      \"type\": \"string\",\n      \"description\": \"The name of the Karma configuration file.\"\n    },\n    \"polyfills\": {\n      \"type\": \"string\",\n      \"description\": \"The name of the polyfills file.\"\n    },\n    \"assets\": {\n      \"type\": \"array\",\n      \"description\": \"List of static application assets.\",\n      \"default\": [],\n      \"items\": {\n        \"$ref\": \"#/definitions/assetPattern\"\n      }\n    },\n    \"scripts\": {\n      \"description\": \"Global scripts to be included in the build.\",\n      \"type\": \"array\",\n      \"default\": [],\n      \"items\": {\n        \"$ref\": \"#/definitions/extraEntryPoint\"\n      }\n    },\n    \"styles\": {\n      \"description\": \"Global styles to be included in the build.\",\n      \"type\": \"array\",\n      \"default\": [],\n      \"items\": {\n        \"$ref\": \"#/definitions/extraEntryPoint\"\n      }\n    },\n    \"inlineStyleLanguage\": {\n      \"description\": \"The stylesheet language to use for the application's inline component styles.\",\n      \"type\": \"string\",\n      \"default\": \"css\",\n      \"enum\": [\"css\", \"less\", \"sass\", \"scss\"]\n    },\n    \"stylePreprocessorOptions\": {\n      \"description\": \"Options to pass to style preprocessors\",\n      \"type\": \"object\",\n      \"properties\": {\n        \"includePaths\": {\n          \"description\": \"Paths to include. Paths will be resolved to workspace root.\",\n          \"type\": \"array\",\n          \"items\": {\n            \"type\": \"string\"\n          },\n          \"default\": []\n        }\n      },\n      \"additionalProperties\": false\n    },\n    \"include\": {\n      \"type\": \"array\",\n      \"items\": {\n        \"type\": \"string\"\n      },\n      \"description\": \"Globs of files to include, relative to workspace or project root. \\nThere are 2 special cases:\\n - when a path to directory is provided, all spec files ending \\\".spec.@(ts|tsx)\\\" will be included\\n - when a path to a file is provided, and a matching spec file exists it will be included instead\"\n    },\n    \"sourceMap\": {\n      \"description\": \"Output source maps for scripts and styles. For more information, see https://angular.io/guide/workspace-config#source-map-configuration.\",\n      \"default\": true,\n      \"oneOf\": [\n        {\n          \"type\": \"object\",\n          \"properties\": {\n            \"scripts\": {\n              \"type\": \"boolean\",\n              \"description\": \"Output source maps for all scripts.\",\n              \"default\": true\n            },\n            \"styles\": {\n              \"type\": \"boolean\",\n              \"description\": \"Output source maps for all styles.\",\n              \"default\": true\n            },\n            \"vendor\": {\n              \"type\": \"boolean\",\n              \"description\": \"Resolve vendor packages source maps.\",\n              \"default\": false\n            }\n          },\n          \"additionalProperties\": false\n        },\n        {\n          \"type\": \"boolean\"\n        }\n      ]\n    },\n    \"progress\": {\n      \"type\": \"boolean\",\n      \"description\": \"Log progress to the console while building.\",\n      \"default\": true\n    },\n    \"watch\": {\n      \"type\": \"boolean\",\n      \"description\": \"Run build when files change.\"\n    },\n    \"poll\": {\n      \"type\": \"number\",\n      \"description\": \"Enable and define the file watching poll time period in milliseconds.\"\n    },\n    \"preserveSymlinks\": {\n      \"type\": \"boolean\",\n      \"description\": \"Do not use the real path when resolving modules. If unset then will default to `true` if NodeJS option --preserve-symlinks is set.\"\n    },\n    \"browsers\": {\n      \"type\": \"string\",\n      \"description\": \"Override which browsers tests are run against.\"\n    },\n    \"codeCoverage\": {\n      \"type\": \"boolean\",\n      \"description\": \"Output a code coverage report.\",\n      \"default\": false\n    },\n    \"codeCoverageExclude\": {\n      \"type\": \"array\",\n      \"description\": \"Globs to exclude from code coverage.\",\n      \"items\": {\n        \"type\": \"string\"\n      },\n      \"default\": []\n    },\n    \"fileReplacements\": {\n      \"description\": \"Replace compilation source files with other compilation source files in the build.\",\n      \"type\": \"array\",\n      \"items\": {\n        \"oneOf\": [\n          {\n            \"type\": \"object\",\n            \"properties\": {\n              \"src\": {\n                \"type\": \"string\"\n              },\n              \"replaceWith\": {\n                \"type\": \"string\"\n              }\n            },\n            \"additionalProperties\": false,\n            \"required\": [\"src\", \"replaceWith\"]\n          },\n          {\n            \"type\": \"object\",\n            \"properties\": {\n              \"replace\": {\n                \"type\": \"string\"\n              },\n              \"with\": {\n                \"type\": \"string\"\n              }\n            },\n            \"additionalProperties\": false,\n            \"required\": [\"replace\", \"with\"]\n          }\n        ]\n      },\n      \"default\": []\n    },\n    \"reporters\": {\n      \"type\": \"array\",\n      \"description\": \"Karma reporters to use. Directly passed to the karma runner.\",\n      \"items\": {\n        \"type\": \"string\"\n      }\n    },\n    \"webWorkerTsConfig\": {\n      \"type\": \"string\",\n      \"description\": \"TypeScript configuration for Web Worker modules.\"\n    }\n  },\n  \"additionalProperties\": false,\n  \"required\": [\"main\", \"tsConfig\", \"karmaConfig\"],\n  \"definitions\": {\n    \"assetPattern\": {\n      \"oneOf\": [\n        {\n          \"type\": \"object\",\n          \"properties\": {\n            \"glob\": {\n              \"type\": \"string\",\n              \"description\": \"The pattern to match.\"\n            },\n            \"input\": {\n              \"type\": \"string\",\n              \"description\": \"The input directory path in which to apply 'glob'. Defaults to the project root.\"\n            },\n            \"output\": {\n              \"type\": \"string\",\n              \"description\": \"Absolute path within the output.\"\n            },\n            \"ignore\": {\n              \"description\": \"An array of globs to ignore.\",\n              \"type\": \"array\",\n              \"items\": {\n                \"type\": \"string\"\n              }\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\"glob\", \"input\", \"output\"]\n        },\n        {\n          \"type\": \"string\"\n        }\n      ]\n    },\n    \"extraEntryPoint\": {\n      \"oneOf\": [\n        {\n          \"type\": \"object\",\n          \"properties\": {\n            \"input\": {\n              \"type\": \"string\",\n              \"description\": \"The file to include.\"\n            },\n            \"bundleName\": {\n              \"type\": \"string\",\n              \"pattern\": \"^[\\\\w\\\\-.]*$\",\n              \"description\": \"The bundle name for this extra entry point.\"\n            },\n            \"inject\": {\n              \"type\": \"boolean\",\n              \"description\": \"If the bundle will be referenced in the HTML file.\",\n              \"default\": true\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\"input\"]\n        },\n        {\n          \"type\": \"string\",\n          \"description\": \"The file to include.\"\n        }\n      ]\n    }\n  }\n}\n"
  },
  {
    "path": "src/builder/library/add-declaration-metadata.service.ts",
    "content": "import type {\n  R3ComponentMetadata,\n  R3DirectiveMetadata,\n} from '@angular/compiler';\nimport { createCssSelectorForTs } from 'cyia-code-util';\nimport { Inject, Injectable } from 'static-injector';\nimport ts from 'typescript';\nimport { MiniProgramCompilerService } from '../mini-program-compiler';\nimport {\n  LIBRARY_COMPONENT_OUTPUT_PATH_SUFFIX,\n  LIBRARY_DIRECTIVE_LISTENERS_SUFFIX,\n  LIBRARY_DIRECTIVE_PROPERTIES_SUFFIX,\n} from './const';\nimport { getComponentOutputPath } from './get-library-path';\nimport { ENTRY_POINT_TOKEN } from './token';\n\n@Injectable()\nexport class AddDeclarationMetaDataService {\n  private directiveMap: Map<ts.ClassDeclaration, R3DirectiveMetadata>;\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  private componentMap: Map<ts.ClassDeclaration, R3ComponentMetadata<any>>;\n\n  constructor(\n    @Inject(ENTRY_POINT_TOKEN) private entryPoint: string,\n    miniProgramCompilerService: MiniProgramCompilerService\n  ) {\n    this.directiveMap = miniProgramCompilerService.getDirectiveMap();\n    this.componentMap = miniProgramCompilerService.getComponentMap();\n  }\n  run(dTsFileName: string, data: string): string {\n    const list = createCssSelectorForTs(data).queryAll(\n      `ClassDeclaration`\n    ) as ts.ClassDeclaration[];\n    return (\n      data +\n      this.addComponentMetaDataDeclaration(list) +\n      this.addDirectiveMetaDataDeclaration(list)\n    );\n  }\n  private addComponentMetaDataDeclaration(list: ts.ClassDeclaration[]) {\n    const metaList = ['\\n'];\n    for (let i = 0; i < list.length; i++) {\n      const classDeclaration = list[i];\n      const isComponentClassDeclaration = classDeclaration.members.some(\n        (item) =>\n          ts.isPropertyDeclaration(item) &&\n          item.modifiers?.some((modifier) => modifier.getText() === 'static') &&\n          item.name.getText() === 'ɵcmp'\n      );\n      if (!isComponentClassDeclaration) {\n        continue;\n      }\n      metaList.push(\n        ...this.getPropertyAndListener(classDeclaration, this.componentMap)\n      );\n      const className = classDeclaration.name!.getText();\n\n      metaList.push(\n        `declare const ${className}_${LIBRARY_COMPONENT_OUTPUT_PATH_SUFFIX}:\"${getComponentOutputPath(\n          this.entryPoint,\n          className\n        )}\";`\n      );\n    }\n    return metaList.join('\\n');\n  }\n  private addDirectiveMetaDataDeclaration(list: ts.ClassDeclaration[]) {\n    const metaList = ['\\n'];\n    for (let i = 0; i < list.length; i++) {\n      const classDeclaration = list[i];\n      const isDirectiveClassDeclaration = classDeclaration.members.some(\n        (item) =>\n          ts.isPropertyDeclaration(item) &&\n          item.modifiers?.some((modifier) => modifier.getText() === 'static') &&\n          item.name.getText() === 'ɵdir'\n      );\n      if (!isDirectiveClassDeclaration) {\n        continue;\n      }\n      metaList.push(\n        ...this.getPropertyAndListener(classDeclaration, this.directiveMap)\n      );\n    }\n    return metaList.join('\\n');\n  }\n  private getPropertyAndListener(\n    classDeclaration: ts.ClassDeclaration,\n    map: Map<ts.ClassDeclaration, R3DirectiveMetadata>\n  ) {\n    const className: string = classDeclaration.name!.getText();\n    const list: string[] = [];\n    for (const [key, meta] of map.entries()) {\n      const directiveClassName = meta.name;\n      if (directiveClassName === className) {\n        const listeners = meta.host.listeners as Record<string, string>;\n        list.push(\n          `declare const ${className}_${LIBRARY_DIRECTIVE_LISTENERS_SUFFIX}:${JSON.stringify(\n            Object.keys(listeners)\n          )};`\n        );\n        const properties = meta.host.properties as Record<string, string>;\n        list.push(\n          `declare const ${className}_${LIBRARY_DIRECTIVE_PROPERTIES_SUFFIX}:${JSON.stringify(\n            Object.keys(properties)\n          )};`\n        );\n        break;\n      }\n    }\n    return list;\n  }\n}\n"
  },
  {
    "path": "src/builder/library/builder.ts",
    "content": "/* eslint-disable @typescript-eslint/no-explicit-any */\n/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {\n  BuilderContext,\n  BuilderOutput,\n  createBuilder,\n} from '@angular-devkit/architect';\nimport { normalizeCacheOptions } from '@angular-devkit/build-angular/src/utils/normalize-cache';\nimport { join, resolve } from 'path';\nimport { Observable, from, of } from 'rxjs';\nimport { catchError, mapTo, switchMap } from 'rxjs/operators';\nimport { ngPackagrFactory } from './ng-packagr-factory';\n\n/**\n * @experimental Direct usage of this function is considered experimental.\n */\nexport function execute(\n  options: any,\n  context: BuilderContext\n): Observable<BuilderOutput> {\n  return from(\n    (async () => {\n      const root = context.workspaceRoot;\n      let tsConfig: string | undefined;\n\n      if (options.tsConfig) {\n        tsConfig = resolve(root, options.tsConfig);\n      }\n      const packager = await ngPackagrFactory(\n        resolve(root, options.project),\n        tsConfig\n      );\n\n      const projectName = context.target?.project;\n      if (!projectName) {\n        throw new Error('The builder requires a target.');\n      }\n\n      const metadata = await context.getProjectMetadata(projectName);\n      const { enabled: cacheEnabled, path: cacheDirectory } =\n        normalizeCacheOptions(metadata, context.workspaceRoot);\n\n      const ngPackagrOptions = {\n        cacheEnabled,\n        cacheDirectory: join(cacheDirectory, 'ng-packagr'),\n      };\n\n      return { packager, ngPackagrOptions };\n    })()\n  ).pipe(\n    switchMap(({ packager, ngPackagrOptions }) =>\n      options.watch\n        ? packager.watch(ngPackagrOptions)\n        : packager.build(ngPackagrOptions)\n    ),\n    mapTo({ success: true, workspaceRoot: context.workspaceRoot }),\n    catchError((err) => of({ success: false, error: err.message }))\n  );\n}\n\nexport default createBuilder<Record<string, string> & any>(execute);\n"
  },
  {
    "path": "src/builder/library/compile-ngc.transform.ts",
    "content": "/* eslint-disable @typescript-eslint/no-explicit-any */\nimport {\n  Transform,\n  transformFromPromise,\n} from 'ng-packagr/lib/graph/transform';\nimport {\n  EntryPointNode,\n  PackageNode,\n  isEntryPoint,\n  isEntryPointInProgress,\n  isPackage,\n} from 'ng-packagr/lib/ng-package/nodes';\nimport { NgPackagrOptions } from 'ng-packagr/lib/ng-package/options.di';\nimport { StylesheetProcessor as StylesheetProcessorClass } from 'ng-packagr/lib/styles/stylesheet-processor';\nimport { setDependenciesTsConfigPaths } from 'ng-packagr/lib/ts/tsconfig';\nimport ora from 'ora';\nimport * as path from 'path';\nimport ts from 'typescript';\nimport { compileSourceFiles } from './compile-source-files';\n\nexport const myCompileNgcTransformFactory = (\n  StylesheetProcessor: typeof StylesheetProcessorClass,\n  options: NgPackagrOptions\n): Transform => {\n  return transformFromPromise(async (graph) => {\n    const spinner = ora({\n      hideCursor: false,\n      discardStdin: false,\n    });\n\n    const entryPoints: EntryPointNode[] = graph.filter(isEntryPoint);\n    const entryPoint: EntryPointNode = entryPoints.find(\n      isEntryPointInProgress()\n    )!;\n    const ngPackageNode: PackageNode = graph.find(isPackage)!;\n    const projectBasePath = ngPackageNode.data.primary.basePath;\n\n    try {\n      // Add paths mappings for dependencies\n      const tsConfig = setDependenciesTsConfigPaths(\n        entryPoint.data.tsConfig!,\n        entryPoints\n      );\n\n      // Compile TypeScript sources\n      const { esm2022: esm2022, declarations } =\n        entryPoint.data.destinationFiles;\n      const { basePath, cssUrl, styleIncludePaths } =\n        entryPoint.data.entryPoint;\n      const { moduleResolutionCache } = entryPoint.cache;\n\n      spinner.start(\n        `Compiling with Angular sources in Ivy ${\n          tsConfig.options.compilationMode || 'full'\n        } compilation mode.`\n      );\n\n      entryPoint.cache.stylesheetProcessor ??= new StylesheetProcessor(\n        projectBasePath,\n        basePath,\n        cssUrl,\n        styleIncludePaths,\n        options.cacheEnabled && options.cacheDirectory\n      );\n\n      await compileSourceFiles(\n        graph,\n        tsConfig,\n        moduleResolutionCache,\n        {\n          outDir: path.dirname(esm2022),\n          declarationDir: path.dirname(declarations),\n          declaration: true,\n          target: ts.ScriptTarget.ES2022,\n        },\n        entryPoint.cache.stylesheetProcessor,\n        options.watch\n      );\n    } catch (error) {\n      spinner.fail();\n      throw error;\n    } finally {\n      if (!options.watch) {\n        entryPoint.cache.stylesheetProcessor?.destroy();\n      }\n    }\n\n    spinner.succeed();\n\n    return graph;\n  });\n};\n"
  },
  {
    "path": "src/builder/library/compile-source-files.ts",
    "content": "import type {\n  CompilerOptions,\n  ParsedConfiguration,\n} from '@angular/compiler-cli';\nimport { dirname, normalize } from '@angular-devkit/core';\nimport { BuildGraph } from 'ng-packagr/lib/graph/build-graph';\nimport {\n  EntryPointNode,\n  PackageNode,\n  isEntryPointInProgress,\n  isPackage,\n} from 'ng-packagr/lib/ng-package/nodes';\nimport { StylesheetProcessor } from 'ng-packagr/lib/styles/stylesheet-processor';\nimport {\n  augmentProgramWithVersioning,\n  cacheCompilerHost,\n} from 'ng-packagr/lib/ts/cache-compiler-host';\nimport { ngCompilerCli } from 'ng-packagr/lib/utils/load-esm';\nimport * as log from 'ng-packagr/lib/utils/log';\nimport { join } from 'node:path';\nimport path from 'path';\nimport { Injector } from 'static-injector';\nimport ts from 'typescript';\nimport { MiniProgramCompilerService } from '../mini-program-compiler';\nimport { BuildPlatform, PlatformType } from '../platform/platform';\nimport { getBuildPlatformInjectConfig } from '../platform/platform-inject-config';\nimport { AddDeclarationMetaDataService } from './add-declaration-metadata.service';\nimport { OutputTemplateMetadataService } from './output-template-metadata.service';\nimport { SetupComponentDataService } from './setup-component-data.service';\nimport { CustomStyleSheetProcessor } from './stylesheet-processor';\nimport {\n  ENTRY_FILE_TOKEN,\n  ENTRY_POINT_TOKEN,\n  RESOLVED_DATA_GROUP_TOKEN,\n} from './token';\n\nexport async function compileSourceFiles(\n  graph: BuildGraph,\n  tsConfig: ParsedConfiguration,\n  moduleResolutionCache: ts.ModuleResolutionCache,\n  extraOptions?: Partial<CompilerOptions>,\n  stylesheetProcessor?: StylesheetProcessor,\n  watch?: boolean\n) {\n  const { NgtscProgram, formatDiagnostics } = await ngCompilerCli();\n\n  const tsConfigOptions: CompilerOptions = {\n    ...tsConfig.options,\n    ...extraOptions,\n  };\n  const entryPoint: EntryPointNode = graph.find(\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\n    isEntryPointInProgress() as any\n  )!;\n  const ngPackageNode: PackageNode = graph.find(isPackage)!;\n  const inlineStyleLanguage = ngPackageNode.data.inlineStyleLanguage;\n\n  const tsCompilerHost = cacheCompilerHost(\n    graph,\n    entryPoint,\n    tsConfigOptions,\n    moduleResolutionCache,\n    stylesheetProcessor,\n    inlineStyleLanguage\n  );\n  // inject\n  augmentLibraryMetadata(tsCompilerHost);\n  const cache = entryPoint.cache;\n  const sourceFileCache = cache.sourcesFileCache;\n\n  // Create the Angular specific program that contains the Angular compiler\n  const angularProgram = new NgtscProgram(\n    tsConfig.rootNames,\n    tsConfigOptions,\n    tsCompilerHost,\n    cache.oldNgtscProgram\n  );\n\n  const angularCompiler = angularProgram.compiler;\n  const { ignoreForDiagnostics, ignoreForEmit } = angularCompiler;\n\n  // SourceFile versions are required for builder programs.\n  // The wrapped host inside NgtscProgram adds additional files that will not have versions.\n  const typeScriptProgram = angularProgram.getTsProgram();\n  augmentProgramWithVersioning(typeScriptProgram);\n\n  let builder: ts.BuilderProgram | ts.EmitAndSemanticDiagnosticsBuilderProgram;\n  if (watch) {\n    builder = cache.oldBuilder =\n      ts.createEmitAndSemanticDiagnosticsBuilderProgram(\n        typeScriptProgram,\n        tsCompilerHost,\n        cache.oldBuilder\n      );\n    cache.oldNgtscProgram = angularProgram;\n  } else {\n    // When not in watch mode, the startup cost of the incremental analysis can be avoided by\n    // using an abstract builder that only wraps a TypeScript program.\n    builder = ts.createAbstractBuilder(typeScriptProgram, tsCompilerHost);\n  }\n\n  // Update semantic diagnostics cache\n  const affectedFiles = new Set<ts.SourceFile>();\n\n  // Analyze affected files when in watch mode for incremental type checking\n  if ('getSemanticDiagnosticsOfNextAffectedFile' in builder) {\n    // eslint-disable-next-line no-constant-condition\n    while (true) {\n      const result = builder.getSemanticDiagnosticsOfNextAffectedFile(\n        undefined,\n        (sourceFile) => {\n          // If the affected file is a TTC shim, add the shim's original source file.\n          // This ensures that changes that affect TTC are typechecked even when the changes\n          // are otherwise unrelated from a TS perspective and do not result in Ivy codegen changes.\n          // For example, changing @Input property types of a directive used in another component's\n          // template.\n          if (\n            ignoreForDiagnostics.has(sourceFile) &&\n            sourceFile.fileName.endsWith('.ngtypecheck.ts')\n          ) {\n            // This file name conversion relies on internal compiler logic and should be converted\n            // to an official method when available. 15 is length of `.ngtypecheck.ts`\n            const originalFilename = sourceFile.fileName.slice(0, -15) + '.ts';\n            const originalSourceFile = builder.getSourceFile(originalFilename);\n            if (originalSourceFile) {\n              affectedFiles.add(originalSourceFile);\n            }\n\n            return true;\n          }\n\n          return false;\n        }\n      );\n\n      if (!result) {\n        break;\n      }\n\n      affectedFiles.add(result.affected as ts.SourceFile);\n    }\n  }\n\n  // Collect program level diagnostics\n  const allDiagnostics: ts.Diagnostic[] = [\n    ...angularCompiler.getOptionDiagnostics(),\n    ...builder.getOptionsDiagnostics(),\n    ...builder.getGlobalDiagnostics(),\n  ];\n  // inject\n  let injector = Injector.create({\n    providers: [\n      ...getBuildPlatformInjectConfig(PlatformType.library),\n      {\n        provide: MiniProgramCompilerService,\n        useFactory: (injector: Injector, buildPlatform: BuildPlatform) => {\n          return new MiniProgramCompilerService(\n            angularProgram,\n            injector,\n            buildPlatform\n          );\n        },\n        deps: [Injector, BuildPlatform],\n      },\n      {\n        provide: ENTRY_FILE_TOKEN,\n        useValue: join(\n          dirname(normalize(tsConfig.rootNames[0])),\n          normalize(tsConfigOptions.flatModuleOutFile!)\n        ),\n      },\n      {\n        provide: ENTRY_POINT_TOKEN,\n        useValue: entryPoint.data.entryPoint.moduleId,\n      },\n    ],\n  });\n  const miniProgramCompilerService = injector.get(MiniProgramCompilerService);\n  // Required to support asynchronous resource loading\n  // Must be done before creating transformers or getting template diagnostics\n  await angularCompiler.analyzeAsync();\n  // inject\n  miniProgramCompilerService.init();\n  const metaMap =\n    await miniProgramCompilerService.exportComponentBuildMetaMap();\n  injector = Injector.create({\n    parent: injector,\n    providers: [\n      { provide: RESOLVED_DATA_GROUP_TOKEN, useValue: metaMap },\n      { provide: AddDeclarationMetaDataService },\n      { provide: OutputTemplateMetadataService },\n      { provide: SetupComponentDataService },\n    ],\n  });\n  // Collect source file specific diagnostics\n  for (const sourceFile of builder.getSourceFiles()) {\n    if (!ignoreForDiagnostics.has(sourceFile)) {\n      allDiagnostics.push(\n        ...builder.getDeclarationDiagnostics(sourceFile),\n        ...builder.getSyntacticDiagnostics(sourceFile),\n        ...builder.getSemanticDiagnostics(sourceFile)\n      );\n    }\n\n    if (sourceFile.isDeclarationFile) {\n      continue;\n    }\n\n    // Collect sources that are required to be emitted\n    if (\n      !ignoreForEmit.has(sourceFile) &&\n      !angularCompiler.incrementalCompilation.safeToSkipEmit(sourceFile)\n    ) {\n      // If required to emit, diagnostics may have also changed\n      if (!ignoreForDiagnostics.has(sourceFile)) {\n        affectedFiles.add(sourceFile);\n      }\n    } else if (\n      sourceFileCache &&\n      !affectedFiles.has(sourceFile) &&\n      !ignoreForDiagnostics.has(sourceFile)\n    ) {\n      // Use cached Angular diagnostics for unchanged and unaffected files\n      const angularDiagnostics =\n        sourceFileCache.getAngularDiagnostics(sourceFile);\n      if (angularDiagnostics?.length) {\n        allDiagnostics.push(...angularDiagnostics);\n      }\n    }\n  }\n\n  // Collect new Angular diagnostics for files affected by changes\n  for (const affectedFile of affectedFiles) {\n    const angularDiagnostics = angularCompiler.getDiagnosticsForFile(\n      affectedFile,\n      /** OptimizeFor.WholeProgram */ 1\n    );\n\n    allDiagnostics.push(...angularDiagnostics);\n    sourceFileCache.updateAngularDiagnostics(affectedFile, angularDiagnostics);\n  }\n\n  const otherDiagnostics = [];\n  const errorDiagnostics = [];\n  for (const diagnostic of allDiagnostics) {\n    if (diagnostic.category === ts.DiagnosticCategory.Error) {\n      errorDiagnostics.push(diagnostic);\n    } else {\n      otherDiagnostics.push(diagnostic);\n    }\n  }\n\n  if (otherDiagnostics.length) {\n    log.msg(formatDiagnostics(errorDiagnostics));\n  }\n\n  if (errorDiagnostics.length) {\n    throw new Error(formatDiagnostics(errorDiagnostics));\n  }\n\n  const transformers = angularCompiler.prepareEmit().transformers;\n  for (const sourceFile of builder.getSourceFiles()) {\n    if (!ignoreForEmit.has(sourceFile)) {\n      builder.emit(sourceFile, undefined, undefined, undefined, transformers);\n    }\n  }\n  function augmentLibraryMetadata(compilerHost: ts.CompilerHost) {\n    const oldWriteFile = compilerHost.writeFile;\n    compilerHost.writeFile = function (\n      fileName: string,\n      data: string,\n      writeByteOrderMark,\n      onError,\n      sourceFiles\n    ) {\n      const entryFileName = injector.get(ENTRY_FILE_TOKEN);\n      if (fileName.endsWith('.map')) {\n        return oldWriteFile.call(\n          this,\n          fileName,\n          data,\n          writeByteOrderMark,\n          onError,\n          sourceFiles\n        );\n      }\n      if (fileName.endsWith('.d.ts')) {\n        const service = injector.get(AddDeclarationMetaDataService);\n        const result = service.run(fileName, data);\n        return oldWriteFile.call(\n          this,\n          fileName,\n          result,\n          writeByteOrderMark,\n          onError,\n          sourceFiles\n        );\n      }\n      const sourceFile = sourceFiles && sourceFiles[0];\n      if (sourceFile) {\n        if (\n          normalize(entryFileName) ===\n          normalize(sourceFile.fileName.replace(/\\.ts$/, '.js'))\n        ) {\n          const service = injector.get(OutputTemplateMetadataService);\n          const result = service.run(fileName, data, sourceFiles![0]);\n          return oldWriteFile.call(\n            this,\n            fileName,\n            result,\n            writeByteOrderMark,\n            onError,\n            sourceFiles\n          );\n        }\n        const originFileName = path.normalize(sourceFile.fileName);\n        const setupComponentDataService = injector.get(\n          SetupComponentDataService\n        );\n        const result = setupComponentDataService.run(\n          data,\n          originFileName,\n          stylesheetProcessor! as CustomStyleSheetProcessor\n        );\n        return oldWriteFile.call(\n          this,\n          fileName,\n          result,\n          writeByteOrderMark,\n          onError,\n          sourceFiles\n        );\n      }\n      return oldWriteFile.call(\n        this,\n        fileName,\n        data,\n        writeByteOrderMark,\n        onError,\n        sourceFiles\n      );\n    };\n  }\n}\n"
  },
  {
    "path": "src/builder/library/const.ts",
    "content": "export const LIBRARY_OUTPUT_ROOTDIR = 'library';\nexport const LIBRARY_DIRECTIVE_LISTENERS_SUFFIX = 'Listeners';\nexport const LIBRARY_DIRECTIVE_PROPERTIES_SUFFIX = 'Properties';\nexport const LIBRARY_COMPONENT_OUTPUT_PATH_SUFFIX = 'OutputPath';\nexport const LIBRARY_COMPONENT_METADATA_SUFFIX = 'ExtraData';\nexport const GLOBAL_TEMPLATE_SUFFIX = 'Global_Template';\n"
  },
  {
    "path": "src/builder/library/get-library-path.ts",
    "content": "import { join, normalize } from '@angular-devkit/core';\nimport { camelize, dasherize } from '@angular-devkit/core/src/utils/strings';\n\nexport function getComponentOutputPath(entry: string, className: string) {\n  return join(\n    normalize(entry),\n    dasherize(camelize(className)),\n    dasherize(camelize(className))\n  );\n}\n"
  },
  {
    "path": "src/builder/library/index.ts",
    "content": "export * from './const';\nexport * from './type';\n"
  },
  {
    "path": "src/builder/library/library.spec.ts",
    "content": "/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { join, normalize } from '@angular-devkit/core';\nimport * as fs from 'fs-extra';\nimport path from 'path';\nimport { describeBuilder } from '../../../test/plugin-describe-builder';\nimport {\n  DEFAULT_ANGULAR_LIBRARY_CONFIG,\n  LIBRARY_BUILDER_INFO,\n} from '../../../test/test-builder';\nimport { execute } from './builder';\nimport { LIBRARY_COMPONENT_METADATA_SUFFIX } from './const';\n\ndescribeBuilder(execute, LIBRARY_BUILDER_INFO, (harness) => {\n  describe('test-library', () => {\n    it('运行', async () => {\n      harness.useTarget('library', DEFAULT_ANGULAR_LIBRARY_CONFIG);\n      const result = await harness.executeOnce();\n      expect(result).toBeTruthy();\n      expect(result.result).toBeTruthy();\n      expect(result.result.success).toBeTruthy();\n      if (!result.result.success) {\n        console.error(result.result.error);\n      }\n      const workspaceRoot: string = (result.result as any).workspaceRoot;\n      const outputPath = normalize(`dist/test-library`);\n      const output = path.join(workspaceRoot, outputPath);\n      const entryFile = harness.expectFile(\n        join(outputPath, 'esm2022', 'test-library.mjs')\n      );\n      entryFile.toExist();\n      entryFile.content.toContain(`$self_Global_Template`);\n      const globalSelfTemplate = harness.expectFile(\n        join(\n          outputPath,\n          'esm2022',\n          'global-self-template',\n          'global-self-template.component.mjs'\n        )\n      );\n      globalSelfTemplate.toExist();\n      globalSelfTemplate.content.toContain(\n        `GlobalSelfTemplateComponent_${LIBRARY_COMPONENT_METADATA_SUFFIX}`\n      );\n      fs.copySync(\n        output,\n        path.resolve(\n          process.cwd(),\n          'test',\n          'hello-world-app',\n          'node_modules',\n          'test-library'\n        )\n      );\n    });\n  });\n});\n"
  },
  {
    "path": "src/builder/library/merge-using-component-path.ts",
    "content": "import { join, normalize, resolve } from '@angular-devkit/core';\nimport { UseComponent } from '../mini-program-compiler';\nimport { LIBRARY_OUTPUT_ROOTDIR } from './const';\nimport { getComponentOutputPath } from './get-library-path';\n\nexport function getUseComponents(\n  libraryPath: UseComponent[],\n  localPath: UseComponent[],\n  moduleId: string\n) {\n  const list = [...libraryPath];\n  list.push(\n    ...localPath.map((item) => {\n      item.path = getComponentOutputPath(moduleId, item.className);\n      return item;\n    })\n  );\n  return list.reduce((pre, cur) => {\n    pre[cur.selector] = resolve(\n      normalize('/'),\n      join(normalize(LIBRARY_OUTPUT_ROOTDIR), cur.path)\n    );\n    return pre;\n  }, {} as Record<string, string>);\n}\n"
  },
  {
    "path": "src/builder/library/ng-packagr-factory.ts",
    "content": "import { COMPILE_NGC_TRANSFORM } from 'ng-packagr/lib/ng-package/entry-point/compile-ngc.di';\nimport { STYLESHEET_PROCESSOR } from 'ng-packagr/lib/styles/stylesheet-processor.di';\nimport { myCompileNgcTransformFactory } from './compile-ngc.transform';\nimport { hookWritePackage } from './remove-publish-only';\nimport { CustomStyleSheetProcessor } from './stylesheet-processor';\n\nexport async function ngPackagrFactory(\n  project: string,\n  tsConfig: string | undefined\n) {\n  const packager = (await import('ng-packagr')).ngPackagr();\n\n  packager.forProject(project);\n\n  if (tsConfig) {\n    packager.withTsConfig(tsConfig);\n  }\n\n  COMPILE_NGC_TRANSFORM.useFactory = myCompileNgcTransformFactory;\n  STYLESHEET_PROCESSOR.useFactory = () => CustomStyleSheetProcessor;\n  packager.withProviders([COMPILE_NGC_TRANSFORM, hookWritePackage()]);\n  return packager;\n}\n"
  },
  {
    "path": "src/builder/library/output-template-metadata.service.ts",
    "content": "import { join, normalize, resolve } from '@angular-devkit/core';\nimport { Inject, Injectable } from 'static-injector';\nimport ts from 'typescript';\nimport { MetaCollection, ResolvedDataGroup } from '../mini-program-compiler';\nimport { GLOBAL_TEMPLATE_SUFFIX, LIBRARY_OUTPUT_ROOTDIR } from './const';\nimport { getUseComponents } from './merge-using-component-path';\nimport {\n  ENTRY_FILE_TOKEN,\n  ENTRY_POINT_TOKEN,\n  RESOLVED_DATA_GROUP_TOKEN,\n} from './token';\nimport { ExtraTemplateData } from './type';\n\n@Injectable()\nexport class OutputTemplateMetadataService {\n  private selfUseComponents!: Record<string, string>;\n  private selfMetaCollection!: MetaCollection;\n  constructor(\n    @Inject(ENTRY_FILE_TOKEN) private entryFile: string,\n    @Inject(RESOLVED_DATA_GROUP_TOKEN)\n    private dataGroup: ResolvedDataGroup,\n    @Inject(ENTRY_POINT_TOKEN) private entryPoint: string\n  ) {}\n\n  run(fileName: string, data: string, sourceFile: ts.SourceFile) {\n    const list = data.split(/\\n|\\r\\n/g);\n    list.splice(\n      list.length - 1,\n      0,\n      `${this.getSelfTemplate()};${this.getLibraryTemplate()}`\n    );\n    return list.join('\\n');\n  }\n  private getSelfTemplate() {\n    const selfMetaCollection = this.dataGroup.otherMetaCollectionGroup['$self'];\n    if (!selfMetaCollection) {\n      return '';\n    }\n    this.selfMetaCollection = selfMetaCollection;\n    const templateStr = selfMetaCollection.templateList\n      .map((item) => item.content)\n      .join('');\n\n    const extraTemplateData: ExtraTemplateData = {\n      template: templateStr,\n      outputPath: resolve(\n        normalize('/'),\n        join(normalize(LIBRARY_OUTPUT_ROOTDIR), this.entryPoint, 'self')\n      ),\n    };\n\n    delete this.dataGroup.otherMetaCollectionGroup['$self'];\n\n    return `let $self_${GLOBAL_TEMPLATE_SUFFIX}=${JSON.stringify(\n      extraTemplateData\n    )}`;\n  }\n  private getLibraryTemplate() {\n    if (!Object.keys(this.dataGroup.otherMetaCollectionGroup).length) {\n      return '';\n    }\n    const obj: Record<string, ExtraTemplateData> = {};\n    for (const key in this.dataGroup.otherMetaCollectionGroup) {\n      if (\n        Object.prototype.hasOwnProperty.call(\n          this.dataGroup.otherMetaCollectionGroup,\n          key\n        )\n      ) {\n        const element = this.dataGroup.otherMetaCollectionGroup[key];\n        const templateStr = element.templateList\n          .map((item) => item.content)\n          .join('');\n\n        const useComponents = getUseComponents(\n          Array.from(element.libraryPath),\n          Array.from(element.localPath),\n          this.entryPoint\n        );\n        const extraTemplateData: ExtraTemplateData = {\n          template: templateStr,\n          useComponents: useComponents,\n        };\n        obj[key] = extraTemplateData;\n      }\n    }\n    return `let library_${GLOBAL_TEMPLATE_SUFFIX}=${JSON.stringify(obj)}`;\n  }\n\n  getSelfUseComponents() {\n    if (!this.selfUseComponents) {\n      const selfMetaCollection =\n        this.selfMetaCollection ||\n        this.dataGroup.otherMetaCollectionGroup['$self'];\n      if (!selfMetaCollection) {\n        return {};\n      }\n      const useComponents = getUseComponents(\n        Array.from(selfMetaCollection.libraryPath),\n        Array.from(selfMetaCollection.localPath),\n        this.entryPoint\n      );\n      this.selfUseComponents = useComponents;\n    }\n    return this.selfUseComponents;\n  }\n}\n"
  },
  {
    "path": "src/builder/library/remove-publish-only.ts",
    "content": "import fs from 'fs-extra';\nimport { transformFromPromise } from 'ng-packagr/lib/graph/transform';\nimport { WRITE_PACKAGE_TRANSFORM } from 'ng-packagr/lib/ng-package/entry-point/write-package.di';\nimport {\n  EntryPointNode,\n  isEntryPointInProgress,\n} from 'ng-packagr/lib/ng-package/nodes';\nimport { NgPackagrOptions } from 'ng-packagr/lib/ng-package/options.di';\nimport path from 'path';\nimport { of } from 'rxjs';\n\nconst oldFactory = WRITE_PACKAGE_TRANSFORM.useFactory;\nexport function hookWritePackage() {\n  WRITE_PACKAGE_TRANSFORM.useFactory = myWritePackage;\n  return WRITE_PACKAGE_TRANSFORM;\n}\nfunction myWritePackage(options: NgPackagrOptions) {\n  return transformFromPromise(async (graph) => {\n    // todo 这里理论上不应该这么做,因为rxjs非同依赖会有一些小问题.但是不涉及到unsubscribe遇不到这些小问题,所以先这么做,未来再想办法\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\n    await oldFactory(options)(of(graph) as any).toPromise();\n    const entryPoint: EntryPointNode = graph.find(\n      // eslint-disable-next-line @typescript-eslint/no-explicit-any\n      isEntryPointInProgress() as any\n    )!;\n    if (!entryPoint.data.entryPoint.isSecondaryEntryPoint) {\n      const packageJsonPath = path.resolve(\n        entryPoint.data.entryPoint.destinationPath,\n        'package.json'\n      );\n      const packageJson = JSON.parse(\n        fs.readFileSync(packageJsonPath).toString()\n      );\n      delete packageJson.scripts.prepublishOnly;\n      fs.writeFileSync(\n        packageJsonPath,\n        JSON.stringify(packageJson, undefined, 2)\n      );\n    }\n  });\n}\n"
  },
  {
    "path": "src/builder/library/schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema\",\n  \"title\": \"ng-packagr Target\",\n  \"description\": \"ng-packagr target options for Build Architect. Use to build library projects.\",\n  \"type\": \"object\",\n  \"properties\": {\n    \"project\": {\n      \"type\": \"string\",\n      \"description\": \"The file path for the ng-packagr configuration file, relative to the current workspace.\"\n    },\n    \"tsConfig\": {\n      \"type\": \"string\",\n      \"description\": \"The full path for the TypeScript configuration file, relative to the current workspace.\"\n    },\n    \"watch\": {\n      \"type\": \"boolean\",\n      \"description\": \"Run build when files change.\",\n      \"default\": false\n    }\n  },\n  \"additionalProperties\": false,\n  \"required\": [\"project\"]\n}\n"
  },
  {
    "path": "src/builder/library/setup-component-data.service.ts",
    "content": "import { join, normalize, resolve, strings } from '@angular-devkit/core';\nimport { Inject, Injectable } from 'static-injector';\nimport { changeComponent } from '../component-template-inject/change-component';\nimport type { ExportLibraryComponentMeta } from '../library';\nimport { ResolvedDataGroup } from '../mini-program-compiler';\nimport { BuildPlatform } from '../platform/platform';\nimport {\n  LIBRARY_COMPONENT_METADATA_SUFFIX,\n  LIBRARY_OUTPUT_ROOTDIR,\n} from './const';\nimport { getComponentOutputPath } from './get-library-path';\nimport { getUseComponents } from './merge-using-component-path';\nimport { OutputTemplateMetadataService } from './output-template-metadata.service';\nimport { CustomStyleSheetProcessor } from './stylesheet-processor';\nimport { ENTRY_POINT_TOKEN, RESOLVED_DATA_GROUP_TOKEN } from './token';\n\n@Injectable()\nexport class SetupComponentDataService {\n  constructor(\n    @Inject(RESOLVED_DATA_GROUP_TOKEN)\n    private dataGroup: ResolvedDataGroup,\n    @Inject(ENTRY_POINT_TOKEN) private entryPoint: string,\n    private addGlobalTemplateService: OutputTemplateMetadataService,\n    private buildPlatform: BuildPlatform\n  ) {}\n  run(\n    data: string,\n    originFileName: string,\n    customStyleSheetProcessor: CustomStyleSheetProcessor\n  ) {\n    const changedData = changeComponent(data);\n    if (!changedData) {\n      return data;\n    }\n    const useComponentPath =\n      this.dataGroup.useComponentPath.get(originFileName)!;\n    const componentClassName = changedData.componentName;\n    const componentDirName = strings.dasherize(\n      strings.camelize(componentClassName)\n    );\n    const libraryPath = getComponentOutputPath(\n      this.entryPoint,\n      componentClassName\n    );\n    const styleUrlList = this.dataGroup.style.get(originFileName);\n    const styleContentList: string[] = [];\n    styleUrlList?.forEach((item) => {\n      styleContentList.push(customStyleSheetProcessor.styleMap.get(item)!);\n    });\n    const selfTemplateImportStr = this.dataGroup.otherMetaCollectionGroup[\n      '$self'\n    ]\n      ? `<import src=\"${resolve(\n          normalize('/'),\n          join(\n            normalize(LIBRARY_OUTPUT_ROOTDIR),\n            this.entryPoint,\n            'self' + this.buildPlatform.fileExtname.contentTemplate\n          )\n        )}\"/>`\n      : '';\n\n    const insertComponentData: ExportLibraryComponentMeta = {\n      id:\n        strings.classify(this.entryPoint) +\n        strings.classify(strings.camelize(componentDirName)),\n      className: componentClassName,\n      content:\n        selfTemplateImportStr +\n        this.dataGroup.outputContent.get(originFileName)!,\n      libraryPath: libraryPath,\n      useComponents: {\n        ...getUseComponents(\n          useComponentPath.libraryPath,\n          useComponentPath.localPath,\n          this.entryPoint\n        ),\n        ...this.addGlobalTemplateService.getSelfUseComponents(),\n      },\n      moduleId: this.entryPoint,\n    };\n    if (styleContentList.length) {\n      insertComponentData.style = styleContentList.join('\\n');\n    }\n\n    const list = changedData.content.split(/\\n|\\r\\n/g);\n    list.splice(\n      Math.max(list.length - 1, 0),\n      0,\n      `let ${componentClassName}_${LIBRARY_COMPONENT_METADATA_SUFFIX}=${JSON.stringify(\n        insertComponentData\n      )}`\n    );\n\n    return list.join('\\n');\n  }\n}\n"
  },
  {
    "path": "src/builder/library/stylesheet-processor.ts",
    "content": "import { StylesheetProcessor } from 'ng-packagr/lib/styles/stylesheet-processor';\n\nexport class CustomStyleSheetProcessor extends StylesheetProcessor {\n  styleMap = new Map<string, string>();\n  async process({\n    filePath,\n    content,\n  }: {\n    filePath: string;\n    content: string;\n  }): Promise<string> {\n    const result = await super.process({ filePath, content });\n    this.styleMap.set(filePath, result);\n    return '';\n  }\n}\n"
  },
  {
    "path": "src/builder/library/token.ts",
    "content": "import { InjectionToken } from 'static-injector';\n\nexport const RESOLVED_DATA_GROUP_TOKEN = new InjectionToken(\n  'RESOLVED_DATA_GROUP_TOKEN'\n);\nexport const ENTRY_POINT_TOKEN = new InjectionToken<string>(\n  'ENTRY_POINT_TOKEN'\n);\n\nexport const ENTRY_FILE_TOKEN = new InjectionToken<string>('ENTRY_FILE_TOKEN');\n"
  },
  {
    "path": "src/builder/library/type.ts",
    "content": "export interface ExtraTemplateData {\n  template: string;\n  useComponents?: Record<string, string>;\n  templateName?: string;\n  outputPath?: string;\n}\n\nexport interface ExportLibraryComponentMeta {\n  id: string;\n  content: string;\n  contentTemplate?: string;\n  style?: string;\n  className: string;\n  libraryPath: string;\n  useComponents: Record<string, string>;\n  moduleId: string;\n}\nexport interface LibraryComponentEntryMeta extends ExportLibraryComponentMeta {\n  importPath: string;\n  context: string;\n  contextPath: string;\n}\n"
  },
  {
    "path": "src/builder/mini-program-compiler/component-compiler.service.ts",
    "content": "import type { R3ComponentMetadata } from '@angular/compiler';\nimport { Inject, Injectable } from 'static-injector';\nimport { BuildPlatform } from '../platform/platform';\nimport { COMPONENT_META } from '../token/component.token';\nimport { ComponentContext, TemplateDefinition } from './parse-node';\n\n@Injectable()\nexport class ComponentCompilerService {\n  constructor(\n    private buildPlatform: BuildPlatform,\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\n    @Inject(COMPONENT_META) private componentMeta: R3ComponentMetadata<any>,\n    private componentContext: ComponentContext\n  ) {}\n\n  private collectionNode() {\n    const nodes = this.componentMeta.template.nodes;\n    const templateDefinition = new TemplateDefinition(\n      nodes,\n      this.componentContext\n    );\n    const list = templateDefinition.run();\n    return list.map((item) => item.getNodeMeta());\n  }\n\n  compile() {\n    const nodeList = this.collectionNode();\n    const result = this.buildPlatform.templateTransform.compile(nodeList);\n    return result;\n  }\n}\n"
  },
  {
    "path": "src/builder/mini-program-compiler/index.ts",
    "content": "export * from './mini-program-compiler.service';\nexport * from './meta-collection';\nexport * from './type';\nexport * from './parse-node';\n"
  },
  {
    "path": "src/builder/mini-program-compiler/meta-collection.ts",
    "content": "import { UseComponent } from './type';\n\nexport class MetaCollection {\n  localPath: Set<UseComponent> = new Set();\n  libraryPath: Set<UseComponent> = new Set();\n  templateList: { name: string; content: string }[] = [];\n  merge(other: MetaCollection) {\n    other.localPath.forEach((item) => {\n      this.localPath.add(item);\n    });\n    other.libraryPath.forEach((item) => {\n      this.libraryPath.add(item);\n    });\n    this.templateList.push(...other.templateList);\n  }\n}\n"
  },
  {
    "path": "src/builder/mini-program-compiler/mini-program-compiler.service.ts",
    "content": "import type {\n  R3ComponentMetadata,\n  R3DirectiveMetadata,\n  SelectorMatcher,\n} from '@angular/compiler';\nimport type { NgtscProgram } from '@angular/compiler-cli';\nimport type { NgCompiler } from '@angular/compiler-cli/src/ngtsc/core';\nimport type {\n  ClassRecord,\n  TraitCompiler,\n} from '@angular/compiler-cli/src/ngtsc/transform';\nimport { createCssSelectorForTs } from 'cyia-code-util';\nimport path from 'path';\nimport { Injectable, Injector } from 'static-injector';\nimport ts, { ClassDeclaration } from 'typescript';\nimport {\n  LIBRARY_COMPONENT_OUTPUT_PATH_SUFFIX,\n  LIBRARY_DIRECTIVE_LISTENERS_SUFFIX,\n  LIBRARY_DIRECTIVE_PROPERTIES_SUFFIX,\n} from '../library';\nimport { BuildPlatform } from '../platform/platform';\nimport { COMPONENT_META } from '../token/component.token';\nimport { angularCompilerPromise, literalResolve } from '../util';\nimport { ComponentCompilerService } from './component-compiler.service';\nimport { MetaCollection } from './meta-collection';\nimport { ComponentContext } from './parse-node';\nimport {\n  ComponentMetaFromLibrary,\n  DirectiveMetaFromLibrary,\n  MetaFromLibrary,\n  ResolvedDataGroup,\n  UseComponent,\n} from './type';\n\n@Injectable()\nexport class MiniProgramCompilerService {\n  private ngCompiler!: NgCompiler;\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  private componentMap = new Map<ClassDeclaration, R3ComponentMetadata<any>>();\n  private directiveMap = new Map<ClassDeclaration, R3DirectiveMetadata>();\n  private resolvedDataGroup: ResolvedDataGroup = {\n    style: new Map<string, string[]>(),\n    outputContent: new Map<string, string>(),\n    useComponentPath: new Map<\n      string,\n      {\n        localPath: UseComponent[];\n        libraryPath: UseComponent[];\n      }\n    >(),\n    otherMetaCollectionGroup: {},\n  };\n  constructor(\n    private ngTscProgram: NgtscProgram,\n    private injector: Injector,\n    private buildPlatform: BuildPlatform\n  ) {}\n  init() {\n    this.ngCompiler = this.ngTscProgram.compiler;\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\n    const traitCompiler: TraitCompiler = (this.ngCompiler as any).compilation\n      .traitCompiler;\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\n    const classes = (traitCompiler as any).classes as Map<\n      ts.ClassDeclaration,\n      ClassRecord\n    >;\n    for (const [classDeclaration, classRecord] of classes) {\n      const fileName = classDeclaration.getSourceFile().fileName;\n      const componentTraits = classRecord.traits.filter(\n        (trait) => trait.handler.name === 'ComponentDecoratorHandler'\n      );\n      if (componentTraits.length > 1) {\n        throw new Error('组件装饰器异常');\n      }\n      componentTraits.forEach((trait) => {\n        // eslint-disable-next-line @typescript-eslint/no-explicit-any\n        const meta: R3ComponentMetadata<any> = {\n          // eslint-disable-next-line @typescript-eslint/no-explicit-any\n          ...(trait as any).analysis?.meta,\n          // eslint-disable-next-line @typescript-eslint/no-explicit-any\n          ...(trait as any).resolution,\n        };\n        this.resolvedDataGroup.style.set(\n          path.normalize(fileName),\n          // eslint-disable-next-line @typescript-eslint/no-explicit-any\n          ((trait as any)?.analysis?.styleUrls || []).map(\n            (item: { url: string }) => this.resolveStyleUrl(fileName, item.url)\n          )\n        );\n        this.componentMap.set(\n          ts.getOriginalNode(classDeclaration) as ts.ClassDeclaration,\n          meta\n        );\n      });\n      const directiveTraits = classRecord.traits.filter(\n        (trait) => trait.handler.name === 'DirectiveDecoratorHandler'\n      );\n      if (directiveTraits.length > 1) {\n        throw new Error('指令装饰器异常');\n      }\n      directiveTraits.forEach((trait) => {\n        this.directiveMap.set(\n          ts.getOriginalNode(classDeclaration) as ts.ClassDeclaration,\n          // eslint-disable-next-line @typescript-eslint/no-explicit-any\n          (trait as any).analysis?.meta\n        );\n      });\n    }\n  }\n\n  async exportComponentBuildMetaMap() {\n    const { SelectorMatcher, CssSelector } = await angularCompilerPromise;\n    for (const [classDeclaration, meta] of this.componentMap) {\n      const fileName = path.normalize(\n        classDeclaration.getSourceFile().fileName\n      );\n      let directiveMatcher: SelectorMatcher | undefined;\n      // todo 这里断点\n      if (meta.declarations.length > 0) {\n        const matcher = new SelectorMatcher();\n        for (const directive of meta.declarations) {\n          const selector = directive.selector;\n          const directiveClassDeclaration = ts.getOriginalNode(\n            // eslint-disable-next-line @typescript-eslint/no-explicit-any\n            (directive as any).ref.node\n          ) as ts.ClassDeclaration;\n          const directiveMeta = this.directiveMap.get(\n            directiveClassDeclaration\n          );\n          const componentMeta = this.componentMap.get(\n            directiveClassDeclaration\n          );\n          let libraryMeta: MetaFromLibrary | undefined;\n          if (directive.isComponent) {\n            libraryMeta = this.getLibraryComponentMeta(\n              // eslint-disable-next-line @typescript-eslint/no-explicit-any\n              (directive as any).ref.node\n            );\n          }\n          if (!directive.isComponent && !directiveMeta) {\n            libraryMeta = this.getLibraryDirectiveMeta(\n              // eslint-disable-next-line @typescript-eslint/no-explicit-any\n              (directive as any).ref.node\n            );\n          }\n          matcher.addSelectables(CssSelector.parse(selector), {\n            directive,\n            directiveMeta,\n            componentMeta,\n            libraryMeta,\n          });\n        }\n        directiveMatcher = matcher;\n      }\n      const componentBuildMeta = this.buildComponentMeta(\n        directiveMatcher,\n        meta\n      );\n      this.resolvedDataGroup.outputContent.set(\n        path.normalize(fileName),\n        componentBuildMeta.content\n      );\n\n      this.resolvedDataGroup.useComponentPath.set(\n        path.normalize(fileName),\n        componentBuildMeta.useComponentPath\n      );\n      for (const key in componentBuildMeta.otherMetaGroup) {\n        if (\n          Object.prototype.hasOwnProperty.call(\n            componentBuildMeta.otherMetaGroup,\n            key\n          )\n        ) {\n          const element = componentBuildMeta.otherMetaGroup[key];\n          this.resolvedDataGroup.otherMetaCollectionGroup[key] =\n            this.resolvedDataGroup.otherMetaCollectionGroup[key] ||\n            new MetaCollection();\n          this.resolvedDataGroup.otherMetaCollectionGroup[key].merge(element);\n        }\n      }\n    }\n\n    this.resolvedDataGroup.useComponentPath.forEach((value, key) => {\n      value.libraryPath = Array.from(new Set(value.libraryPath));\n      value.localPath = Array.from(new Set(value.localPath));\n    });\n\n    return this.resolvedDataGroup;\n  }\n\n  private buildComponentMeta(\n    directiveMatcher: SelectorMatcher | undefined,\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\n    componentMeta: R3ComponentMetadata<any>\n  ) {\n    const injector = Injector.create({\n      parent: this.injector,\n      providers: [\n        { provide: ComponentCompilerService },\n        { provide: COMPONENT_META, useValue: componentMeta },\n        {\n          provide: ComponentContext,\n          useFactory: () => {\n            return new ComponentContext(directiveMatcher);\n          },\n        },\n      ],\n    });\n    const instance = injector.get(ComponentCompilerService);\n    return instance.compile();\n  }\n  private resolveStyleUrl(componentPath: string, styleUrl: string) {\n    return path.normalize(path.resolve(path.dirname(componentPath), styleUrl));\n  }\n  getDirectiveMap() {\n    return this.directiveMap;\n  }\n  getComponentMap() {\n    return this.componentMap;\n  }\n  private getLibraryDirectiveMeta(\n    classDeclaration: ts.ClassDeclaration\n  ): DirectiveMetaFromLibrary | undefined {\n    let listeners: string[] = [];\n    let properties: string[] = [];\n    const directiveName = classDeclaration.name!.getText();\n    const selector = createCssSelectorForTs(classDeclaration.getSourceFile());\n    const listenersNode = selector.queryOne(\n      `VariableDeclaration[name=${directiveName}_${LIBRARY_DIRECTIVE_LISTENERS_SUFFIX}]`\n    ) as ts.VariableDeclaration;\n    if (listenersNode) {\n      listeners = literalResolve(listenersNode.type!.getText());\n    }\n    const propertiesNode = selector.queryOne(\n      `VariableDeclaration[name=${directiveName}_${LIBRARY_DIRECTIVE_PROPERTIES_SUFFIX}]`\n    ) as ts.VariableDeclaration;\n    if (propertiesNode) {\n      properties = literalResolve(propertiesNode.type!.getText());\n    }\n    return {\n      isComponent: false,\n      listeners: listeners,\n      properties: properties,\n    };\n  }\n  private getLibraryComponentMeta(\n    classDeclaration: ts.ClassDeclaration\n  ): ComponentMetaFromLibrary | undefined {\n    const directiveName = classDeclaration.name!.getText();\n    const selector = createCssSelectorForTs(classDeclaration.getSourceFile());\n    const exportPathNode = selector.queryOne(\n      `VariableDeclaration[name=${directiveName}_${LIBRARY_COMPONENT_OUTPUT_PATH_SUFFIX}]`\n    ) as ts.VariableDeclaration;\n    if (!exportPathNode) {\n      return undefined;\n    }\n    const exportPath = exportPathNode.type!.getText();\n    return {\n      exportPath: literalResolve(exportPath),\n      ...this.getLibraryDirectiveMeta(classDeclaration)!,\n      isComponent: true,\n    };\n  }\n}\n"
  },
  {
    "path": "src/builder/mini-program-compiler/parse-node/bound-text.ts",
    "content": "import type { BoundText } from '../../angular-internal/ast.type';\nimport {\n  NgBoundTextMeta,\n  NgNodeKind,\n  NgNodeMeta,\n  ParsedNode,\n} from './interface';\n\nexport class ParsedNgBoundText implements ParsedNode<NgBoundTextMeta> {\n  kind = NgNodeKind.BoundText;\n\n  constructor(\n    private node: BoundText,\n    public parent: ParsedNode<NgNodeMeta> | undefined,\n    public index: number\n  ) {}\n  getNodeMeta(): NgBoundTextMeta {\n    return {\n      kind: NgNodeKind.BoundText,\n      index: this.index,\n    };\n  }\n}\n"
  },
  {
    "path": "src/builder/mini-program-compiler/parse-node/component-context.ts",
    "content": "/* eslint-disable @typescript-eslint/no-explicit-any */\nimport type {\n  R3ComponentMetadata,\n  R3DirectiveDependencyMetadata,\n  R3DirectiveMetadata,\n  SelectorMatcher,\n} from '@angular/compiler';\n\nimport type {\n  ImportedFile,\n  Reference,\n} from '@angular/compiler-cli/src/ngtsc/imports';\nimport { Injectable } from 'static-injector';\nimport ts from 'typescript';\nimport * as t from '../../angular-internal/ast.type';\nimport { createCssSelector } from '../../angular-internal/template';\nimport { getAttrsForDirectiveMatching } from '../../angular-internal/util';\nimport type { DirectiveMetaFromLibrary, MetaFromLibrary } from '../type';\nimport type { MatchedDirective, MatchedMeta } from './type';\n\n@Injectable()\nexport class ComponentContext {\n  constructor(private directiveMatcher: SelectorMatcher | undefined) {}\n  matchDirective(node: t.Element): MatchedMeta[] {\n    if (!this.directiveMatcher) {\n      return [];\n    }\n    const name: string = node.name;\n    const selector = createCssSelector(\n      name,\n      getAttrsForDirectiveMatching(node)\n    );\n    const result: MatchedMeta[] = [];\n    this.directiveMatcher.match(\n      selector,\n      (\n        selector,\n        meta: {\n          directive: R3DirectiveDependencyMetadata & {\n            ref: Reference<ts.ClassDeclaration>;\n            importedFile: ImportedFile;\n          };\n          componentMeta: R3ComponentMetadata<any>;\n          directiveMeta: R3DirectiveMetadata;\n          libraryMeta: MetaFromLibrary;\n        }\n      ) => {\n        let item: Partial<MatchedMeta>;\n        const isComponent: boolean = !!meta.directive.isComponent;\n        if (isComponent) {\n          item = {\n            isComponent,\n            outputs: meta.directive.outputs,\n            filePath: (meta.directive.importedFile as ts.SourceFile).fileName,\n            selector: meta.directive.selector,\n            className: meta.directive.ref.node.name!.getText(),\n            listeners:\n              Object.keys(meta.componentMeta?.host?.listeners || {}) || [],\n            inputs: meta.directive.inputs,\n          };\n          if (meta.libraryMeta?.isComponent) {\n            item.exportPath = meta.libraryMeta.exportPath;\n            item.listeners = meta.libraryMeta.listeners;\n            item.properties = meta.libraryMeta.properties;\n          }\n        } else {\n          item = {\n            isComponent,\n            listeners:\n              Object.keys(meta.directiveMeta?.host?.listeners || {}) || [],\n            properties:\n              Object.keys(meta.directiveMeta?.host?.properties || {}) || [],\n            inputs: meta.directive.inputs,\n            outputs: meta.directive.outputs,\n          };\n          if (meta.libraryMeta && !meta.libraryMeta.isComponent) {\n            (item as MatchedDirective).listeners = (\n              meta.libraryMeta as DirectiveMetaFromLibrary\n            ).listeners!;\n            (item as MatchedDirective).properties = (\n              meta.libraryMeta as DirectiveMetaFromLibrary\n            ).properties!;\n          }\n        }\n        result.push(item as MatchedMeta);\n      }\n    );\n    return result;\n  }\n}\n"
  },
  {
    "path": "src/builder/mini-program-compiler/parse-node/content.ts",
    "content": "import type { Content } from '../../angular-internal/ast.type';\nimport { NgContentMeta, NgNodeKind, NgNodeMeta, ParsedNode } from './interface';\n\nconst SELECT_NAME_VALUE_REGEXP = /^\\[slot=[\"']?([^\"']*)[\"']?\\]$/;\nexport class ParsedNgContent implements ParsedNode<NgContentMeta> {\n  kind = NgNodeKind.Content;\n\n  constructor(\n    private node: Content,\n    public parent: ParsedNode<NgNodeMeta> | undefined,\n    public index: number\n  ) {}\n  getNodeMeta(): NgContentMeta {\n    const nameAttr = this.node.attributes.find(\n      (item) => item.name === 'select'\n    );\n    let value: string | undefined;\n    if (nameAttr) {\n      const result = nameAttr.value.match(SELECT_NAME_VALUE_REGEXP);\n      if (!result) {\n        throw new Error(\n          `ng-content未匹配到指定格式的select,value:${nameAttr.value},需要格式为[slot=\"xxxx\"]`\n        );\n      }\n      value = result[1];\n    }\n    return {\n      kind: NgNodeKind.Content,\n      name: value,\n      index: this.index,\n    };\n  }\n}\n"
  },
  {
    "path": "src/builder/mini-program-compiler/parse-node/element.ts",
    "content": "import type { Element } from '../../angular-internal/ast.type';\nimport { ComponentContext } from './component-context';\nimport { NgElementMeta, NgNodeKind, NgNodeMeta, ParsedNode } from './interface';\nimport type { MatchedComponent, MatchedDirective } from './type';\n\nexport class ParsedNgElement implements ParsedNode<NgElementMeta> {\n  private tagName!: string;\n  private children: ParsedNode<NgNodeMeta>[] = [];\n  attributeObject: Record<string, string> = {};\n  kind = NgNodeKind.Element;\n  inputs: string[] = [];\n  outputs: string[] = [];\n  singleClosedTag = false;\n  constructor(\n    private node: Element,\n    public parent: ParsedNode<NgNodeMeta> | undefined,\n    private componentMeta: MatchedComponent | undefined,\n    public index: number,\n    private directiveMeta: MatchedDirective | undefined\n  ) {}\n  private analysis() {\n    this.getTagName();\n    this.node.attributes\n      .filter((item) => item.name !== 'class' && item.name !== 'style')\n      .forEach((item) => {\n        this.attributeObject[item.name] = item.value;\n      });\n\n    this.node.inputs.forEach((input) => {\n      if (input.type === 0) {\n        this.inputs.push(input.name);\n      }\n    });\n    this.node.outputs.forEach((output) => {\n      this.outputs.push(output.name);\n    });\n\n    if (\n      !this.node.endSourceSpan ||\n      this.node.startSourceSpan.end.offset ===\n        this.node.endSourceSpan.end.offset\n    ) {\n      this.singleClosedTag = true;\n    }\n  }\n  private getTagName() {\n    const originTagName = this.node.name;\n    this.tagName = originTagName;\n    if (/^(div|p|h1|h2|h3|h4|h5|h6|span)$/.test(originTagName)) {\n      this.tagName = 'view';\n    } else if (originTagName === 'ng-container') {\n      this.tagName = 'block';\n    }\n  }\n\n  appendNgNodeChild(child: ParsedNode<NgNodeMeta>) {\n    this.children.push(child);\n  }\n  getNodeMeta(): NgElementMeta {\n    this.analysis();\n\n    return {\n      kind: NgNodeKind.Element,\n      tagName: this.tagName,\n      children: this.children.map((child) => child.getNodeMeta()),\n      inputs: this.inputs,\n      outputs: this.outputs,\n      attributes: this.attributeObject,\n      singleClosedTag: this.singleClosedTag,\n      componentMeta: this.componentMeta,\n      index: this.index,\n      directiveMeta: this.directiveMeta,\n    };\n  }\n}\n"
  },
  {
    "path": "src/builder/mini-program-compiler/parse-node/index.ts",
    "content": "export * from './component-context';\nexport * from './template-definition';\nexport * from './interface';\n"
  },
  {
    "path": "src/builder/mini-program-compiler/parse-node/interface.ts",
    "content": "import type { MatchedComponent, MatchedDirective } from './type';\n\nexport interface ParsedNode<T> {\n  kind: NgNodeKind;\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  parent: ParsedNode<any> | undefined;\n  getNodeMeta(): T;\n  index: number;\n}\nexport enum NgNodeKind {\n  Element,\n  BoundText,\n  Text,\n  Template,\n  Content,\n}\nexport interface NgNodeMeta {\n  kind: NgNodeKind;\n  index: number;\n}\nexport interface NgElementMeta extends NgNodeMeta {\n  kind: NgNodeKind.Element;\n  tagName: string;\n  children: NgNodeMeta[];\n  attributes: Record<string, string>;\n  inputs: string[];\n  outputs: string[];\n  singleClosedTag: boolean;\n  componentMeta: MatchedComponent | undefined;\n  directiveMeta: MatchedDirective | undefined;\n}\nexport interface NgBoundTextMeta extends NgNodeMeta {\n  kind: NgNodeKind.BoundText;\n}\nexport interface NgTextMeta extends NgNodeMeta {\n  kind: NgNodeKind.Text;\n  value: string;\n}\n\nexport interface NgTemplateMeta extends NgNodeMeta {\n  kind: NgNodeKind.Template;\n  children: NgNodeMeta[];\n  defineTemplateName: string;\n}\nexport interface NgContentMeta extends NgNodeMeta {\n  kind: NgNodeKind.Content;\n  name: string | undefined;\n}\n"
  },
  {
    "path": "src/builder/mini-program-compiler/parse-node/template-definition.ts",
    "content": "import type {\n  AST,\n  AstVisitor,\n  Binary,\n  BindingPipe,\n  Call,\n  Chain,\n  Conditional,\n  ImplicitReceiver,\n  Interpolation,\n  KeyedRead,\n  KeyedWrite,\n  LiteralArray,\n  LiteralMap,\n  LiteralPrimitive,\n  NonNullAssert,\n  PrefixNot,\n  PropertyRead,\n  PropertyWrite,\n  SafeCall,\n  SafeKeyedRead,\n  SafePropertyRead,\n  Text,\n  TmplAstDeferredBlock,\n  TmplAstDeferredBlockError,\n  TmplAstDeferredBlockLoading,\n  TmplAstDeferredBlockPlaceholder,\n  TmplAstDeferredTrigger,\n  TmplAstForLoopBlock,\n  TmplAstForLoopBlockEmpty,\n  TmplAstIfBlock,\n  TmplAstIfBlockBranch,\n  TmplAstNode,\n  TmplAstRecursiveVisitor,\n  TmplAstSwitchBlock,\n  TmplAstSwitchBlockCase,\n  TmplAstUnknownBlock,\n  Visitor,\n} from '@angular/compiler';\n\nimport * as t from '../../angular-internal/ast.type';\nimport { ParsedNgBoundText } from './bound-text';\nimport { ComponentContext } from './component-context';\nimport { ParsedNgContent } from './content';\nimport { ParsedNgElement } from './element';\nimport { NgNodeMeta, ParsedNode } from './interface';\nimport { ParsedNgTemplate } from './template';\nimport { ParsedNgText } from './text';\nimport { MatchedComponent, MatchedDirective } from './type';\n\nexport class TemplateDefinition implements TmplAstRecursiveVisitor {\n  private templateDefinitionMap = new Map<t.Template, TemplateDefinition>();\n  private parentNode: ParsedNgElement | ParsedNgTemplate | undefined;\n  list: ParsedNode<NgNodeMeta>[] = [];\n  private declIndex = 0;\n\n  astVisitor = new CustomAstVisitor(() => {\n    this.declIndex++;\n  });\n  constructor(\n    private nodes: t.Node[],\n    private componentContext: ComponentContext\n  ) {}\n  init() {}\n  visit?(node: t.Node) {}\n  visitElement(element: t.Element) {\n    const nodeIndex = this.declIndex++;\n    let componentMeta: MatchedComponent | undefined;\n    let directiveMeta: MatchedDirective | undefined;\n    const result = this.componentContext.matchDirective(element);\n    const directiveMetaList = result.filter((item) => {\n      if (item.isComponent) {\n        componentMeta = item;\n      }\n      return !item.isComponent;\n    });\n    if (directiveMetaList.length) {\n      directiveMeta = {\n        isComponent: false,\n        listeners: directiveMetaList.map((item) => item.listeners).flat(),\n        properties: directiveMetaList.map((item) => item.properties).flat(),\n        inputs: directiveMetaList.map((item) => item.inputs).flat(),\n        outputs: directiveMetaList.map((item) => item.outputs).flat(),\n      };\n    }\n\n    const instance = new ParsedNgElement(\n      element,\n      this.parentNode,\n      componentMeta,\n      nodeIndex,\n      directiveMeta\n    );\n    if (this.parentNode) {\n      this.parentNode.appendNgNodeChild(instance);\n    }\n    element.inputs.forEach((item) => {\n      item.value.visit(this.astVisitor);\n    });\n    const oldParent = this.parentNode;\n    this.parentNode = instance;\n    this.prepareRefsArray(element.references);\n\n    visitAll(this, element.children);\n    this.parentNode = oldParent;\n    if (!this.parentNode) {\n      this.list.push(instance);\n    }\n  }\n\n  visitTemplate(template: t.Template) {\n    const nodeIndex = this.declIndex++;\n    const templateInstance = new ParsedNgTemplate(\n      template,\n      this.parentNode,\n      nodeIndex\n    );\n    if (this.parentNode) {\n      this.parentNode.appendNgNodeChild(templateInstance);\n    }\n    this.prepareRefsArray(template.references);\n    template.templateAttrs.forEach((item) => {\n      if (typeof item.value !== 'string') {\n        item.value.visit(this.astVisitor);\n      }\n    });\n    template.inputs.forEach((item) => {\n      item.value.visit(this.astVisitor);\n    });\n    const instance = new TemplateDefinition(\n      template.children,\n      this.componentContext\n    );\n    instance.parentNode = templateInstance;\n    this.templateDefinitionMap.set(template, instance);\n\n    instance.run();\n    if (!this.parentNode) {\n      this.list.push(templateInstance);\n    }\n  }\n  visitContent(content: t.Content) {\n    const nodeIndex = this.declIndex++;\n    const instance = new ParsedNgContent(content, this.parentNode, nodeIndex);\n    if (this.parentNode) {\n      this.parentNode.appendNgNodeChild(instance);\n    } else {\n      this.list.push(instance);\n    }\n  }\n  visitVariable(variable: t.Variable) {}\n  visitReference(reference: t.Reference) {}\n  visitTextAttribute(attribute: t.TextAttribute) {}\n  visitBoundAttribute(attribute: t.BoundAttribute) {}\n  visitBoundEvent(attribute: t.BoundEvent) {}\n  visitText(text: t.Text) {\n    const nodeIndex = this.declIndex++;\n    const instance = new ParsedNgText(text, this.parentNode, nodeIndex);\n    if (this.parentNode) {\n      this.parentNode.appendNgNodeChild(instance);\n    } else {\n      this.list.push(instance);\n    }\n  }\n  visitBoundText(text: t.BoundText) {\n    const nodeIndex = this.declIndex++;\n    text.value.visit(this.astVisitor);\n    const instance = new ParsedNgBoundText(text, this.parentNode, nodeIndex);\n    if (this.parentNode) {\n      this.parentNode.appendNgNodeChild(instance);\n    } else {\n      this.list.push(instance);\n    }\n  }\n  visitIcu(icu: t.Icu) {}\n  run() {\n    visitAll(this, this.nodes);\n    return this.list;\n  }\n  prepareRefsArray(refs: t.Reference[]) {\n    if (!refs || !refs.length) {\n      return;\n    }\n    refs.forEach((item) => {\n      this.declIndex++;\n    });\n  }\n  // todo\n  visitDeferredBlock(deferred: TmplAstDeferredBlock): void {}\n  visitDeferredBlockError(block: TmplAstDeferredBlockError): void {}\n  visitDeferredBlockLoading(block: TmplAstDeferredBlockLoading): void {}\n  visitDeferredBlockPlaceholder(block: TmplAstDeferredBlockPlaceholder): void {}\n  visitDeferredTrigger(trigger: TmplAstDeferredTrigger): void {}\n  visitForLoopBlock(block: TmplAstForLoopBlock): void {}\n  visitForLoopBlockEmpty(block: TmplAstForLoopBlockEmpty): void {}\n  visitIfBlock(block: TmplAstIfBlock): void {}\n  visitIfBlockBranch(block: TmplAstIfBlockBranch): void {}\n  visitSwitchBlock(block: TmplAstSwitchBlock): void {}\n  visitSwitchBlockCase(block: TmplAstSwitchBlockCase): void {}\n  visitUnknownBlock(block: TmplAstUnknownBlock): void {}\n}\nexport function visitAll(visitor: TemplateDefinition, nodes: TmplAstNode[]) {\n  for (const node of nodes) {\n    node.visit(visitor);\n  }\n}\nclass CustomAstVisitor implements AstVisitor {\n  constructor(private pipeCallback: () => void) {}\n  visitCall(ast: Call) {\n    ast.receiver.visit(this);\n    this.visitAll(ast.args);\n  }\n  visitSafeCall(ast: SafeCall) {\n    ast.receiver.visit(this);\n    this.visitAll(ast.args);\n  }\n  visitSafeKeyedRead(ast: SafeKeyedRead) {\n    ast.receiver.visit(this);\n    ast.key.visit(this);\n  }\n  visitImplicitReceiver(ast: ImplicitReceiver) {}\n  visitInterpolation(ast: Interpolation) {\n    this.visitAll(ast.expressions);\n  }\n  visitKeyedRead(ast: KeyedRead) {\n    ast.receiver.visit(this);\n    ast.key.visit(this);\n  }\n  visitKeyedWrite(ast: KeyedWrite) {\n    ast.receiver.visit(this);\n    ast.key.visit(this);\n    ast.value.visit(this);\n  }\n  visitLiteralArray(ast: LiteralArray) {\n    this.visitAll(ast.expressions);\n  }\n  visitLiteralMap(ast: LiteralMap) {\n    this.visitAll(ast.values);\n  }\n  visitLiteralPrimitive(ast: LiteralPrimitive) {}\n  visitPipe(ast: BindingPipe) {\n    this.pipeCallback();\n  }\n  visitPrefixNot(ast: PrefixNot) {\n    ast.expression.visit(this);\n  }\n  visitNonNullAssert(ast: NonNullAssert) {\n    ast.expression.visit(this);\n  }\n  visitPropertyRead(ast: PropertyRead) {\n    ast.receiver.visit(this);\n  }\n  visitPropertyWrite(ast: PropertyWrite) {}\n\n  visitSafePropertyRead(ast: SafePropertyRead) {}\n  visitBinary(ast: Binary) {\n    ast.left.visit(this);\n    ast.right.visit(this);\n  }\n  visitChain(ast: Chain) {\n    this.visitAll(ast.expressions);\n  }\n  visitConditional(ast: Conditional) {\n    ast.condition.visit(this);\n    ast.trueExp.visit(this);\n    ast.falseExp.visit(this);\n  }\n  visit(ast: AST) {}\n  visitAll(asts: AST[]) {\n    for (let i = 0; i < asts.length; ++i) {\n      const original = asts[i];\n      original.visit(this);\n    }\n  }\n}\n"
  },
  {
    "path": "src/builder/mini-program-compiler/parse-node/template.ts",
    "content": "import type { Template } from '../../angular-internal/ast.type';\nimport {\n  NgNodeKind,\n  NgNodeMeta,\n  NgTemplateMeta,\n  ParsedNode,\n} from './interface';\n\nexport class ParsedNgTemplate implements ParsedNode<NgTemplateMeta> {\n  kind = NgNodeKind.Template;\n  private children: ParsedNode<NgNodeMeta>[] = [];\n\n  constructor(\n    private node: Template,\n    public parent: ParsedNode<NgNodeMeta> | undefined,\n    public index: number\n  ) {}\n\n  appendNgNodeChild(child: ParsedNode<NgNodeMeta>) {\n    this.children.push(child);\n  }\n  private getTemplateName(): string {\n    if (this.node.references && this.node.references.length) {\n      return this.node.references[0].name;\n    } else {\n      return `ngDefault_${this.index}`;\n    }\n  }\n\n  getNodeMeta(): NgTemplateMeta {\n    const directive = this.getTemplateName()!;\n    const meta: NgTemplateMeta = {\n      kind: NgNodeKind.Template,\n      children: this.children.map((child) => child.getNodeMeta()),\n      index: this.index,\n      defineTemplateName: directive,\n    };\n\n    return meta;\n  }\n}\n"
  },
  {
    "path": "src/builder/mini-program-compiler/parse-node/text.ts",
    "content": "import type { Text } from '../../angular-internal/ast.type';\nimport { NgNodeKind, NgNodeMeta, NgTextMeta, ParsedNode } from './interface';\n\nexport class ParsedNgText implements ParsedNode<NgTextMeta> {\n  kind = NgNodeKind.Text;\n\n  constructor(\n    private node: Text,\n    public parent: ParsedNode<NgNodeMeta> | undefined,\n    public index: number\n  ) {}\n\n  getNodeMeta(): NgTextMeta {\n    return {\n      kind: NgNodeKind.Text,\n      value: this.node.value,\n      index: this.index,\n    };\n  }\n}\n"
  },
  {
    "path": "src/builder/mini-program-compiler/parse-node/type.ts",
    "content": "export type MatchedMeta = MatchedComponent | MatchedDirective;\nexport interface MatchedComponent {\n  isComponent: true;\n  selector: string;\n  filePath: string;\n  exportPath: string;\n  className: string;\n  listeners: string[];\n  properties: string[];\n  inputs: string[];\n  outputs: string[];\n}\nexport interface MatchedDirective {\n  isComponent: false;\n  listeners: string[];\n  properties: string[];\n  inputs: string[];\n  outputs: string[];\n}\n"
  },
  {
    "path": "src/builder/mini-program-compiler/type.ts",
    "content": "import { MetaCollection } from './meta-collection';\n\nexport interface ComponentMetaFromLibrary {\n  isComponent: true;\n  exportPath: string;\n  listeners: string[];\n  properties: string[];\n}\nexport interface DirectiveMetaFromLibrary {\n  isComponent: false;\n  listeners: string[];\n  properties: string[];\n}\nexport type MetaFromLibrary =\n  | ComponentMetaFromLibrary\n  | DirectiveMetaFromLibrary;\n\nexport interface UseComponent {\n  selector: string;\n  className: string;\n  path: string;\n}\nexport interface ResolvedDataGroup {\n  style: Map<string, string[]>;\n  outputContent: Map<string, string>;\n  useComponentPath: Map<\n    string,\n    {\n      localPath: UseComponent[];\n      libraryPath: UseComponent[];\n    }\n  >;\n  otherMetaCollectionGroup: Record<string, MetaCollection>;\n}\n"
  },
  {
    "path": "src/builder/platform/bd/bdzn-platform.ts",
    "content": "import * as fs from 'fs-extra';\nimport * as path from 'path';\nimport { Injectable } from 'static-injector';\nimport { BuildPlatform } from '../platform';\nimport { BdZnTransform } from './bdzn.transform';\n\n@Injectable()\nexport class BdZnBuildPlatform extends BuildPlatform {\n  packageName = 'bd';\n  globalObject = 'swan';\n  globalVariablePrefix = 'swan.__window';\n  fileExtname = {\n    style: '.css',\n    logic: '.js',\n    content: '.swan',\n    contentTemplate: '.swan',\n  };\n  importTemplate = `${fs\n    .readFileSync(path.resolve(__dirname, '../template/app-template.js'))\n    .toString()};\n    swan.__global = swan.__window = obj;`;\n  constructor(public templateTransform: BdZnTransform) {\n    super(templateTransform);\n  }\n}\n"
  },
  {
    "path": "src/builder/platform/bd/bdzn.transform.ts",
    "content": "import { Injectable } from 'static-injector';\nimport { WxTransformLike } from '../template-transform-strategy/wx-like/wx-transform.base';\n\n@Injectable()\nexport class BdZnTransform extends WxTransformLike {\n  override directivePrefix = 's';\n  override seq = '-';\n  override templateInterpolation: [string, string] = ['{{{', '}}}'];\n}\n"
  },
  {
    "path": "src/builder/platform/dd/dd-platform.ts",
    "content": "import * as fs from 'fs-extra';\nimport * as path from 'path';\nimport { Injectable } from 'static-injector';\nimport { BuildPlatform } from '../platform';\nimport { DdTransform } from './dd.transform';\n\n@Injectable()\nexport class DdBuildPlatform extends BuildPlatform {\n  packageName = 'dd';\n  globalObject = 'dd';\n  globalVariablePrefix = 'dd.__window';\n  fileExtname = {\n    style: '.acss',\n    logic: '.js',\n    content: '.axml',\n    contentTemplate: '.axml',\n  };\n  importTemplate = `${fs\n    .readFileSync(path.resolve(__dirname, '../template/app-template.js'))\n    .toString()};\n    dd.__global = dd.__window = obj;`;\n  constructor(public templateTransform: DdTransform) {\n    super(templateTransform);\n  }\n}\n"
  },
  {
    "path": "src/builder/platform/dd/dd.transform.ts",
    "content": "import { Injectable } from 'static-injector';\nimport { WxTransformLike } from '../template-transform-strategy/wx-like/wx-transform.base';\n\n@Injectable()\nexport class DdTransform extends WxTransformLike {\n  directivePrefix = 'a';\n}\n"
  },
  {
    "path": "src/builder/platform/index.ts",
    "content": "export * from './platform-inject-config';\nexport * from './type';\nexport * from './platform';\n"
  },
  {
    "path": "src/builder/platform/jd/jd-platform.ts",
    "content": "import * as fs from 'fs-extra';\nimport * as path from 'path';\nimport { Injectable } from 'static-injector';\nimport { BuildPlatform } from '../platform';\nimport { JdTransform } from './jd.transform';\n\n@Injectable()\nexport class JdBuildPlatform extends BuildPlatform {\n  packageName = 'jd';\n  globalObject = 'jd';\n  globalVariablePrefix = 'jd.__window';\n  fileExtname = {\n    style: '.jxss',\n    logic: '.js',\n    content: '.jxml',\n    contentTemplate: '.jxml',\n  };\n  importTemplate = `${fs\n    .readFileSync(path.resolve(__dirname, '../template/app-template.js'))\n    .toString()};\n    jd.__global = jd.__window = obj;`;\n  constructor(public templateTransform: JdTransform) {\n    super(templateTransform);\n  }\n}\n"
  },
  {
    "path": "src/builder/platform/jd/jd.transform.ts",
    "content": "import { Injectable } from 'static-injector';\nimport { WxTransformLike } from '../template-transform-strategy/wx-like/wx-transform.base';\n\n@Injectable()\nexport class JdTransform extends WxTransformLike {\n  directivePrefix = 'jd';\n}\n"
  },
  {
    "path": "src/builder/platform/library/library-platform.ts",
    "content": "import { Injectable } from 'static-injector';\nimport { BuildPlatform } from '../platform';\nimport { LibraryTransform } from './library.transform';\n\nexport const ERROR_VALUE = '!!!library_can_not_use!!!';\n@Injectable()\nexport class LibraryBuildPlatform extends BuildPlatform {\n  globalObject = ERROR_VALUE;\n  globalVariablePrefix = ERROR_VALUE;\n  fileExtname = {\n    style: '${fileExtname.style}',\n    logic: '${fileExtname.logic}',\n    content: '${fileExtname.content}',\n    contentTemplate: '${fileExtname.contentTemplate}',\n  };\n  importTemplate = ERROR_VALUE;\n  constructor(public templateTransform: LibraryTransform) {\n    super(templateTransform);\n  }\n}\n"
  },
  {
    "path": "src/builder/platform/library/library.transform.ts",
    "content": "import { Injectable } from 'static-injector';\nimport {\n  EVENT_PREFIX_REGEXP,\n  WxTransformLike,\n} from '../template-transform-strategy/wx-like/wx-transform.base';\n\n@Injectable()\nexport class LibraryTransform extends WxTransformLike {\n  directivePrefix = '${directivePrefix}';\n  templateInterpolation: [string, string] = [\n    '${templateInterpolation[0]}',\n    '${templateInterpolation[1]}',\n  ];\n\n  override eventListConvert = (list: string[]) => {\n    return `\\${eventListConvert(${JSON.stringify(list)})}`;\n  };\n}\n"
  },
  {
    "path": "src/builder/platform/platform-inject-config.ts",
    "content": "import { BdZnBuildPlatform } from './bd/bdzn-platform';\nimport { BdZnTransform } from './bd/bdzn.transform';\nimport { DdBuildPlatform } from './dd/dd-platform';\nimport { DdTransform } from './dd/dd.transform';\nimport { JdBuildPlatform } from './jd/jd-platform';\nimport { JdTransform } from './jd/jd.transform';\nimport { LibraryBuildPlatform } from './library/library-platform';\nimport { LibraryTransform } from './library/library.transform';\nimport { BuildPlatform, PlatformType } from './platform';\nimport { QqBuildPlatform } from './qq/qq-platform';\nimport { QqTransform } from './qq/qq.transform';\nimport { WxBuildPlatform } from './wx/wx-platform';\nimport { WxTransform } from './wx/wx.transform';\nimport { ZfbBuildPlatform } from './zfb/zfb-platform';\nimport { ZfbTransform } from './zfb/zfb.transform';\nimport { ZjBuildPlatform } from './zjtd/zj-platform';\nimport { ZjTransform } from './zjtd/zj.transform';\n\nexport function getBuildPlatformInjectConfig(platform: PlatformType) {\n  switch (platform) {\n    case PlatformType.wx:\n      return [\n        { provide: WxTransform },\n        { provide: WxBuildPlatform },\n        { provide: BuildPlatform, useClass: WxBuildPlatform },\n      ];\n    case PlatformType.zj:\n      return [\n        { provide: ZjTransform },\n        { provide: ZjBuildPlatform },\n        { provide: BuildPlatform, useClass: ZjBuildPlatform },\n      ];\n    case PlatformType.jd:\n      return [\n        { provide: JdTransform },\n        { provide: JdBuildPlatform },\n        { provide: BuildPlatform, useClass: JdBuildPlatform },\n      ];\n    case PlatformType.bdzn:\n      return [\n        { provide: BdZnTransform },\n        { provide: BdZnBuildPlatform },\n        { provide: BuildPlatform, useClass: BdZnBuildPlatform },\n      ];\n    case PlatformType.zfb:\n      return [\n        { provide: ZfbTransform },\n        { provide: ZfbBuildPlatform },\n        { provide: BuildPlatform, useClass: ZfbBuildPlatform },\n      ];\n    case PlatformType.qq:\n      return [\n        { provide: QqTransform },\n        { provide: QqBuildPlatform },\n        { provide: BuildPlatform, useClass: QqBuildPlatform },\n      ];\n    case PlatformType.dd:\n      return [\n        { provide: DdTransform },\n        { provide: DdBuildPlatform },\n        { provide: BuildPlatform, useClass: DdBuildPlatform },\n      ];\n    case PlatformType.library:\n      return [\n        { provide: LibraryTransform },\n        { provide: LibraryBuildPlatform },\n        { provide: BuildPlatform, useClass: LibraryBuildPlatform },\n      ];\n    default:\n      throw new Error('未能匹配到相关平台');\n  }\n}\n"
  },
  {
    "path": "src/builder/platform/platform.ts",
    "content": "import { Injectable } from 'static-injector';\nimport { TemplateTransformBase } from './template-transform-strategy/transform.base';\nimport { PlatformFileExtname } from './type';\n\nexport enum PlatformType {\n  wx = 'wx',\n  zj = 'zj',\n  jd = 'jd',\n  bdzn = 'bdzn',\n  zfb = 'zfb',\n  qq = 'qq',\n  dd = 'dd',\n  /** 这个属性只会在内部被使用 */\n  library = 'library',\n}\n@Injectable()\nexport class BuildPlatform {\n  packageName!: string;\n  globalObject!: string;\n  globalVariablePrefix!: string;\n  fileExtname!: PlatformFileExtname;\n  importTemplate!: string;\n  constructor(public templateTransform: TemplateTransformBase) {\n    this.templateTransform.init();\n  }\n}\n"
  },
  {
    "path": "src/builder/platform/qq/qq-platform.ts",
    "content": "import * as fs from 'fs-extra';\nimport * as path from 'path';\nimport { Injectable } from 'static-injector';\nimport { BuildPlatform } from '../platform';\nimport { QqTransform } from './qq.transform';\n\n@Injectable()\nexport class QqBuildPlatform extends BuildPlatform {\n  packageName = 'qq';\n  globalObject = 'qq';\n  globalVariablePrefix = 'qq.__window';\n  fileExtname = {\n    style: '.qss',\n    logic: '.js',\n    content: '.qml',\n    contentTemplate: '.qml',\n  };\n  importTemplate = `${fs\n    .readFileSync(path.resolve(__dirname, '../template/app-template.js'))\n    .toString()};\n    qq.__global = qq.__window = obj;`;\n  constructor(public templateTransform: QqTransform) {\n    super(templateTransform);\n  }\n}\n"
  },
  {
    "path": "src/builder/platform/qq/qq.transform.ts",
    "content": "import { Injectable } from 'static-injector';\nimport { WxTransformLike } from '../template-transform-strategy/wx-like/wx-transform.base';\n\n@Injectable()\nexport class QqTransform extends WxTransformLike {\n  directivePrefix = 'qq';\n}\n"
  },
  {
    "path": "src/builder/platform/template/app-template.js",
    "content": "const obj = {\n  Zone: typeof Zone !== 'undefined' && Zone,\n  setTimeout: typeof setTimeout !== 'undefined' && setTimeout,\n  clearTimeout:\n    typeof clearTimeout !== 'undefined' &&\n    function (id) {\n      return clearTimeout(id);\n    },\n  setInterval: typeof setInterval !== 'undefined' && setInterval,\n  clearInterval:\n    typeof clearInterval !== 'undefined' &&\n    function (id) {\n      return clearInterval(id);\n    },\n  Promise: typeof Promise !== 'undefined' && Promise,\n  Reflect: typeof Reflect !== 'undefined' && Reflect,\n  requestAnimationFrame:\n    typeof requestAnimationFrame !== 'undefined' && requestAnimationFrame,\n  cancelAnimationFrame:\n    typeof cancelAnimationFrame !== 'undefined' &&\n    function (id) {\n      return cancelAnimationFrame(id);\n    },\n  performance: typeof performance !== 'undefined' && performance,\n  navigator: typeof navigator !== 'undefined' && navigator,\n  // 来自 queue-microtask 因为引入太麻烦直接复制了\n  queueMicrotask:typeof queueMicrotask === 'function'\n  ? queueMicrotask.bind(typeof window !== 'undefined' ? window : global)\n  // reuse resolved promise, and allocate it lazily\n  : cb => (promise || (promise = Promise.resolve()))\n    .then(cb)\n    .catch(err => setTimeout(() => { throw err }, 0))\n};\n"
  },
  {
    "path": "src/builder/platform/template-transform-strategy/transform.base.ts",
    "content": "/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { Injectable } from 'static-injector';\nimport type { NgNodeMeta } from '../../mini-program-compiler';\nimport { MetaCollection, UseComponent } from '../../mini-program-compiler';\n\n@Injectable()\nexport abstract class TemplateTransformBase {\n  abstract init(): any;\n  abstract compile(nodes: NgNodeMeta[]): {\n    content: string;\n    useComponentPath: {\n      localPath: UseComponent[];\n      libraryPath: UseComponent[];\n    };\n    otherMetaGroup: Record<string, MetaCollection>;\n  };\n  abstract getData(): any;\n\n  abstract templateInterpolation: [string, string];\n  abstract eventListConvert: (list: string[]) => string;\n}\n"
  },
  {
    "path": "src/builder/platform/template-transform-strategy/wx-like/wx-container.ts",
    "content": "import type {\n  NgBoundTextMeta,\n  NgContentMeta,\n  NgElementMeta,\n  NgNodeMeta,\n  NgTemplateMeta,\n  NgTextMeta,\n} from '../../../mini-program-compiler';\nimport { MetaCollection } from '../../../mini-program-compiler';\nimport {\n  isNgBoundTextMeta,\n  isNgContentMeta,\n  isNgElementMeta,\n  isNgTemplateMeta,\n  isNgTextMeta,\n} from '../../util/type-predicate';\n\nexport interface WxContainerGlobalConfig {\n  seq: string;\n  directivePrefix: string;\n  eventListConvert: (name: string[]) => string;\n  templateInterpolation: [string, string];\n}\nexport class WxContainer {\n  private templateStr: string = '';\n  private childContainerList: WxContainer[] = [];\n  fromTemplate!: string;\n  defineTemplateName!: string;\n  private metaCollection: MetaCollection = new MetaCollection();\n  constructor(private parent?: WxContainer) {}\n\n  private _compileTemplate(node: NgNodeMeta): string {\n    if (isNgElementMeta(node)) {\n      return this.ngElementTransform(node);\n    } else if (isNgBoundTextMeta(node)) {\n      return this.ngBoundTextTransform(node);\n    } else if (isNgTextMeta(node)) {\n      return this.ngTextTransform(node);\n    } else if (isNgContentMeta(node)) {\n      return this.ngContentTransform(node);\n    } else if (isNgTemplateMeta(node)) {\n      return this.ngTemplateTransform(node);\n    } else {\n      throw new Error('未知的ng节点元数据');\n    }\n  }\n\n  compileNode(node: NgNodeMeta) {\n    this.templateStr += this._compileTemplate(node);\n  }\n\n  private ngElementTransform(node: NgElementMeta): string {\n    if (node.componentMeta) {\n      if (node.componentMeta.exportPath) {\n        this.metaCollection.libraryPath.add({\n          selector: node.componentMeta.selector,\n          path: node.componentMeta.exportPath,\n          className: node.componentMeta.className,\n        });\n      } else {\n        this.metaCollection.localPath.add({\n          path: node.componentMeta.filePath,\n          selector: node.componentMeta.selector,\n          className: node.componentMeta.className,\n        });\n      }\n    }\n\n    const children = node.children.map((child) => this._compileTemplate(child));\n    const commonTagProperty = `${this.setComponentIdentification(\n      node.componentMeta?.isComponent,\n      node.index\n    )} ${this.elementPropertyAndEvent(node, node.index).join(' ')}`;\n    if (node.singleClosedTag) {\n      return `<${node.tagName} ${commonTagProperty}/>`;\n    }\n    return `<${node.tagName} ${\n      node.tagName === 'block' ? '' : commonTagProperty\n    }>${children.join('')}</${node.tagName}>`;\n  }\n  private ngBoundTextTransform(node: NgBoundTextMeta): string {\n    return `{{nodeList[${node.index}].value}}`;\n  }\n  private ngContentTransform(node: NgContentMeta): string {\n    return node.name ? `<slot name=\"${node.name}\"></slot>` : `<slot></slot>`;\n  }\n  private ngTemplateTransform(node: NgTemplateMeta): string {\n    let content = '';\n    const defineTemplateName = node.defineTemplateName;\n    const childContainer = new WxContainer(this);\n    const globalTemplate = this.isGlobalTemplate(node.defineTemplateName);\n    if (globalTemplate) {\n      if (this.fromTemplate && this.fromTemplate !== globalTemplate) {\n        throw new Error(\n          `全局ng-template中不可包含其他位置的ng-template,当前为${this.fromTemplate},包含${globalTemplate}`\n        );\n      } else if (globalTemplate) {\n        childContainer.fromTemplate = globalTemplate;\n        childContainer.defineTemplateName = defineTemplateName;\n      }\n    } else {\n      childContainer.fromTemplate = this.fromTemplate;\n      childContainer.defineTemplateName = defineTemplateName;\n    }\n    this.childContainerList.push(childContainer);\n    node.children.forEach((childNode) => {\n      childContainer.compileNode(childNode);\n    });\n    if (this.fromTemplate === childContainer.fromTemplate) {\n      this.metaCollection.templateList.push({\n        name: defineTemplateName,\n        content: `<template name=\"${defineTemplateName}\">${childContainer.templateStr}</template>`,\n      });\n    }\n\n    content += `<block ${WxContainer.globalConfig.directivePrefix}${\n      WxContainer.globalConfig.seq\n    }for=\"{{nodeList[${node.index}]}}\" ${\n      WxContainer.globalConfig.directivePrefix\n    }${WxContainer.globalConfig.seq}key=\"index\">\n      <template is=\"{{item.__templateName||'${defineTemplateName}'}}\" ${this.getTemplateDataStr(\n      node.index,\n      `index`\n    )}></template>\n      </block>`;\n\n    return content;\n  }\n  private ngTextTransform(node: NgTextMeta): string {\n    return `${node.value}`;\n  }\n\n  private getTemplateDataStr(directiveIndex: number, indexName: string) {\n    return `data=\"${WxContainer.globalConfig.templateInterpolation[0]}...nodeList[${directiveIndex}][${indexName}] ${WxContainer.globalConfig.templateInterpolation[1]}\"`;\n  }\n\n  export(): { wxmlTemplate: string } {\n    return {\n      wxmlTemplate: this.templateStr,\n    };\n  }\n\n  private setComponentIdentification(\n    isComponent: boolean | undefined,\n    nodeIndex: number | undefined\n  ) {\n    if (isComponent) {\n      return `nodePath=\"{{nodePath}}\" nodeIndex=\"${nodeIndex}\"`;\n    }\n    return ``;\n  }\n\n  private elementPropertyAndEvent(node: NgElementMeta, index: number) {\n    const propertyMap = new Map<string, string>();\n    const attributeMap = new Map<string, string>();\n    propertyMap.set('class', `nodeList[${index}].class`);\n    propertyMap.set('style', `nodeList[${index}].style`);\n    Object.entries(node.attributes)\n      .filter(([key, value]) => value !== '')\n      .forEach(([key, value]) => {\n        attributeMap.set(key, value);\n      });\n    node.inputs\n      .filter(\n        (property) =>\n          !(\n            (node.componentMeta?.inputs?.includes(property) ||\n              node.directiveMeta?.inputs?.includes(property)) &&\n            !(\n              node.directiveMeta?.properties?.includes(property) ||\n              node.componentMeta?.properties?.includes(property)\n            )\n          )\n      )\n      .filter((key) => !/^(class\\.?|style\\.?)/.test(key))\n      .forEach((key) => {\n        propertyMap.set(key, `nodeList[${index!}].property.${key}`);\n      });\n    [\n      ...(node.directiveMeta?.properties || []),\n      ...(node.componentMeta?.properties || []),\n    ]\n      .filter((key) => !/^(class\\.?|style\\.?)/.test(key))\n      .forEach((key) => {\n        propertyMap.set(key, `nodeList[${index!}].property.${key}`);\n      });\n    const eventList: string[] = [\n      ...node.outputs.filter(\n        (item) =>\n          !(\n            node.componentMeta?.outputs.some((output) => output === item) ||\n            node.directiveMeta?.outputs.some((output) => output === item)\n          )\n      ),\n      ...(node.directiveMeta?.listeners || []),\n      ...(node.componentMeta?.isComponent ? node.componentMeta.listeners : []),\n    ];\n\n    const result = WxContainer.globalConfig.eventListConvert(eventList);\n    if (result) {\n      propertyMap.set(`data-node-path`, `nodePath`);\n      propertyMap.set(`data-node-index`, `${index}`);\n    }\n    return [\n      ...Array.from(attributeMap.entries()).map(\n        ([key, value]) => `${key}=\"${value}\"`\n      ),\n      ...Array.from(propertyMap.entries()).map(\n        ([key, value]) => `${key}=\"{{${value}}}\"`\n      ),\n      result,\n    ];\n  }\n  static globalConfig: WxContainerGlobalConfig;\n  static initWxContainerFactory(globalConfig: WxContainerGlobalConfig) {\n    this.globalConfig = globalConfig;\n  }\n  private isGlobalTemplate(name: string) {\n    const result = name.match(/^\\$\\$mp\\$\\$([^$]+)\\$\\$(.*)/);\n    if (!result) {\n      return undefined;\n    }\n    return result[1];\n  }\n  exportMetaCollectionGroup() {\n    const obj: Record<string, MetaCollection> = {};\n    if (!this.fromTemplate) {\n      obj.$inline = obj.$inline || new MetaCollection();\n      obj.$inline.merge(this.metaCollection);\n    } else if (this.fromTemplate == '__self__') {\n      obj.$self = obj.$self || new MetaCollection();\n      obj.$self.merge(this.metaCollection);\n      obj.$self.templateList.push({\n        name: this.defineTemplateName,\n        content: `<template name=\"${this.defineTemplateName}\">${this.templateStr}</template>`,\n      });\n    } else {\n      obj[this.fromTemplate] = obj[this.fromTemplate] || new MetaCollection();\n      obj[this.fromTemplate].merge(this.metaCollection);\n      obj[this.fromTemplate].templateList.push({\n        name: this.defineTemplateName,\n        content: `<template name=\"${this.defineTemplateName}\">${this.templateStr}</template>`,\n      });\n    }\n    this.childContainerList.forEach((container) => {\n      const result = container.exportMetaCollectionGroup();\n      for (const key in result) {\n        if (Object.prototype.hasOwnProperty.call(result, key)) {\n          const element = result[key];\n          obj[key] = obj[key] || new MetaCollection();\n          obj[key].merge(element);\n        }\n      }\n    });\n    return obj;\n  }\n}\n"
  },
  {
    "path": "src/builder/platform/template-transform-strategy/wx-like/wx-transform.base.ts",
    "content": "import { strings } from '@angular-devkit/core';\nimport type { NgNodeMeta } from '../../../mini-program-compiler';\nimport { TemplateTransformBase } from '../transform.base';\nimport { WxContainer } from './wx-container';\n\nexport const EVENT_PREFIX_REGEXP =\n  /^(bind|catch|mut-bind|capture-bind|capture-catch)(.*)$/;\nexport abstract class WxTransformLike extends TemplateTransformBase {\n  seq = ':';\n  templateInterpolation: [string, string] = ['{{', '}}'];\n  abstract directivePrefix: string;\n\n  constructor() {\n    super();\n  }\n  init() {\n    WxContainer.initWxContainerFactory({\n      seq: this.seq,\n      directivePrefix: this.directivePrefix,\n      eventListConvert: this.eventListConvert,\n      templateInterpolation: this.templateInterpolation,\n    });\n  }\n  compile(nodes: NgNodeMeta[]) {\n    const container = new WxContainer();\n\n    nodes.forEach((node) => {\n      container.compileNode(node);\n    });\n    const result = container.export();\n    const metaCollectionGroup = container.exportMetaCollectionGroup();\n    const inlineMetaCollection = metaCollectionGroup.$inline;\n    delete metaCollectionGroup.$inline;\n    return {\n      content: `${inlineMetaCollection.templateList\n        .map((item) => item.content)\n        .join('')}<block ${this.directivePrefix}${this.seq}if=\"{{hasLoad}}\">${\n        result.wxmlTemplate\n      }</block>`,\n      useComponentPath: {\n        localPath: [...inlineMetaCollection.localPath],\n        libraryPath: [...inlineMetaCollection.libraryPath],\n      },\n      otherMetaGroup: metaCollectionGroup,\n    };\n  }\n\n  getData() {\n    return { directivePrefix: this.directivePrefix };\n  }\n  eventNameConvert(tagEventMeta: string) {\n    const result = tagEventMeta.match(EVENT_PREFIX_REGEXP);\n    let prefix: string = 'bind';\n    let type: string = tagEventMeta;\n    if (result) {\n      prefix = result[1];\n      type = result[2];\n    }\n    return {\n      prefix,\n      type,\n      name: `${prefix}:${type}`,\n    };\n  }\n  eventListConvert = (list: string[]) => {\n    const eventMap = new Map();\n    list.forEach((eventName) => {\n      const result = this.eventNameConvert(eventName);\n      const prefix = strings.camelize(result.prefix);\n      const bindEventName = `${prefix}Event`;\n      if (eventMap.has(result.name)) {\n        if (eventMap.get(result.name) === bindEventName) {\n          return;\n        } else {\n          throw new Error(\n            `事件名[${result.name}]解析异常,原绑定${eventMap.get(\n              result.name\n            )},现绑定${bindEventName}`\n          );\n        }\n      }\n      eventMap.set(result.name, bindEventName);\n    });\n\n    return Array.from(eventMap.entries())\n      .map(([key, value]) => `${key}=\"${value}\"`)\n      .join(' ');\n  };\n}\n"
  },
  {
    "path": "src/builder/platform/type.ts",
    "content": "export interface PlatformFileExtname {\n  style: string;\n  logic: string;\n  content: string;\n  contentTemplate: string;\n  config?: string;\n}\n"
  },
  {
    "path": "src/builder/platform/util/dataset-bind.ts",
    "content": "/* eslint-disable @typescript-eslint/no-explicit-any */\nexport class DatasetBind {\n  constructor(private data: any) {}\n  toJSON() {\n    return this.objectToJSON(this.data);\n  }\n  private objectToJSON(obj: Record<string, unknown>) {\n    let str = '{';\n\n    for (const key in obj) {\n      if (Object.prototype.hasOwnProperty.call(obj, key)) {\n        const element = obj[key];\n        str += `${key}:`;\n        if (typeof element === 'string') {\n          str += `${this.stringToJSON(element)}`;\n        } else if (typeof element === 'number') {\n          str += `${this.numberToJSON(element)}`;\n        } else if (element instanceof Array) {\n          str += `${this.arrayToJSON(element)}`;\n        } else if (typeof element === 'object' && element !== null) {\n          str += `${this.objectToJSON(element as any)}`;\n        }\n        str += ',';\n      }\n    }\n    str = str.substr(0, str.length - 1);\n    str += '}';\n    return str;\n  }\n  private numberToJSON(number: number) {\n    return `${number}`;\n  }\n  private stringToJSON(string: string) {\n    return `'${string}'`;\n  }\n  private arrayToJSON(list: any[]) {\n    let str = '[';\n    for (let i = 0; i < list.length; i++) {\n      const element = list[i];\n      if (typeof element === 'string') {\n        str += this.stringToJSON(element);\n      } else if (typeof element === 'number') {\n        str += this.numberToJSON(element);\n      } else if (element instanceof Array) {\n        str += this.arrayToJSON(element);\n      } else if (typeof element === 'object' && element !== null) {\n        str += this.objectToJSON(element as any);\n      }\n      if (i !== list.length - 1) {\n        str += ',';\n      }\n    }\n    str += ']';\n    return str;\n  }\n}\n"
  },
  {
    "path": "src/builder/platform/util/type-predicate.ts",
    "content": "import {\n  NgBoundTextMeta,\n  NgContentMeta,\n  NgElementMeta,\n  NgNodeKind,\n  NgNodeMeta,\n  NgTemplateMeta,\n  NgTextMeta,\n} from '../../mini-program-compiler';\n\nexport function isNgElementMeta(node: NgNodeMeta): node is NgElementMeta {\n  return node.kind === NgNodeKind.Element;\n}\nexport function isNgBoundTextMeta(node: NgNodeMeta): node is NgBoundTextMeta {\n  return node.kind === NgNodeKind.BoundText;\n}\nexport function isNgContentMeta(node: NgNodeMeta): node is NgContentMeta {\n  return node.kind === NgNodeKind.Content;\n}\nexport function isNgTemplateMeta(node: NgNodeMeta): node is NgTemplateMeta {\n  return node.kind === NgNodeKind.Template;\n}\nexport function isNgTextMeta(node: NgNodeMeta): node is NgTextMeta {\n  return node.kind === NgNodeKind.Text;\n}\n"
  },
  {
    "path": "src/builder/platform/wx/wx-platform.ts",
    "content": "import * as fs from 'fs-extra';\nimport * as path from 'path';\nimport { Injectable } from 'static-injector';\nimport { BuildPlatform } from '../platform';\nimport { WxTransform } from './wx.transform';\n\n@Injectable()\nexport class WxBuildPlatform extends BuildPlatform {\n  packageName = 'wx';\n  globalObject = 'wx';\n  globalVariablePrefix = 'wx.__window';\n  fileExtname = {\n    style: '.wxss',\n    logic: '.js',\n    content: '.wxml',\n    contentTemplate: '.wxml',\n  };\n  importTemplate = `${fs\n    .readFileSync(path.resolve(__dirname, '../template/app-template.js'))\n    .toString()};\n    wx.__global = wx.__window = obj;`;\n  constructor(public templateTransform: WxTransform) {\n    super(templateTransform);\n  }\n}\n"
  },
  {
    "path": "src/builder/platform/wx/wx.transform.ts",
    "content": "import { Injectable } from 'static-injector';\nimport { WxTransformLike } from '../template-transform-strategy/wx-like/wx-transform.base';\n\n@Injectable()\nexport class WxTransform extends WxTransformLike {\n  directivePrefix = 'wx';\n}\n"
  },
  {
    "path": "src/builder/platform/zfb/zfb-platform.ts",
    "content": "import * as fs from 'fs-extra';\nimport * as path from 'path';\nimport { Injectable } from 'static-injector';\nimport { BuildPlatform } from '../platform';\nimport { ZfbTransform } from './zfb.transform';\n\n@Injectable()\nexport class ZfbBuildPlatform extends BuildPlatform {\n  packageName = 'zfb';\n  globalObject = 'my';\n  globalVariablePrefix = 'my.__window';\n  fileExtname = {\n    style: '.acss',\n    logic: '.js',\n    content: '.axml',\n    contentTemplate: '.axml',\n  };\n  importTemplate = `${fs\n    .readFileSync(path.resolve(__dirname, '../template/app-template.js'))\n    .toString()};\n    my.__global = my.__window = obj;`;\n  constructor(public templateTransform: ZfbTransform) {\n    super(templateTransform);\n  }\n}\n"
  },
  {
    "path": "src/builder/platform/zfb/zfb.transform.ts",
    "content": "import { capitalize } from '@angular-devkit/core/src/utils/strings';\nimport { Injectable } from 'static-injector';\nimport { WxTransformLike } from '../template-transform-strategy/wx-like/wx-transform.base';\n\nconst BIND_PREFIX_REGEXP = /^(bind|mut-bind|capture-bind)(.*)/;\nconst CATCH_PREFIX_REGEXP = /^(catch|capture-catch)(.*)/;\n@Injectable()\nexport class ZfbTransform extends WxTransformLike {\n  directivePrefix = 'a';\n  override eventNameConvert(name: string) {\n    let result = name.match(BIND_PREFIX_REGEXP);\n    if (result) {\n      return {\n        prefix: 'on',\n        type: result[2],\n        name: `on${capitalize(result[2])}`,\n      };\n    }\n    result = name.match(CATCH_PREFIX_REGEXP);\n    if (result) {\n      return {\n        prefix: 'catch',\n        type: result[2],\n        name: `catch${capitalize(result[2])}`,\n      };\n    }\n    return {\n      prefix: 'on',\n      type: name,\n      name: `on${capitalize(name)}`,\n    };\n  }\n}\n"
  },
  {
    "path": "src/builder/platform/zjtd/zj-platform.ts",
    "content": "import * as fs from 'fs-extra';\nimport * as path from 'path';\nimport { Injectable } from 'static-injector';\nimport { BuildPlatform } from '../platform';\nimport { ZjTransform } from './zj.transform';\n/** 字节小程序适配 */\n@Injectable()\nexport class ZjBuildPlatform extends BuildPlatform {\n  packageName = 'zjtd';\n  globalObject = 'tt';\n  globalVariablePrefix = 'tt.__window';\n  fileExtname = {\n    style: '.ttss',\n    logic: '.js',\n    content: '.ttml',\n    contentTemplate: '.ttml',\n    config: '.json',\n  };\n  importTemplate = `${fs\n    .readFileSync(path.resolve(__dirname, '../template/app-template.js'))\n    .toString()};\n    tt.__global = tt.__window = obj;`;\n  constructor(public templateTransform: ZjTransform) {\n    super(templateTransform);\n  }\n}\n"
  },
  {
    "path": "src/builder/platform/zjtd/zj.transform.ts",
    "content": "import { Injectable } from 'static-injector';\nimport { WxTransformLike } from '../template-transform-strategy/wx-like/wx-transform.base';\n\n@Injectable()\nexport class ZjTransform extends WxTransformLike {\n  directivePrefix = 'tt';\n}\n"
  },
  {
    "path": "src/builder/test/fixture/watch/sub3/sub3.component.html",
    "content": "<div>测试</div>\n"
  },
  {
    "path": "src/builder/test/fixture/watch/sub3/sub3.component.ts",
    "content": "import { Component, OnInit } from '@angular/core';\n\n@Component({\n  selector: 'app-sub3',\n  templateUrl: './sub3.component.html',\n})\nexport class Sub3Component implements OnInit {\n  constructor() {}\n\n  ngOnInit() {}\n}\n"
  },
  {
    "path": "src/builder/test/fixture/watch/sub3/sub3.entry.ts",
    "content": "import { pageStartup } from 'angular-miniprogram';\nimport { Sub3Component } from './sub3.component';\nimport { Sub3Module } from './sub3.module';\n\npageStartup(Sub3Module, Sub3Component);\n"
  },
  {
    "path": "src/builder/test/fixture/watch/sub3/sub3.module.ts",
    "content": "import { NgModule } from '@angular/core';\nimport { CommonModule } from 'angular-miniprogram/common';\nimport { Sub3Component } from './sub3.component';\n\n@NgModule({\n  imports: [CommonModule],\n  declarations: [Sub3Component],\n})\nexport class Sub3Module {}\n"
  },
  {
    "path": "src/builder/token/component.token.ts",
    "content": "import { InjectionToken } from 'static-injector';\n\nexport const COMPONENT_META = new InjectionToken('COMPONENT_META');\n"
  },
  {
    "path": "src/builder/util/index.ts",
    "content": "export * from './library-template-scope-name';\nexport * from './literal-resolve';\nexport * from './load_esm';\nexport * from './raw-updater';\nexport * from './run-script';\n"
  },
  {
    "path": "src/builder/util/library-template-scope-name.ts",
    "content": "import { strings } from '@angular-devkit/core';\n\nexport function libraryTemplateScopeName(library: string) {\n  return strings.classify(library.replace(/[@/]/g, ''));\n}\n"
  },
  {
    "path": "src/builder/util/literal-resolve.ts",
    "content": "/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { runScript } from './run-script';\n\nexport function literalResolve<T extends Record<string, any>>(\n  content: string,\n  options?: T\n) {\n  return runScript(`(()=>{return ${content}})()`, options);\n}\n"
  },
  {
    "path": "src/builder/util/load_esm.ts",
    "content": "async function loadEsmModule<T>(modulePath: string): Promise<T> {\n  const namespaceObject = await new Function(\n    'modulePath',\n    `return import(modulePath);`\n  )(modulePath);\n\n  // If it is not ESM then the values needed will be stored in the `default` property.\n  // TODO_ESM: This can be removed once `@angular/*` packages are ESM only.\n  if (namespaceObject.default) {\n    return namespaceObject.default;\n  } else {\n    return namespaceObject;\n  }\n}\n\nexport const angularCompilerPromise =\n  loadEsmModule<typeof import('@angular/compiler')>('@angular/compiler');\nexport const angularCompilerCliPromise = loadEsmModule<\n  typeof import('@angular/compiler-cli')\n>('@angular/compiler-cli');\n"
  },
  {
    "path": "src/builder/util/raw-updater.spec.ts",
    "content": "import { DeleteChange, InsertChange, ReplaceChange } from 'cyia-code-util';\nimport { RawUpdater } from './raw-updater';\n\nconst originContent = '123456789';\ndescribe('raw-updater', () => {\n  it('default', () => {\n    const result = RawUpdater.update(originContent, []);\n    expect(result).toBe(originContent);\n  });\n  it('insert', () => {\n    const result = RawUpdater.update(originContent, [\n      new InsertChange(0, '000'),\n      new InsertChange(5, '000'),\n      new InsertChange(8, '000'),\n    ]);\n    expect(result).toBe(`000123450006780009`);\n  });\n  it('delete', () => {\n    const result = RawUpdater.update(originContent, [\n      new DeleteChange(0, 1),\n      new DeleteChange(5, 1),\n      new DeleteChange(8, 1),\n    ]);\n    expect(result).toBe(`234578`);\n  });\n  it('replace', () => {\n    const result = RawUpdater.update(originContent, [\n      new ReplaceChange(0, 1, '000'),\n      new ReplaceChange(5, 1, '000'),\n      new ReplaceChange(8, 1, '000'),\n    ]);\n    expect(result).toBe(`000234500078000`);\n  });\n  it('混合', () => {\n    const result = RawUpdater.update(originContent, [\n      new InsertChange(0, '000'),\n      new DeleteChange(5, 1),\n      new ReplaceChange(8, 1, '000'),\n    ]);\n    expect(result).toBe(`0001234578000`);\n  });\n});\n"
  },
  {
    "path": "src/builder/util/raw-updater.ts",
    "content": "import {\n  Change,\n  DeleteChange,\n  InsertChange,\n  ReplaceChange,\n} from 'cyia-code-util';\n\nexport class RawUpdater {\n  static update(content: string, change: Change[]) {\n    change = change.sort((a, b) => b.start - a.start);\n    return new RawUpdater(content, change).update();\n  }\n  originContent!: string;\n  constructor(private content: string, private changes: Change[]) {\n    this.originContent = content;\n  }\n  update() {\n    this.changes.forEach((change) => {\n      let deleteChange: DeleteChange | undefined;\n      let insertChange: InsertChange | undefined;\n      if (change instanceof ReplaceChange) {\n        insertChange = new InsertChange(change.start, change.content);\n        deleteChange = new DeleteChange(change.start, change.length);\n      } else if (change instanceof InsertChange) {\n        insertChange = change;\n      } else if (change instanceof DeleteChange) {\n        deleteChange = change;\n      }\n      let list!: [string, string];\n      if (deleteChange) {\n        list = this.slice(deleteChange.start, deleteChange.length);\n      }\n      if (!list && insertChange) {\n        list = this.slice(insertChange.start);\n        list.splice(1, 0, insertChange.content);\n      } else if (insertChange) {\n        list.splice(1, 0, insertChange.content);\n      }\n      this.content = list.join('');\n    });\n    return this.content;\n  }\n  private slice(pos: number, length: number = 0): [string, string] {\n    return [\n      this.content.substring(0, pos),\n      this.content.substring(pos + length),\n    ];\n  }\n}\n"
  },
  {
    "path": "src/builder/util/run-script.ts",
    "content": "/* eslint-disable no-console */\nimport vm from 'vm';\n\nexport function runScript(code: string, context?: vm.Context) {\n  try {\n    return vm.runInNewContext(code, context);\n  } catch (error) {\n    console.error('运行脚本错误');\n  }\n}\n"
  },
  {
    "path": "src/library/common/.gitignore",
    "content": "*\n!.gitignore\n!ng-package.json\n!/http\n!/http/ng-package.json"
  },
  {
    "path": "src/library/common/ng-package.json",
    "content": "{\n  \"$schema\": \"../../../node_modules/ng-packagr/ng-package.schema.json\",\n  \"lib\": {\n    \"entryFile\": \"./index.ts\"\n  }\n}\n"
  },
  {
    "path": "src/library/declaration/index.d.ts",
    "content": "declare const ngDevMode: null | any;\ndeclare const Zone: any\n"
  },
  {
    "path": "src/library/forms/.gitignore",
    "content": "*\n!.gitignore\n!/src\n!/src/directives\n!/src/directives/default_value_accessor.ts\n!/src/directives/checkbox_value_accessor.ts\n!/src/directives/radio_control_value_accessor.ts\n!/src/directives.ts\n!/readme.md\n!/src/directives/picker_view_value_accessor.ts\n!/src/directives/switch_value_accessor.ts\n!/src/directives/slider_value_accessor.ts\n!/src/directives/picker_value_accessor.ts\n!/src/forms.ts\n!/ng-package.json\n"
  },
  {
    "path": "src/library/forms/ng-package.json",
    "content": "{\n  \"$schema\": \"../../../node_modules/ng-packagr/ng-package.schema.json\",\n  \"lib\": {\n    \"entryFile\": \"./index.ts\"\n  }\n}\n"
  },
  {
    "path": "src/library/forms/readme.md",
    "content": "# 表单逻辑\n\n| 组件名         | 输入属性                                                                                                                                              | 事件                                       | 禁用       | 备注                                                                    |\n| -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------ | ---------- | ----------------------------------------------------------------------- |\n| input          | value`string`                                                                                                                                         | bindinput<br>bindfocus<br>bindblur         | disabled   | 事件比较多,可以对比参考<br>,text,number,idcard,digit,safe-password 类型 |\n| textarea       | value`string`                                                                                                                                         | bindfocus<br>bindblur<br>bindinput         | disabled   |\n| checkbox       | `checked` boolean                                                                                                                                     | 触发`checkbox-group`的 `change` 自身无事件 | `disabled` | `value`在触发时携带                                                     |\n| checkbox-group |                                                                                                                                                       |                                            |            | 只用于`checkbox`                                                        |\n| editor         |                                                                                                                                                       |                                            |            | 貌似不支持双向绑定                                                      |\n| picker         | mode 对应, <br>selector:value`number`,<br>multiSelector:value`[]`,<br>time:value`string hh:mm`,<br>data:value`string YYYY-MM-DD`,<br>region:value`[]` | bindchange                                 | disabled   |\n| picker-view    | value`number[]`组                                                                                                                                     | bindchange                                 | 无禁用     |\n| radio          | checked                                                                                                                                               | 自身无事件                                 | disabled   | 需要配合                                                                |\n| radio-group    |                                                                                                                                                       | bindchange                                 |            |\n| slider         | value`number`                                                                                                                                         | bindchange                                 | disabled   |\n| switch         | checked`boolean`                                                                                                                                      | bindchange                                 | disabled   |\n\n# 开发状态\n\n- input 已实现\n- switch 已实现\n- slider 已实现\n- radio 已实现\n- checkbox 已实现\n- picker 已实现\n\n# 待实现\n\n- 双向绑定后,变更检测触发有点问题\n\n# 修改文件\n\n- 双向绑定部分,修改和添加了部分组件的双向绑定支持以适应小程序.\n- forms/directives 改了导出导入声明,用来添加修改移除双向绑定\n\n# 不同平台\n\n- 如果出现不同平台,并且不同平台有不同的模块绑定逻辑,那么这里将不做适配,转为第三方适配\n"
  },
  {
    "path": "src/library/forms/src/directives/checkbox_value_accessor.ts",
    "content": "/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {\n  ContentChildren,\n  Directive,\n  ElementRef,\n  HostBinding,\n  Input,\n  QueryList,\n  Renderer2,\n  forwardRef,\n} from '@angular/core';\n\nimport {\n  BuiltInControlValueAccessor,\n  ControlValueAccessor,\n  NG_VALUE_ACCESSOR,\n} from './control_value_accessor';\n\nexport const CHECKBOX_VALUE_ACCESSOR: any = {\n  provide: NG_VALUE_ACCESSOR,\n  useExisting: forwardRef(() => CheckBoxGroupValueAccessor),\n  multi: true,\n};\n\n@Directive({\n  selector:\n    'checkbox-group[formControlName],checkbox-group[formControl],checkbox-group[ngModel]',\n  host: {\n    '(bindchange)': 'valueChange($event.detail.value)',\n  },\n  providers: [CHECKBOX_VALUE_ACCESSOR],\n})\nexport class CheckBoxGroupValueAccessor\n  extends BuiltInControlValueAccessor\n  implements ControlValueAccessor\n{\n  @ContentChildren(forwardRef(() => CheckboxControl), { descendants: true })\n  children!: QueryList<CheckboxControl>;\n  valueChange(list: string[]) {\n    if (this.children) {\n      this.children.forEach((item) => {\n        item.updateChecked(list.some((value) => value === item.value));\n      });\n    }\n    this.onChange(list);\n  }\n  writeValue(list: string[]) {\n    if (this.children) {\n      this.children.forEach((item) => {\n        item.updateChecked(list.some((value) => value === item.value));\n      });\n    }\n  }\n}\n/**\n * @description\n * A `ControlValueAccessor` for writing a value and listening to changes on a checkbox input\n * element.\n *\n * @usageNotes\n *\n * ### Using a checkbox with a reactive form.\n *\n * The following example shows how to use a checkbox with a reactive form.\n *\n * ```ts\n * const rememberLoginControl = new FormControl();\n * ```\n *\n * ```\n * <input type=\"checkbox\" [formControl]=\"rememberLoginControl\">\n * ```\n *\n * @ngModule ReactiveFormsModule\n * @ngModule FormsModule\n * @publicApi\n */\n@Directive({\n  selector: 'checkbox',\n  host: {},\n})\nexport class CheckboxControl {\n  /**\n   * @description\n   * Tracks the value of the radio input element\n   */\n  @HostBinding('value') @Input() readonly value!: string | undefined;\n  @HostBinding('checked')\n  checked: boolean | undefined;\n  constructor(private elementRef: ElementRef, private renderer: Renderer2) {}\n  updateChecked(value: boolean) {\n    this.renderer.setProperty(this.elementRef.nativeElement, 'checked', value);\n  }\n}\n"
  },
  {
    "path": "src/library/forms/src/directives/default_value_accessor.ts",
    "content": "/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {\n  Directive,\n  ElementRef,\n  HostBinding,\n  Inject,\n  InjectionToken,\n  Optional,\n  Renderer2,\n  forwardRef,\n} from '@angular/core';\n\nimport {\n  BaseControlValueAccessor,\n  ControlValueAccessor,\n  NG_VALUE_ACCESSOR,\n} from './control_value_accessor';\n\nexport const DEFAULT_VALUE_ACCESSOR: any = {\n  provide: NG_VALUE_ACCESSOR,\n  useExisting: forwardRef(() => DefaultValueAccessor),\n  multi: true,\n};\n\n/**\n * @description\n * Provide this token to control if form directives buffer IME input until\n * the \"compositionend\" event occurs.\n * @publicApi\n */\nexport const COMPOSITION_BUFFER_MODE = new InjectionToken<boolean>(\n  'CompositionEventMode'\n);\n\n/**\n * The default `ControlValueAccessor` for writing a value and listening to changes on input\n * elements. The accessor is used by the `FormControlDirective`, `FormControlName`, and\n * `NgModel` directives.\n *\n * {@searchKeywords ngDefaultControl}\n *\n * @usageNotes\n *\n * ### Using the default value accessor\n *\n * The following example shows how to use an input element that activates the default value accessor\n * (in this case, a text field).\n *\n * ```ts\n * const firstNameControl = new FormControl();\n * ```\n *\n * ```\n * <input type=\"text\" [formControl]=\"firstNameControl\">\n * ```\n *\n * This value accessor is used by default for `<input type=\"text\">` and `<textarea>` elements, but\n * you could also use it for custom components that have similar behavior and do not require special\n * processing. In order to attach the default value accessor to a custom element, add the\n * `ngDefaultControl` attribute as shown below.\n *\n * ```\n * <custom-input-component ngDefaultControl [(ngModel)]=\"value\"></custom-input-component>\n * ```\n *\n * @ngModule ReactiveFormsModule\n * @ngModule FormsModule\n * @publicApi\n */\n@Directive({\n  selector:\n    'input[formControlName],textarea[formControlName],input[formControl],textarea[formControl],input[ngModel],textarea[ngModel],[ngDefaultControl]',\n  // TODO: vsavkin replace the above selector with the one below it once\n  // https://github.com/angular/angular/issues/3011 is implemented\n  // selector: '[ngModel],[formControl],[formControlName]',\n  host: {\n    '(bindinput)': 'valueChange($event.detail.value)',\n    '(bindblur)': 'onTouched()',\n  },\n  providers: [DEFAULT_VALUE_ACCESSOR],\n})\nexport class DefaultValueAccessor\n  extends BaseControlValueAccessor\n  implements ControlValueAccessor\n{\n  @HostBinding('value') value: string | undefined;\n  @HostBinding('disabled') disabled: boolean | undefined;\n  constructor(renderer: Renderer2, elementRef: ElementRef) {\n    super(renderer, elementRef);\n  }\n\n  /**\n   * Sets the \"value\" property on the input element.\n   * @nodoc\n   */\n  writeValue(value: string): void {\n    const normalizedValue = value == null ? undefined : value;\n    if (typeof normalizedValue !== 'undefined') {\n      this.setProperty('value', normalizedValue);\n    }\n  }\n  valueChange(value: string) {\n    this.onChange(value);\n  }\n}\n"
  },
  {
    "path": "src/library/forms/src/directives/picker_value_accessor.ts",
    "content": "/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {\n  Directive,\n  ElementRef,\n  HostBinding,\n  Renderer2,\n  forwardRef,\n} from '@angular/core';\n\nimport {\n  BuiltInControlValueAccessor,\n  ControlValueAccessor,\n  NG_VALUE_ACCESSOR,\n} from './control_value_accessor';\n\nexport const SWITCH_VALUE_ACCESSOR: any = {\n  provide: NG_VALUE_ACCESSOR,\n  useExisting: forwardRef(() => PickerValueAccessor),\n  multi: true,\n};\n\n/**\n * @description\n * The `ControlValueAccessor` for writing a number value and listening to number input changes.\n * The value accessor is used by the `FormControlDirective`, `FormControlName`, and `NgModel`\n * directives.\n *\n * @usageNotes\n *\n * ### Using a number input with a reactive form.\n *\n * The following example shows how to use a number input with a reactive form.\n *\n * ```ts\n * const totalCountControl = new FormControl();\n * ```\n *\n * ```\n * <input type=\"number\" [formControl]=\"totalCountControl\">\n * ```\n *\n * @ngModule ReactiveFormsModule\n * @ngModule FormsModule\n * @publicApi\n */\n@Directive({\n  selector: 'picker[formControlName],picker[formControl],picker[ngModel]',\n  host: { '(bindchange)': 'valueChange($event.detail.value)' },\n  providers: [SWITCH_VALUE_ACCESSOR],\n})\nexport class PickerValueAccessor\n  extends BuiltInControlValueAccessor\n  implements ControlValueAccessor\n{\n  @HostBinding('value') value: number | any[] | string | undefined;\n  @HostBinding('disabled') disabled: boolean | undefined;\n  /**\n   * Sets the \"value\" property on the input element.\n   * @nodoc\n   */\n  writeValue(value: number | any[] | string): void {\n    const normalizedValue = value == null ? undefined : value;\n    if (typeof normalizedValue !== 'undefined') {\n      this.setProperty('value', normalizedValue);\n    }\n  }\n  valueChange(value: any) {\n    this.setProperty('value', value);\n    this.onChange(value);\n  }\n}\n"
  },
  {
    "path": "src/library/forms/src/directives/picker_view_value_accessor.ts",
    "content": "/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {\n  Directive,\n  ElementRef,\n  HostBinding,\n  Renderer2,\n  forwardRef,\n} from '@angular/core';\n\nimport {\n  BuiltInControlValueAccessor,\n  ControlValueAccessor,\n  NG_VALUE_ACCESSOR,\n} from './control_value_accessor';\n\nexport const PICKER_VIEW_VALUE_ACCESSOR: any = {\n  provide: NG_VALUE_ACCESSOR,\n  useExisting: forwardRef(() => PickerViewValueAccessor),\n  multi: true,\n};\n\n/**\n * @description\n * The `ControlValueAccessor` for writing a number value and listening to number input changes.\n * The value accessor is used by the `FormControlDirective`, `FormControlName`, and `NgModel`\n * directives.\n *\n * @usageNotes\n *\n * ### Using a number input with a reactive form.\n *\n * The following example shows how to use a number input with a reactive form.\n *\n * ```ts\n * const totalCountControl = new FormControl();\n * ```\n *\n * ```\n * <input type=\"number\" [formControl]=\"totalCountControl\">\n * ```\n *\n * @ngModule ReactiveFormsModule\n * @ngModule FormsModule\n * @publicApi\n */\n@Directive({\n  selector:\n    'picker-view[formControlName],picker-view[formControl],picker-view[ngModel]',\n  host: { '(bindchange)': 'valueChange($event.detail.value)' },\n  providers: [PICKER_VIEW_VALUE_ACCESSOR],\n})\nexport class PickerViewValueAccessor\n  extends BuiltInControlValueAccessor\n  implements ControlValueAccessor\n{\n  @HostBinding('value') value: number[] | undefined;\n  /**\n   * Sets the \"value\" property on the input element.\n   * @nodoc\n   */\n  writeValue(value: number[]): void {\n    const normalizedValue = value == null ? undefined : value;\n    if (typeof normalizedValue !== 'undefined') {\n      this.setProperty('value', normalizedValue);\n    }\n  }\n  override setDisabledState() {}\n  valueChange(value: any) {\n    this.setProperty('value', value);\n    this.onChange(value);\n  }\n}\n"
  },
  {
    "path": "src/library/forms/src/directives/radio_control_value_accessor.ts",
    "content": "/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {\n  ContentChildren,\n  Directive,\n  ElementRef,\n  HostBinding,\n  Injectable,\n  Injector,\n  Input,\n  NgModule,\n  OnDestroy,\n  OnInit,\n  QueryList,\n  Renderer2,\n  forwardRef,\n} from '@angular/core';\n\nimport {\n  BuiltInControlValueAccessor,\n  ControlValueAccessor,\n  NG_VALUE_ACCESSOR,\n} from './control_value_accessor';\nimport { NgControl } from './ng_control';\n\nexport const RADIO_GROUP_VALUE_ACCESSOR: any = {\n  provide: NG_VALUE_ACCESSOR,\n  useExisting: forwardRef(() => RadioGroupValueAccessor),\n  multi: true,\n};\n\nfunction throwNameError() {\n  throw new Error(`\n      If you define both a name and a formControlName attribute on your radio button, their values\n      must match. Ex: <input type=\"radio\" formControlName=\"food\" name=\"food\">\n    `);\n}\n\n/**\n * Internal-only NgModule that works as a host for the `RadioControlRegistry` tree-shakable\n * provider. Note: the `InternalFormsSharedModule` can not be used here directly, since it's\n * declared *after* the `RadioControlRegistry` class and the `providedIn` doesn't support\n * `forwardRef` logic.\n */\n@NgModule()\nexport class RadioControlRegistryModule {}\n\n/**\n * @description\n * Class used by Angular to track radio buttons. For internal use only.\n */\n@Injectable({ providedIn: RadioControlRegistryModule })\nexport class RadioControlRegistry {\n  private _accessors: any[] = [];\n\n  /**\n   * @description\n   * Adds a control to the internal registry. For internal use only.\n   */\n  add(control: NgControl, accessor: RadioControl) {\n    this._accessors.push([control, accessor]);\n  }\n\n  /**\n   * @description\n   * Removes a control from the internal registry. For internal use only.\n   */\n  remove(accessor: RadioControl) {\n    for (let i = this._accessors.length - 1; i >= 0; --i) {\n      if (this._accessors[i][1] === accessor) {\n        this._accessors.splice(i, 1);\n        return;\n      }\n    }\n  }\n\n  /**\n   * @description\n   * Selects a radio button. For internal use only.\n   */\n  select(accessor: RadioControl) {\n    this._accessors.forEach((c) => {\n      if (this._isSameGroup(c, accessor) && c[1] !== accessor) {\n        c[1].fireUncheck(accessor.value);\n      }\n    });\n  }\n\n  private _isSameGroup(\n    controlPair: [NgControl, RadioControl],\n    accessor: RadioControl\n  ): boolean {\n    if (!controlPair[0].control) {\n      return false;\n    }\n    // todo 这个服务不一定保留\n    return false;\n    // return (\n    //   controlPair[0]._parent === accessor._control._parent &&\n    //   controlPair[1].name === accessor.name\n    // );\n  }\n}\n@Directive({\n  selector:\n    'radio-group[formControlName],radio-group[formControl],radio-group[ngModel]',\n  host: {\n    '(bindchange)': 'valueChange($event.detail.value)',\n  },\n  providers: [RADIO_GROUP_VALUE_ACCESSOR],\n})\nexport class RadioGroupValueAccessor\n  extends BuiltInControlValueAccessor\n  implements ControlValueAccessor\n{\n  @ContentChildren(forwardRef(() => RadioControl), { descendants: true })\n  children!: QueryList<RadioControl>;\n  valueChange(value: string) {\n    if (this.children) {\n      this.children.forEach((item) => {\n        item.updateChecked(item.value === value);\n      });\n    }\n    this.onChange(value);\n  }\n  writeValue(value: string) {\n    if (this.children) {\n      this.children.forEach((item) => {\n        item.updateChecked(item.value === value);\n      });\n    }\n  }\n}\n/**\n * @description\n * The `ControlValueAccessor` for writing radio control values and listening to radio control\n * changes. The value accessor is used by the `FormControlDirective`, `FormControlName`, and\n * `NgModel` directives.\n *\n * @usageNotes\n *\n * ### Using radio buttons with reactive form directives\n *\n * The follow example shows how to use radio buttons in a reactive form. When using radio buttons in\n * a reactive form, radio buttons in the same group should have the same `formControlName`.\n * Providing a `name` attribute is optional.\n *\n * {@example forms/ts/reactiveRadioButtons/reactive_radio_button_example.ts region='Reactive'}\n *\n * @ngModule ReactiveFormsModule\n * @ngModule FormsModule\n * @publicApi\n * todo 写入值可以从这里来,读取的话就需要从上一级,需要处理本组件与group的关系\n */\n@Directive({\n  selector: 'radio',\n  host: {},\n})\nexport class RadioControl {\n  /**\n   * @description\n   * Tracks the value of the radio input element\n   */\n\n  @HostBinding('value') @Input() readonly value!: string | undefined;\n  @HostBinding('checked')\n  checked: boolean | undefined;\n\n  constructor(\n    private renderer: Renderer2,\n    private elementRef: ElementRef,\n    private _registry: RadioControlRegistry,\n    private _injector: Injector\n  ) {}\n\n  updateChecked(value: boolean) {\n    this.renderer.setProperty(this.elementRef.nativeElement, 'checked', value);\n  }\n}\n"
  },
  {
    "path": "src/library/forms/src/directives/slider_value_accessor.ts",
    "content": "/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {\n  Directive,\n  ElementRef,\n  HostBinding,\n  Renderer2,\n  forwardRef,\n} from '@angular/core';\n\nimport {\n  BuiltInControlValueAccessor,\n  ControlValueAccessor,\n  NG_VALUE_ACCESSOR,\n} from './control_value_accessor';\n\nexport const NUMBER_VALUE_ACCESSOR: any = {\n  provide: NG_VALUE_ACCESSOR,\n  useExisting: forwardRef(() => SliderValueAccessor),\n  multi: true,\n};\n\n/**\n * @description\n * The `ControlValueAccessor` for writing a number value and listening to number input changes.\n * The value accessor is used by the `FormControlDirective`, `FormControlName`, and `NgModel`\n * directives.\n *\n * @usageNotes\n *\n * ### Using a number input with a reactive form.\n *\n * The following example shows how to use a number input with a reactive form.\n *\n * ```ts\n * const totalCountControl = new FormControl();\n * ```\n *\n * ```\n * <input type=\"number\" [formControl]=\"totalCountControl\">\n * ```\n *\n * @ngModule ReactiveFormsModule\n * @ngModule FormsModule\n * @publicApi\n */\n@Directive({\n  selector: 'slider[formControlName],slider[formControl],slider[ngModel]',\n  host: { '(bindchange)': 'valueChange($event.detail.value)' },\n  providers: [NUMBER_VALUE_ACCESSOR],\n})\nexport class SliderValueAccessor\n  extends BuiltInControlValueAccessor\n  implements ControlValueAccessor\n{\n  @HostBinding('value') value: number | undefined;\n  @HostBinding('disabled') disabled: boolean | undefined;\n  /**\n   * Sets the \"value\" property on the input element.\n   * @nodoc\n   */\n  writeValue(value: number): void {\n    const normalizedValue = value == null ? undefined : value;\n    if (typeof normalizedValue !== 'undefined') {\n      this.setProperty('value', normalizedValue);\n    }\n  }\n  valueChange(value: any) {\n    this.setProperty('value', value);\n    this.onChange(value);\n  }\n}\n"
  },
  {
    "path": "src/library/forms/src/directives/switch_value_accessor.ts",
    "content": "/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {\n  Directive,\n  ElementRef,\n  HostBinding,\n  Renderer2,\n  forwardRef,\n} from '@angular/core';\n\nimport {\n  BuiltInControlValueAccessor,\n  ControlValueAccessor,\n  NG_VALUE_ACCESSOR,\n} from './control_value_accessor';\n\nexport const SWITCH_VALUE_ACCESSOR: any = {\n  provide: NG_VALUE_ACCESSOR,\n  useExisting: forwardRef(() => SwitchValueAccessor),\n  multi: true,\n};\n\n/**\n * @description\n * The `ControlValueAccessor` for writing a number value and listening to number input changes.\n * The value accessor is used by the `FormControlDirective`, `FormControlName`, and `NgModel`\n * directives.\n *\n * @usageNotes\n *\n * ### Using a number input with a reactive form.\n *\n * The following example shows how to use a number input with a reactive form.\n *\n * ```ts\n * const totalCountControl = new FormControl();\n * ```\n *\n * ```\n * <input type=\"number\" [formControl]=\"totalCountControl\">\n * ```\n *\n * @ngModule ReactiveFormsModule\n * @ngModule FormsModule\n * @publicApi\n */\n@Directive({\n  selector: 'switch[formControlName],switch[formControl],switch[ngModel]',\n  host: { '(bindchange)': 'valueChange($event.detail.value)' },\n  providers: [SWITCH_VALUE_ACCESSOR],\n})\nexport class SwitchValueAccessor\n  extends BuiltInControlValueAccessor\n  implements ControlValueAccessor\n{\n  @HostBinding('checked') value: boolean | undefined;\n  @HostBinding('disabled') disabled: boolean | undefined;\n  /**\n   * Sets the \"value\" property on the input element.\n   * @nodoc\n   */\n  writeValue(value: boolean): void {\n    const normalizedValue = value == null ? undefined : value;\n    if (typeof normalizedValue !== 'undefined') {\n      this.setProperty('value', normalizedValue);\n    }\n  }\n  valueChange(value: any) {\n    this.setProperty('value', value);\n    this.onChange(value);\n  }\n}\n"
  },
  {
    "path": "src/library/forms/src/directives.ts",
    "content": "/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport { NgModule, Type } from '@angular/core';\n\nimport {\n  CheckboxControl,\n  CheckBoxGroupValueAccessor,\n} from './directives/checkbox_value_accessor';\nimport { DefaultValueAccessor } from './directives/default_value_accessor';\nimport {\n  NgControlStatus,\n  NgControlStatusGroup,\n} from './directives/ng_control_status';\nimport { NgForm } from './directives/ng_form';\nimport { NgModel } from './directives/ng_model';\nimport { NgModelGroup } from './directives/ng_model_group';\nimport { NgNoValidate } from './directives/ng_no_validate_directive';\nimport { PickerValueAccessor } from './directives/picker_value_accessor';\nimport { PickerViewValueAccessor } from './directives/picker_view_value_accessor';\nimport {\n  RadioControl,\n  RadioControlRegistryModule,\n  RadioGroupValueAccessor,\n} from './directives/radio_control_value_accessor';\nimport { RangeValueAccessor } from './directives/range_value_accessor';\nimport { FormControlDirective } from './directives/reactive_directives/form_control_directive';\nimport { FormControlName } from './directives/reactive_directives/form_control_name';\nimport { FormGroupDirective } from './directives/reactive_directives/form_group_directive';\nimport {\n  FormArrayName,\n  FormGroupName,\n} from './directives/reactive_directives/form_group_name';\nimport {\n  NgSelectOption,\n  SelectControlValueAccessor,\n} from './directives/select_control_value_accessor';\nimport {\n  NgSelectMultipleOption,\n  SelectMultipleControlValueAccessor,\n} from './directives/select_multiple_control_value_accessor';\nimport { SliderValueAccessor } from './directives/slider_value_accessor';\nimport { SwitchValueAccessor } from './directives/switch_value_accessor';\nimport {\n  CheckboxRequiredValidator,\n  EmailValidator,\n  MaxLengthValidator,\n  MaxValidator,\n  MinLengthValidator,\n  MinValidator,\n  PatternValidator,\n  RequiredValidator,\n} from './directives/validators';\n\nexport {\n  CheckboxControl,\n  CheckBoxGroupValueAccessor,\n} from './directives/checkbox_value_accessor';\nexport { ControlValueAccessor } from './directives/control_value_accessor';\nexport { DefaultValueAccessor } from './directives/default_value_accessor';\nexport { NgControl } from './directives/ng_control';\nexport {\n  NgControlStatus,\n  NgControlStatusGroup,\n} from './directives/ng_control_status';\nexport { NgForm } from './directives/ng_form';\nexport { NgModel } from './directives/ng_model';\nexport { NgModelGroup } from './directives/ng_model_group';\nexport { SliderValueAccessor } from './directives/slider_value_accessor';\nexport { SwitchValueAccessor } from './directives/switch_value_accessor';\nexport { PickerViewValueAccessor } from './directives/picker_view_value_accessor';\nexport { PickerValueAccessor } from './directives/picker_value_accessor';\n\nexport {\n  RadioControl,\n  RadioGroupValueAccessor,\n} from './directives/radio_control_value_accessor';\nexport { RangeValueAccessor } from './directives/range_value_accessor';\nexport {\n  FormControlDirective,\n  NG_MODEL_WITH_FORM_CONTROL_WARNING,\n} from './directives/reactive_directives/form_control_directive';\nexport { FormControlName } from './directives/reactive_directives/form_control_name';\nexport { FormGroupDirective } from './directives/reactive_directives/form_group_directive';\nexport {\n  FormArrayName,\n  FormGroupName,\n} from './directives/reactive_directives/form_group_name';\nexport {\n  NgSelectOption,\n  SelectControlValueAccessor,\n} from './directives/select_control_value_accessor';\nexport {\n  NgSelectMultipleOption,\n  SelectMultipleControlValueAccessor,\n} from './directives/select_multiple_control_value_accessor';\n\nexport const SHARED_FORM_DIRECTIVES: Type<any>[] = [\n  NgNoValidate,\n  NgSelectOption,\n  NgSelectMultipleOption,\n  DefaultValueAccessor,\n  SliderValueAccessor,\n  RangeValueAccessor,\n  CheckboxControl,\n  SelectControlValueAccessor,\n  SelectMultipleControlValueAccessor,\n  RadioControl,\n  NgControlStatus,\n  NgControlStatusGroup,\n  RequiredValidator,\n  MinLengthValidator,\n  MaxLengthValidator,\n  PatternValidator,\n  CheckboxRequiredValidator,\n  EmailValidator,\n  MinValidator,\n  MaxValidator,\n  SwitchValueAccessor,\n  PickerViewValueAccessor,\n  PickerValueAccessor,\n  RadioGroupValueAccessor,\n  CheckBoxGroupValueAccessor,\n];\n\nexport const TEMPLATE_DRIVEN_DIRECTIVES: Type<any>[] = [\n  NgModel,\n  NgModelGroup,\n  NgForm,\n];\n\nexport const REACTIVE_DRIVEN_DIRECTIVES: Type<any>[] = [\n  FormControlDirective,\n  FormGroupDirective,\n  FormControlName,\n  FormGroupName,\n  FormArrayName,\n];\n\n/**\n * Internal module used for sharing directives between FormsModule and ReactiveFormsModule\n */\n@NgModule({\n  declarations: SHARED_FORM_DIRECTIVES,\n  imports: [RadioControlRegistryModule],\n  exports: SHARED_FORM_DIRECTIVES,\n})\nexport class ɵInternalFormsSharedModule {}\n\nexport { ɵInternalFormsSharedModule as InternalFormsSharedModule };\n"
  },
  {
    "path": "src/library/forms/src/forms.ts",
    "content": "/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/**\n * @module\n * @description\n * This module is used for handling user input, by defining and building a `FormGroup` that\n * consists of `FormControl` objects, and mapping them onto the DOM. `FormControl`\n * objects can then be used to read information from the form DOM elements.\n *\n * Forms providers are not included in default providers; you must import these providers\n * explicitly.\n */\n\nexport { ɵInternalFormsSharedModule } from './directives';\nexport { AbstractControlDirective } from './directives/abstract_control_directive';\nexport { AbstractFormGroupDirective } from './directives/abstract_form_group_directive';\nexport { CheckboxControl } from './directives/checkbox_value_accessor';\nexport { ControlContainer } from './directives/control_container';\nexport {\n  ControlValueAccessor,\n  NG_VALUE_ACCESSOR,\n} from './directives/control_value_accessor';\nexport {\n  COMPOSITION_BUFFER_MODE,\n  DefaultValueAccessor,\n} from './directives/default_value_accessor';\nexport { Form } from './directives/form_interface';\nexport { NgControl } from './directives/ng_control';\nexport {\n  NgControlStatus,\n  NgControlStatusGroup,\n} from './directives/ng_control_status';\nexport { NgForm } from './directives/ng_form';\nexport { NgModel } from './directives/ng_model';\nexport { NgModelGroup } from './directives/ng_model_group';\nexport { ɵNgNoValidate } from './directives/ng_no_validate_directive';\nexport { NumberValueAccessor } from './directives/number_value_accessor';\nexport { RangeValueAccessor } from './directives/range_value_accessor';\nexport { FormControlDirective } from './directives/reactive_directives/form_control_directive';\nexport { FormControlName } from './directives/reactive_directives/form_control_name';\nexport { FormGroupDirective } from './directives/reactive_directives/form_group_directive';\nexport {\n  FormArrayName,\n  FormGroupName,\n} from './directives/reactive_directives/form_group_name';\nexport {\n  NgSelectOption,\n  SelectControlValueAccessor,\n} from './directives/select_control_value_accessor';\nexport { SwitchValueAccessor } from './directives/switch_value_accessor';\nexport { SliderValueAccessor } from './directives/slider_value_accessor';\nexport {\n  SelectMultipleControlValueAccessor,\n  ɵNgSelectMultipleOption,\n} from './directives/select_multiple_control_value_accessor';\nexport {\n  RadioGroupValueAccessor,\n  RadioControl,\n} from './directives/radio_control_value_accessor';\nexport { PickerViewValueAccessor } from './directives/picker_view_value_accessor';\nexport { PickerValueAccessor } from './directives/picker_value_accessor';\nexport { CheckBoxGroupValueAccessor } from './directives/checkbox_value_accessor';\nexport {\n  AsyncValidator,\n  AsyncValidatorFn,\n  CheckboxRequiredValidator,\n  EmailValidator,\n  MaxLengthValidator,\n  MaxValidator,\n  MinLengthValidator,\n  MinValidator,\n  PatternValidator,\n  RequiredValidator,\n  ValidationErrors,\n  Validator,\n  ValidatorFn,\n} from './directives/validators';\nexport {\n  FormBuilder,\n  NonNullableFormBuilder,\n  UntypedFormBuilder,\n  ɵElement,\n} from './form_builder';\nexport {\n  AbstractControl,\n  AbstractControlOptions,\n  FormControlStatus,\n  ɵCoerceStrArrToNumArr,\n  ɵGetProperty,\n  ɵNavigate,\n  ɵRawValue,\n  ɵTokenize,\n  ɵTypedOrUntyped,\n  ɵValue,\n  ɵWriteable,\n} from './model/abstract_model';\nexport {\n  FormArray,\n  UntypedFormArray,\n  ɵFormArrayRawValue,\n  ɵFormArrayValue,\n} from './model/form_array';\nexport {\n  FormControl,\n  FormControlOptions,\n  FormControlState,\n  UntypedFormControl,\n  ɵFormControlCtor,\n} from './model/form_control';\nexport {\n  FormGroup,\n  FormRecord,\n  UntypedFormGroup,\n  ɵFormGroupRawValue,\n  ɵFormGroupValue,\n  ɵOptionalKeys,\n} from './model/form_group';\nexport { NG_ASYNC_VALIDATORS, NG_VALIDATORS, Validators } from './validators';\nexport { VERSION } from './version';\n\nexport * from './form_providers';\n"
  },
  {
    "path": "src/library/index.ts",
    "content": "export * from 'angular-miniprogram/platform';\n"
  },
  {
    "path": "src/library/ng-package.json",
    "content": "{\n  \"$schema\": \"../node_modules/ng-packagr/ng-package.schema.json\",\n  \"dest\": \"../../dist\",\n  \"deleteDestPath\": true,\n  \"allowedNonPeerDependencies\": [\n    \"cyia-code-util\",\n    \"webpack-bootstrap-assets-plugin\",\n    \"static-injector\"\n  ],\n  \"lib\": {\n    \"entryFile\": \"./platform/index.ts\"\n  }\n}\n"
  },
  {
    "path": "src/library/package.json",
    "content": "{\n  \"name\": \"angular-miniprogram\",\n  \"version\": \"1.5.2\",\n  \"description\": \"使用Angular开发小程序\",\n  \"keywords\": [\n    \"Angular\",\n    \"miniprogram\",\n    \"wechat\",\n    \"weixin\",\n    \"Angular 17\"\n  ],\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/wszgrcy/angular-miniprogram.git\"\n  },\n  \"author\": \"wszgrcy\",\n  \"license\": \"MIT\",\n  \"bugs\": {\n    \"url\": \"https://github.com/wszgrcy/angular-miniprogram/issues\"\n  },\n  \"homepage\": \"https://github.com/wszgrcy/angular-miniprogram#readme\",\n  \"dependencies\": {\n    \"cyia-code-util\": \"1.8.0\",\n    \"webpack-bootstrap-assets-plugin\": \"2.0.3\",\n    \"static-injector\": \"4.0.2\"\n  },\n  \"peerDependencies\": {\n    \"ng-packagr\": \"^17.3.0\",\n    \"@angular/core\": \"^17.3.1\",\n    \"jasmine-core\": \"5.1.2\"\n  },\n  \"exports\": {\n    \"./karma/client\": {\n      \"default\": \"./karma/client/index.js\"\n    },\n    \"./karma/plugin\": {\n      \"default\": \"./karma/plugin/index.js\",\n      \"types\": \"./karma/plugin/index.d.ts\"\n    }\n  },\n  \"builders\": \"./builder/builders.json\"\n}\n"
  },
  {
    "path": "src/library/platform/bd/index.ts",
    "content": "export * from './platform-core';\n"
  },
  {
    "path": "src/library/platform/bd/ng-package.json",
    "content": "{\n  \"$schema\": \"../../../node_modules/ng-packagr/ng-package.schema.json\",\n  \"lib\": {\n    \"entryFile\": \"./index.ts\"\n  }\n}\n"
  },
  {
    "path": "src/library/platform/bd/platform-core.ts",
    "content": "/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { MiniProgramCoreFactory as BaseFactory } from 'angular-miniprogram/platform/default';\n\nclass MiniProgramCoreFactory extends BaseFactory {}\nexport const MiniProgramCore = new MiniProgramCoreFactory();\n\nexport {\n  PAGE_TOKEN,\n  MiniProgramRenderer,\n  MiniProgramRendererFactory,\n  ComponentFinderService,\n  propertyChange,\n} from 'angular-miniprogram/platform/default';\n"
  },
  {
    "path": "src/library/platform/dd/index.ts",
    "content": "export * from './platform-core';\n"
  },
  {
    "path": "src/library/platform/dd/ng-package.json",
    "content": "{\n  \"$schema\": \"../../../node_modules/ng-packagr/ng-package.schema.json\",\n  \"lib\": {\n    \"entryFile\": \"./index.ts\"\n  }\n}\n"
  },
  {
    "path": "src/library/platform/dd/platform-core.ts",
    "content": "export * from 'angular-miniprogram/platform/default';\n"
  },
  {
    "path": "src/library/platform/default/agent-node.spec.ts",
    "content": "import { AgentNode } from './agent-node';\n\nfunction getAgentNode() {\n  return new AgentNode('element');\n}\ndescribe('AgentNode', () => {\n  it('appendChild', () => {\n    const root = new AgentNode('element');\n    const child1 = new AgentNode('element');\n    root.appendChild(child1);\n    expect(root.children[0]).toBe(child1);\n    expect(child1.parent).toBe(root);\n    expect(child1.nextSibling).toBe(undefined);\n    const child2 = new AgentNode('element');\n    root.appendChild(child2);\n    expect(root.children.length).toBe(2);\n    expect(child2.parent).toBe(root);\n    expect(child1.nextSibling).toBe(child2);\n    expect(child2.nextSibling).toBe(undefined);\n  });\n  it('setParent', () => {\n    const parent1 = getAgentNode();\n    const child1 = getAgentNode();\n    parent1.appendChild(child1);\n    expect(child1.parent).toBe(parent1);\n    const parent2 = getAgentNode();\n    child1.setParent(parent2);\n    expect(child1.parent).toBe(parent2);\n    expect(parent1.children.length).toBe(0);\n    expect(parent2.children.length).toBe(1);\n  });\n  it('insertBefore', () => {\n    const parent1 = getAgentNode();\n    const child1 = getAgentNode();\n    const child2 = getAgentNode();\n    parent1.appendChild(child1);\n    parent1.insertBefore(child2, child1);\n    expect(parent1.children.length).toBe(2);\n    expect(parent1.children[0]).toBe(child2);\n    expect(parent1.children[1]).toBe(child1);\n    expect(parent1.children[0].nextSibling).toBe(parent1.children[1]);\n    const child3 = getAgentNode();\n    parent1.insertBefore(child3, child1);\n    expect(parent1.children[1]).toBe(child3);\n    expect(parent1.children[2]).toBe(child1);\n    expect(parent1.children[1].nextSibling).toBe(parent1.children[2]);\n  });\n  it('removeChild', () => {\n    const root = getAgentNode();\n    const list = new Array(3).fill(undefined).map(() => getAgentNode());\n    list.forEach((item) => {\n      root.appendChild(item);\n    });\n    root.removeChild(list[1]);\n    expect(root.children.length).toBe(2);\n    expect(root.children[0].nextSibling).toBe(root.children[1]);\n    root.removeChild(list[2]);\n    expect(root.children.length).toBe(1);\n    expect(root.children[0].nextSibling).toBe(undefined);\n    root.removeChild(list[0]);\n    expect(root.children.length).toBe(0);\n    list.forEach((item) => {\n      expect(item.nextSibling).toBe(undefined);\n      expect(item.parent).toBe(undefined);\n    });\n  });\n  it('toView', () => {\n    const element = new AgentNode('element');\n    element.classList.add('class1');\n    element.style['color'] = 'red';\n    element.property['property1'] = 1;\n    element.attribute.style = 'display:flex';\n    expect(element.toView()).toEqual({\n      class: 'class1',\n      style: 'color:red;display:flex',\n      property: { property1: 1 },\n    });\n    const text = new AgentNode('text');\n    text.value = 'content';\n    expect(text.toView()).toEqual({ value: 'content' });\n  });\n});\n"
  },
  {
    "path": "src/library/platform/default/agent-node.ts",
    "content": "import type {\n  MPElementData,\n  MPTextData,\n} from 'angular-miniprogram/platform/type';\n\nexport class AgentNode {\n  selector!: string | unknown;\n  name!: string;\n  parent!: AgentNode | undefined;\n  nextSibling!: AgentNode | undefined;\n  attribute: Record<string, string> = {};\n  style: Record<string, string> = {};\n  property: Record<string, unknown> = {};\n  classList = new Set<string>();\n  value!: string;\n  children: AgentNode[] = [];\n  listener: Record<string, Function> = {};\n  constructor(public type: 'element' | 'comment' | 'text') {}\n  appendChild(child: AgentNode) {\n    const lastChildIndex = this.children.length - 1;\n    this.children.push(child);\n    child.parent = this;\n    if (lastChildIndex > -1) {\n      this.children[lastChildIndex].nextSibling = child;\n    }\n  }\n  setParent(parent: AgentNode) {\n    const oldParent = this.parent;\n    if (oldParent) {\n      const index = oldParent.children.findIndex((item) => item === this);\n      if (index === -1) {\n        throw new Error('没有在之前的父级上找到该节点' + this);\n      }\n      oldParent.children.splice(index, 1);\n    }\n    parent.appendChild(this);\n  }\n  insertBefore(newChild: AgentNode, refChild: AgentNode) {\n    const refIndex = this.children.findIndex((item) => item === refChild);\n    if (refIndex === -1) {\n      throw new Error('未找到引用子节点' + refChild);\n    }\n\n    if (refIndex === 0) {\n      newChild.nextSibling = refChild;\n    } else {\n      this.children[refIndex - 1].nextSibling = newChild;\n      newChild.nextSibling = refChild;\n    }\n    this.children.splice(refIndex, 0, newChild);\n  }\n  removeChild(child: AgentNode) {\n    const index = this.children.findIndex((item) => item === child);\n    if (index === 0) {\n      this.children.shift();\n    } else if (index + 1 === this.children.length) {\n      this.children[index - 1].nextSibling = undefined;\n      this.children.pop();\n    } else {\n      this.children[index - 1].nextSibling = this.children[index + 1];\n      this.children.splice(index, 1);\n    }\n    child.nextSibling = undefined;\n    child.parent = undefined;\n  }\n  toView(): MPTextData | MPElementData {\n    if (this.type === 'text') {\n      return { value: this.value };\n    } else {\n      return {\n        class:\n          Array.from(this.classList).join(' ') +\n          (this.attribute.class ? ' ' + this.attribute.class : ''),\n\n        style:\n          Object.entries(this.style)\n            .map(([style, value]) => `${style}:${value}`)\n            .join(';') +\n          (this.attribute.style ? ';' + this.attribute.style : ''),\n\n        property: { ...this.property },\n      };\n    }\n  }\n}\n"
  },
  {
    "path": "src/library/platform/default/component-finder.service.ts",
    "content": "import { Injectable } from '@angular/core';\n\n@Injectable()\nexport class ComponentFinderService<T = unknown> {\n  private map = new Map<unknown, T>();\n  private mapPromise = new Map<unknown, Function>();\n  async get(component: unknown) {\n    if (this.map.has(component)) {\n      return this.map.get(component);\n    }\n    let fn: Function;\n    const promise = new Promise((res) => {\n      fn = res;\n    });\n    this.mapPromise.set(component, fn!);\n    return promise.then((result) => {\n      this.mapPromise.delete(component);\n      return result;\n    });\n  }\n  /** @internal */\n  set(component: unknown, instance: T): void {\n    if (this.mapPromise.has(component)) {\n      this.mapPromise.get(component)!();\n    }\n    this.map.set(component, instance);\n  }\n  /** @internal */\n  remove(component: unknown) {\n    return this.map.delete(component);\n  }\n}\n"
  },
  {
    "path": "src/library/platform/default/component-template-hook.factory.ts",
    "content": "/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { ComponentRef, NgZone } from '@angular/core';\nimport { LView } from 'angular-miniprogram/platform/type';\nimport type {\n  MPElementData,\n  MPTextData,\n  MPView,\n  NodePath,\n} from 'angular-miniprogram/platform/type';\nimport { AgentNode } from './agent-node';\nimport { diffNodeData } from './diff-node-data';\n// packages\\core\\src\\render3\\interfaces\\view.ts\nconst CLEANUP = 7;\nexport const LVIEW_CONTEXT = 8;\nexport const INJECTOR = 9;\n// packages\\core\\src\\render3\\interfaces\\container.ts\nconst VIEW_REFS = 8;\n// HEADER_OFFSET\nconst start = 25;\n\nconst linkMap = new Map<LView, any>();\nconst nodePathMap = new Map<LView, NodePath>();\nlet index = 0;\nconst pageRegistryMap = new Map<number, LView>();\nconst lViewLastDataMap = new Map<LView, Record<string, any>>();\nlet waitingRefreshLViewList: (() => void)[] = [];\n/** @internal */\nexport function propertyChange(lView: LView) {\n  if (linkMap.has(lView)) {\n    const ngZone = lView[INJECTOR]!.get(NgZone);\n    waitingRefreshLViewList.push(() => {\n      ngZone.runOutsideAngular(() => {\n        const instance = linkMap.get(lView);\n        if (!instance) {\n          return;\n        }\n        const currentData = getPageRefreshContext(lView);\n        const diffData = getDiffData(lView, currentData);\n        if (Object.keys(diffData).length) {\n          instance.setData(diffData);\n        }\n      });\n    });\n  }\n}\nexport function endRender() {\n  for (const fn of waitingRefreshLViewList) {\n    fn();\n  }\n  waitingRefreshLViewList = [];\n}\n\nexport function getPageRefreshContext(lView: LView) {\n  const lviewPath = getLViewPath(lView);\n  const nodeList = lViewToWXView(lView, lviewPath);\n  const ctx: Partial<MPView> = {\n    nodeList: nodeList,\n    nodePath: lviewPath || [],\n    hasLoad: true,\n  };\n  return ctx;\n}\n\nfunction lViewToWXView(lView: LView, parentNodePath: any[] = []) {\n  const tView = lView[1];\n  const end = tView.bindingStartIndex;\n  const nodeList: MPView['nodeList'] = [];\n  for (let index = start; index < end; index++) {\n    const item = lView[index];\n    if (item instanceof AgentNode) {\n      nodeList[index - start] = item.toView();\n    } else if (item && item[1] === true) {\n      const lContainerList: MPView[] = [];\n      const viewRefList: any[] = item[VIEW_REFS] || [];\n      viewRefList.forEach((item, itemIndex) => {\n        const nodePath = [\n          ...parentNodePath,\n          'directive',\n          index - start,\n          itemIndex,\n        ];\n        lContainerList.push({\n          __templateName: item._lView[LVIEW_CONTEXT]\n            ? item._lView[LVIEW_CONTEXT].__templateName\n            : undefined,\n          nodeList: lViewToWXView(item._lView, nodePath),\n          nodePath: nodePath,\n          index: lContainerList.length,\n        });\n      });\n      nodeList[index - start] = lContainerList;\n    } else {\n      // todo\n      nodeList[index - start] = {} as any;\n    }\n  }\n  return nodeList;\n}\n\nexport function setLViewPath(lView: LView, nodePath: NodePath) {\n  nodePath = nodePath.slice();\n  nodePathMap.set(lView, nodePath);\n}\nfunction getLViewPath(lView: LView) {\n  return nodePathMap.get(lView);\n}\nexport function updatePath(context: MPView, nodePath: NodePath) {\n  nodePath = nodePath.slice();\n  context.nodePath = nodePath;\n  const list: (MPView[] | MPElementData | MPTextData | MPView)[] = [\n    ...context.nodeList,\n  ];\n  while (list.length) {\n    const item = list.pop()!;\n    if (item instanceof Array) {\n      list.push(...item);\n    }\n    if ((item as any).nodeList && (item as any).nodeList.length) {\n      list.push(...(item as any).nodeList);\n    }\n    if ((item as MPView).nodePath) {\n      ((item as MPView).nodePath as any[]).unshift(...nodePath);\n    }\n  }\n  return context;\n}\n\nexport function resolveNodePath(list: NodePath): any {\n  list = list.slice();\n  let lView = pageRegistryMap.get(list.shift() as number)!;\n  while (list.length) {\n    const item = list.shift()!;\n    if (item === 'directive') {\n      const index = list.shift()! as number;\n      const lContainer = lView[index + start];\n      const child = list.shift() as number;\n      const viewRef = lContainer[VIEW_REFS][child];\n      lView = viewRef['_lView'];\n    } else {\n      lView = lView[start + item];\n    }\n  }\n  return lView;\n}\nexport function findCurrentElement(lView: LView, list: NodePath = []) {\n  list = [...list];\n  while (list.length) {\n    const item = list.shift()!;\n    if (item === 'directive') {\n      const index = list.shift() as number;\n      const lContainer = lView[index + start];\n      const child = list.shift() as number;\n      const viewRef = lContainer[VIEW_REFS][child];\n      lView = viewRef['_lView'];\n    } else {\n      lView = lView[item + start];\n    }\n  }\n\n  return lView as any;\n}\n\nexport function lViewLinkToMPComponentRef(ref: any, lView: LView) {\n  linkMap.set(lView, ref);\n}\n\nexport function cleanWhenDestroy(lView: LView, fn: () => void) {\n  const list: Function[] = (lView[CLEANUP] = lView[CLEANUP] || []);\n  list.push(() => cleanAll(lView));\n  list.push(fn);\n}\nexport function cleanAll(lView: LView) {\n  linkMap.delete(lView);\n  nodePathMap.delete(lView);\n  lViewLastDataMap.delete(lView);\n}\n\nexport function findPageLView(componentRef: ComponentRef<unknown>) {\n  const lView = (componentRef as any)._rootLView[start];\n\n  index++;\n  pageRegistryMap.set(index, lView);\n  return { lView: lView as any, id: index };\n}\nexport function removePageLViewLink(id: number) {\n  const lView = pageRegistryMap.get(id)!;\n  lViewLastDataMap.delete(lView);\n  pageRegistryMap.delete(id);\n}\nexport function getDiffData(lView: LView, currentData: Record<string, any>) {\n  const lastData = lViewLastDataMap.get(lView);\n  if (!lastData) {\n    lViewLastDataMap.set(lView, currentData);\n    return currentData;\n  }\n  const diff = diffNodeData(lastData, currentData);\n  lViewLastDataMap.set(lView, currentData);\n  return diff;\n}\n"
  },
  {
    "path": "src/library/platform/default/diff-node-data.spec.ts",
    "content": "import { diffNodeData } from './diff-node-data';\n\ndescribe('diffNodeData', () => {\n  it('基础', () => {\n    expect(diffNodeData({}, {})).toEqual({});\n    expect(diffNodeData({}, { a: 1 })).toEqual({ a: 1 });\n    expect(diffNodeData({ a: 1 }, {})).toEqual({});\n    expect(diffNodeData({}, { a: [] })).toEqual({ a: [] });\n  });\n  it('复合', () => {\n    expect(diffNodeData({ a: [1] }, { a: [2] })).toEqual({ a: [2] });\n    expect(diffNodeData({ a: [1, 2] }, { a: [2, 2] })).toEqual({ ['a[0]']: 2 });\n\n    expect(diffNodeData({ a: 1 }, { a: 2 })).toEqual({ a: 2 });\n    expect(diffNodeData({ a: 1, b: 2 }, { a: 2, b: 2 })).toEqual({ a: 2 });\n    expect(diffNodeData({ a: { b: 1 }, c: 1 }, { a: { b: 2 }, c: 1 })).toEqual({\n      a: { b: 2 },\n    });\n    expect(\n      diffNodeData({ a: { b: 1, b1: 1 }, c: 1 }, { a: { b: 2, b1: 1 }, c: 1 })\n    ).toEqual({\n      ['a.b']: 2,\n    });\n  });\n  it('减少数量全量', () => {\n    expect(\n      diffNodeData({ a: { b: 1, b1: 1 }, c: 1 }, { a: { b: 2 }, c: 1 })\n    ).toEqual({\n      a: { b: 2 },\n    });\n    expect(diffNodeData({ a: [1, 2], c: 1 }, { a: [1], c: 1 })).toEqual({\n      a: [1],\n    });\n  });\n  it('增加数量全量', () => {\n    expect(\n      diffNodeData({ a: { b: 2 }, c: 1 }, { a: { b: 1, b1: 1 }, c: 1 })\n    ).toEqual({\n      a: { b: 1, b1: 1 },\n    });\n    expect(diffNodeData({ a: [1], c: 1 }, { a: [1, 2], c: 1 })).toEqual({\n      a: [1, 2],\n    });\n  });\n});\n"
  },
  {
    "path": "src/library/platform/default/diff-node-data.ts",
    "content": "interface DiffResult {\n  allChange: boolean;\n  object?: Record<string, unknown>;\n}\nfunction _arrayOrObjectItemDiff(\n  count: number,\n  prefix: string,\n  fromItem: unknown,\n  toItem: unknown,\n  changeObject: Record<string, unknown>\n) {\n  if (fromItem instanceof Array && toItem instanceof Array) {\n    const result = diffDataArray(fromItem, toItem, prefix);\n    if (result.allChange || result.object) {\n      if (result.allChange) {\n        count++;\n        changeObject[prefix] = toItem;\n      } else {\n        changeObject = { ...changeObject, ...result.object };\n      }\n    }\n    return { count: count, changeObject };\n  } else if (\n    typeof fromItem === 'object' &&\n    fromItem !== null &&\n    typeof toItem === 'object' &&\n    toItem !== null\n  ) {\n    const result = diffDataObject(\n      fromItem as Record<string, null>,\n      toItem as Record<string, null>,\n      prefix\n    );\n    if (result.allChange || result.object) {\n      if (result.allChange) {\n        count++;\n        changeObject[prefix] = toItem;\n      } else {\n        changeObject = { ...changeObject, ...result.object };\n      }\n    }\n    return { count: count, changeObject };\n  } else if (fromItem !== toItem) {\n    changeObject[prefix] = toItem;\n    count++;\n    return { count: count, changeObject };\n  }\n  return { count: count, changeObject };\n}\nfunction diffDataObject(\n  from: Record<string, unknown>,\n  to: Record<string, unknown>,\n  prefix: string\n): DiffResult {\n  const toKeyList = Object.keys(to);\n  let changeObject: Record<string, unknown> = {};\n  const point = prefix ? '.' : '';\n  let count = 0;\n  if (Object.keys(from).length !== toKeyList.length) {\n    return { allChange: true };\n  }\n\n  for (let index = 0; index < toKeyList.length; index++) {\n    const key = toKeyList[index];\n    const fromItem = from[key];\n    const toItem = to[key];\n    const currentPrefix = `${prefix}${point}${key}`;\n    const result = _arrayOrObjectItemDiff(\n      count,\n      currentPrefix,\n      fromItem,\n      toItem,\n      changeObject\n    );\n    count = result.count;\n    changeObject = result.changeObject;\n  }\n  if (count === toKeyList.length && toKeyList.length !== 0) {\n    return { allChange: true };\n  }\n  return { allChange: false, object: changeObject };\n}\nfunction diffDataArray(\n  from: unknown[],\n  to: unknown[],\n  prefix: string\n): DiffResult {\n  let changeObject: Record<string, unknown> = {};\n\n  if (from.length !== to.length) {\n    return { allChange: true };\n  }\n  let count = 0;\n  for (let i = 0; i < to.length; i++) {\n    const fromItem = from[i];\n    const toItem = to[i];\n    const currentPrefix = `${prefix}[${i}]`;\n    const result = _arrayOrObjectItemDiff(\n      count,\n      currentPrefix,\n      fromItem,\n      toItem,\n      changeObject\n    );\n    count = result.count;\n    changeObject = result.changeObject;\n  }\n  if (count === to.length && to.length !== 0) {\n    return {\n      allChange: true,\n    };\n  }\n  return { allChange: false, object: changeObject };\n}\nexport function diffNodeData(\n  from: Record<string, unknown>,\n  to: Record<string, unknown>\n) {\n  const result = diffDataObject(from, to, '');\n  if (result.allChange) {\n    return to;\n  }\n  return result.object!;\n}\n"
  },
  {
    "path": "src/library/platform/default/index.ts",
    "content": "export * from './platform-core';\nexport * from './token';\nexport * from './mini-program.renderer';\nexport * from './mini-program.renderer.factory';\nexport * from './component-finder.service';\nexport { propertyChange } from './component-template-hook.factory';\n"
  },
  {
    "path": "src/library/platform/default/mini-program.renderer.factory.ts",
    "content": "import {\n  Injectable,\n  Renderer2,\n  RendererFactory2,\n  RendererType2,\n} from '@angular/core';\nimport { AgentNode } from './agent-node';\nimport { endRender } from './component-template-hook.factory';\nimport { MiniProgramRenderer } from './mini-program.renderer';\n\n@Injectable()\nexport class MiniProgramRendererFactory implements RendererFactory2 {\n  defaultRenderer!: MiniProgramRenderer;\n  constructor() {\n    this.defaultRenderer = new MiniProgramRenderer();\n  }\n\n  createRenderer(element: AgentNode, type: RendererType2 | null): Renderer2 {\n    return this.defaultRenderer;\n  }\n  begin() {}\n  end() {\n    endRender();\n  }\n}\n"
  },
  {
    "path": "src/library/platform/default/mini-program.renderer.ts",
    "content": "import { Renderer2, RendererStyleFlags2 } from '@angular/core';\nimport { AgentNode } from './agent-node';\n\nexport class MiniProgramRenderer implements Renderer2 {\n  root!: AgentNode;\n  constructor() {}\n  data = Object.create(null);\n  destroy() {}\n  createElement(name: string, namespace?: string | null) {\n    const element = new AgentNode('element');\n    element.name = name;\n    element.classList.add(`tag-name-${name}`);\n    return element;\n  }\n  createComment(value: string) {\n    const comment = new AgentNode('comment');\n    comment.value = value;\n    return comment;\n  }\n  createText(value: string) {\n    const text = new AgentNode('text');\n    text.value = value;\n    return text;\n  }\n  destroyNode() {}\n  appendChild(parent: AgentNode, newChild: AgentNode) {\n    parent.appendChild(newChild);\n  }\n  insertBefore(\n    parent: AgentNode,\n    newChild: AgentNode,\n    refChild: AgentNode,\n    isMove?: boolean\n  ) {\n    if (isMove) {\n      // todo 应该没用\n    }\n    if (parent) {\n      parent.insertBefore(newChild, refChild);\n    }\n  }\n  removeChild(parent: AgentNode, oldChild: AgentNode, isHostElement?: boolean) {\n    if (isHostElement) {\n      // todo 应该没用\n    }\n    if (parent) {\n      parent.removeChild(oldChild);\n    }\n  }\n  selectRootElement(\n    selectorOrNode: string | unknown,\n    preserveContent?: boolean\n  ) {\n    const root = new AgentNode('element');\n    root.selector = selectorOrNode;\n    this.root = root;\n    return root;\n  }\n  parentNode(node: AgentNode) {\n    return node.parent;\n  }\n  nextSibling(node: AgentNode) {\n    return node.nextSibling;\n  }\n  setAttribute(\n    el: AgentNode,\n    name: string,\n    value: string,\n    namespace?: string | null\n  ) {\n    el.attribute[name] = value;\n  }\n  removeAttribute(el: AgentNode, name: string, namespace?: string | null) {\n    delete el.attribute[name];\n  }\n  addClass(el: AgentNode, name: string) {\n    el.classList.add(name);\n  }\n  removeClass(el: AgentNode, name: string) {\n    el.classList.delete(name);\n  }\n  setStyle(\n    el: AgentNode,\n    style: string,\n    value: string,\n    flags?: RendererStyleFlags2\n  ) {\n    el.style[style] = value;\n  }\n  removeStyle(el: AgentNode, style: string, flags?: RendererStyleFlags2) {\n    delete el.style[style];\n  }\n  setProperty(el: AgentNode, name: string, value: unknown) {\n    el.property[name] = value;\n  }\n  setValue(node: AgentNode, value: string) {\n    node.value = value;\n  }\n  listen(\n    target: AgentNode,\n    eventName: string,\n    callback: (event: WechatMiniprogram.BaseEvent) => boolean | void\n  ) {\n    if (!(target instanceof AgentNode)) {\n      throw new Error('不支持其他类型监听');\n    }\n    target.listener[eventName] = callback;\n    return () => {};\n  }\n}\n"
  },
  {
    "path": "src/library/platform/default/ng-package.json",
    "content": "{\n  \"$schema\": \"../../../node_modules/ng-packagr/ng-package.schema.json\",\n  \"lib\": {\n    \"entryFile\": \"./index.ts\"\n  }\n}\n"
  },
  {
    "path": "src/library/platform/default/platform-core.ts",
    "content": "/// <reference types=\"miniprogram-api-typings\"/>\nimport {\n  ApplicationRef,\n  ChangeDetectorRef,\n  ComponentRef,\n  NgModuleRef,\n  NgZone,\n  Type,\n} from '@angular/core';\nimport type {\n  AppOptions,\n  LView,\n  MiniProgramComponentInstance,\n  MiniProgramComponentOptions,\n  MiniProgramPageOptions,\n  NodePath,\n} from 'angular-miniprogram/platform/type';\nimport { AgentNode } from './agent-node';\nimport { ComponentFinderService } from './component-finder.service';\nimport {\n  INJECTOR,\n  LVIEW_CONTEXT,\n  cleanAll,\n  cleanWhenDestroy,\n  findCurrentElement,\n  findPageLView,\n  getDiffData,\n  getPageRefreshContext,\n  lViewLinkToMPComponentRef,\n  removePageLViewLink,\n  resolveNodePath,\n  setLViewPath,\n  updatePath,\n} from './component-template-hook.factory';\n\nexport class MiniProgramCoreFactory {\n  public MINIPROGRAM_GLOBAL = wx;\n  public loadApp = <T>(app: T) => {\n    App(app || {});\n    const appInstance = getApp() as unknown as AppOptions;\n\n    appInstance.__ngStartPagePromise = new Promise((resolve) => {\n      appInstance.__ngStartPageResolve = resolve;\n    });\n    return appInstance;\n  };\n\n  protected eventPrefixList = [\n    { listener: 'bind', prefix: 'bind' },\n    { listener: 'catch', prefix: 'catch' },\n    { listener: 'mutBind', prefix: 'mut-bind' },\n    { listener: 'captureBind', prefix: 'capture-bind' },\n    { listener: 'captureCatch', prefix: 'capture-catch' },\n  ];\n  protected getListenerEventMapping(prefix: string, name: string) {\n    return [name, prefix + name];\n  }\n\n  protected linkNgComponentWithPath(\n    mpComponentInstance: MiniProgramComponentInstance,\n    list: NodePath\n  ) {\n    mpComponentInstance.__isLink = true;\n    const lView: LView = resolveNodePath(list);\n    const injector = lView[INJECTOR]!;\n    mpComponentInstance.__lView = lView;\n    mpComponentInstance.__ngComponentInstance = lView[LVIEW_CONTEXT];\n    mpComponentInstance.__ngComponentInjector = injector;\n    const ngZone = injector.get(NgZone);\n    mpComponentInstance.__ngZone = ngZone;\n    const componentFinderService = injector.get(ComponentFinderService);\n    componentFinderService.set(\n      mpComponentInstance.__ngComponentInstance,\n      mpComponentInstance\n    );\n    cleanWhenDestroy(lView, () => {\n      componentFinderService.remove(mpComponentInstance.__ngComponentInstance);\n    });\n    setLViewPath(lView, list);\n    lViewLinkToMPComponentRef(mpComponentInstance, lView);\n    mpComponentInstance.__waitLinkResolve();\n    ngZone.runOutsideAngular(() => {\n      const initValue = getPageRefreshContext(lView);\n      const diffData = getDiffData(lView, initValue);\n      if (Object.keys(diffData).length) {\n        mpComponentInstance.setData(diffData);\n      }\n    });\n  }\n  /** 监听事件 */\n  protected listenerEvent() {\n    const _this = this;\n    return this.eventPrefixList.reduce((pre: Record<string, Function>, cur) => {\n      pre[cur.listener + 'Event'] = function (\n        this: MiniProgramComponentInstance,\n        event: WechatMiniprogram.BaseEvent\n      ) {\n        if (this.__lView) {\n          const dataset = event.currentTarget?.dataset || event.target.dataset;\n          const currentPath: NodePath = [\n            ...(dataset.nodePath || []),\n            dataset.nodeIndex,\n          ];\n          const nodePath = this.__completePath || [];\n          const relativePath = currentPath.slice(nodePath.length);\n          let el = findCurrentElement(this.__lView, relativePath) as AgentNode;\n          if (!(el instanceof AgentNode)) {\n            el = el[0];\n            if (!(el instanceof AgentNode)) {\n              throw new Error('查询代理节点失败');\n            }\n          }\n\n          const eventName = event.type;\n          _this\n            .getListenerEventMapping(cur.prefix, eventName)\n            .forEach((name) => {\n              this.__ngZone.run(() => {\n                if (el.listener[name]) {\n                  el.listener[name](event);\n                }\n              });\n            });\n        } else {\n          throw new Error('未绑定lView');\n        }\n      };\n\n      return pre;\n    }, {});\n  }\n  protected pageStatus = {\n    destroy: function (this: MiniProgramComponentInstance) {\n      if (this.__ngDestroy) {\n        this.__ngDestroy();\n      }\n    },\n    attachView: function (this: MiniProgramComponentInstance) {\n      if (this.__ngComponentInjector && this.__isDetachView) {\n        const applicationRef = this.__ngComponentInjector.get(ApplicationRef);\n        applicationRef.attachView(this.__ngComponentHostView);\n        this.__isDetachView = false;\n      }\n    },\n    detachView: function (this: MiniProgramComponentInstance) {\n      if (this.__ngComponentInjector) {\n        this.__isDetachView = true;\n        const applicationRef = this.__ngComponentInjector.get(ApplicationRef);\n        applicationRef.detachView(this.__ngComponentHostView);\n      }\n    },\n  };\n  protected linkNgComponentWithPage(\n    mpComponentInstance: MiniProgramComponentInstance,\n    componentRef: ComponentRef<unknown>,\n    ngModuleRef: NgModuleRef<unknown>\n  ) {\n    mpComponentInstance.__isLink = true;\n    mpComponentInstance.__ngComponentHostView = componentRef.hostView;\n    mpComponentInstance.__ngComponentInstance = componentRef.instance;\n    mpComponentInstance.__ngComponentInjector = componentRef.injector;\n    const ngZone = componentRef.injector.get(NgZone);\n    mpComponentInstance.__ngZone = ngZone;\n    const { lView, id }: { lView: LView; id: number } =\n      findPageLView(componentRef);\n    setLViewPath(lView, [id]);\n    mpComponentInstance.__completePath = [id];\n    ngZone.runOutsideAngular(() => {\n      const initValue = getPageRefreshContext(lView);\n      const diffData = getDiffData(lView, initValue);\n      if (Object.keys(diffData).length) {\n        mpComponentInstance.setData(diffData);\n      }\n    });\n    lViewLinkToMPComponentRef(mpComponentInstance, lView);\n    mpComponentInstance.__lView = lView;\n    mpComponentInstance.__ngDestroy = () => {\n      ngModuleRef.destroy();\n      componentRef.destroy();\n      removePageLViewLink(id);\n      cleanAll(lView);\n    };\n  }\n\n  public pageStartup = (\n    module: Type<unknown>,\n    component: Type<unknown>,\n    pageOptions?: { useComponent: boolean }\n  ) => {\n    const _this = this;\n    if (pageOptions?.useComponent) {\n      const options = this.getComponentOptions<true>(component) || {};\n      const config: WechatMiniprogram.Component.Options<{}, {}, {}, {}, true> =\n        {\n          ...options,\n          data: { hasLoad: false },\n          options: { ...options?.options, multipleSlots: true },\n          methods: {\n            ...options.methods,\n            ...this.listenerEvent(),\n            onHide: async function (this: MiniProgramComponentInstance) {\n              if (options.methods?.onHide) {\n                await options.methods.onHide.bind(this)();\n              }\n              _this.pageStatus.detachView.bind(this)();\n            },\n            onUnload: async function (this: MiniProgramComponentInstance) {\n              if (options.methods?.onUnload) {\n                await options.methods.onUnload.bind(this)();\n              }\n              _this.pageStatus.destroy.bind(this)();\n            },\n\n            onShow: async function (this: MiniProgramComponentInstance) {\n              if (options.methods?.onShow) {\n                await options.methods.onShow.bind(this)();\n              }\n              return _this.pageStatus.attachView.bind(this)();\n            },\n          },\n        };\n      config.lifetimes = config.lifetimes || {};\n      const oldCreated = config.lifetimes.created;\n      let componentRef: ComponentRef<unknown>,\n        ngModuleRef: NgModuleRef<unknown>;\n      config.lifetimes.created = function (this: MiniProgramComponentInstance) {\n        const app = getApp<AppOptions>();\n        // eslint-disable-next-line @typescript-eslint/no-explicit-any\n        this.__lifeTimePromiseObject = {} as any;\n        return (this.__lifeTimePromiseObject['created'] =\n          app.__ngStartPagePromise.then(() => {\n            const result = app.__ngStartPage(module, component, this);\n            componentRef = result.componentRef;\n            ngModuleRef = result.ngModuleRef;\n            if (oldCreated) {\n              oldCreated.bind(this)();\n            }\n          }));\n      };\n      const oldAttached = config.lifetimes.attached;\n      config.lifetimes.attached = function (\n        this: MiniProgramComponentInstance\n      ) {\n        return this.__lifeTimePromiseObject['created'].then(() => {\n          _this.linkNgComponentWithPage(this, componentRef, ngModuleRef);\n          if (oldAttached) {\n            oldAttached.bind(this)();\n          }\n        });\n      };\n      return Component(config);\n    }\n    const options = this.getPageOptions(component) || {};\n    return Page({\n      ...options,\n      ...this.listenerEvent(),\n      data: { hasLoad: false },\n\n      onHide: async function (this: MiniProgramComponentInstance) {\n        if (options.onHide) {\n          await options.onHide.bind(this)();\n        }\n        _this.pageStatus.detachView.bind(this)();\n      },\n      onUnload: async function (this: MiniProgramComponentInstance) {\n        if (options.onUnload) {\n          await options.onUnload.bind(this)();\n        }\n        _this.pageStatus.destroy.bind(this)();\n      },\n      onLoad: function (this: MiniProgramComponentInstance, query) {\n        const app = getApp<AppOptions>();\n        // eslint-disable-next-line @typescript-eslint/no-explicit-any\n        this.__lifeTimePromiseObject = {} as any;\n        return (this.__lifeTimePromiseObject['onLoad'] =\n          app.__ngStartPagePromise.then(() => {\n            const { componentRef, ngModuleRef } = app.__ngStartPage(\n              module,\n              component,\n              this\n            );\n            _this.linkNgComponentWithPage(this, componentRef, ngModuleRef);\n            if (options.onLoad) {\n              return options.onLoad.bind(this)(query);\n            }\n          }));\n      },\n      onShow: function (this: MiniProgramComponentInstance) {\n        return (this.__lifeTimePromiseObject['onShow'] =\n          this.__lifeTimePromiseObject['onLoad'].then(async () => {\n            if (options.onShow) {\n              await options.onShow.bind(this)();\n            }\n            return _this.pageStatus.attachView.bind(this)();\n          }));\n      },\n      onReady: function (this: MiniProgramComponentInstance) {\n        return this.__lifeTimePromiseObject.onShow.then(() => {\n          if (options.onReady) {\n            return options.onReady.bind(this)();\n          }\n        });\n      },\n    });\n  };\n  protected addNgComponentLinkLogic(\n    config: WechatMiniprogram.Component.Options<{}, {}, {}>\n  ) {\n    config.lifetimes = config.lifetimes || {};\n    const oldCreate = config.lifetimes.created;\n    config.lifetimes.created = function (this: MiniProgramComponentInstance) {\n      this.__waitLinkPromise = new Promise<void>((resolve) => {\n        this.__waitLinkResolve = resolve;\n      });\n\n      if (oldCreate) {\n        oldCreate.bind(this)();\n      }\n    };\n    const _this = this;\n    config.properties = {\n      nodePath: {\n        type: null,\n        observer: function (\n          this: MiniProgramComponentInstance,\n          list: NodePath\n        ) {\n          if (this.__isLink) {\n            return;\n          }\n          if (typeof list === 'string') {\n            list = JSON.parse(list);\n          }\n          this.__nodePath = list || [];\n          if (typeof this.__nodeIndex !== 'undefined') {\n            this.__completePath = [...this.__nodePath, this.__nodeIndex];\n            _this.linkNgComponentWithPath(this, this.__completePath);\n          }\n        },\n      },\n      nodeIndex: {\n        type: null,\n        observer: function (this: MiniProgramComponentInstance, index: number) {\n          if (this.__isLink) {\n            return;\n          }\n          if (typeof index === 'string') {\n            index = parseInt(index, 10);\n          }\n          this.__nodeIndex = index;\n          if (typeof this.__nodePath !== 'undefined') {\n            this.__completePath = [...this.__nodePath, this.__nodeIndex];\n            _this.linkNgComponentWithPath(this, this.__completePath);\n          }\n        },\n      },\n    };\n    return config;\n  }\n  public componentRegistry = (component: Type<unknown>) => {\n    const options = this.getComponentOptions(component) || {};\n    let config: WechatMiniprogram.Component.Options<{}, {}, {}> = {\n      ...options,\n      data: { hasLoad: false },\n      options: { ...options?.options, multipleSlots: true },\n      methods: {\n        ...this.listenerEvent(),\n      },\n    };\n\n    config = this.addNgComponentLinkLogic(config);\n    return Component(config);\n  };\n\n  protected getPageOptions(component: Type<unknown> & MiniProgramPageOptions) {\n    return component.mpPageOptions as WechatMiniprogram.Page.Options<{}, {}>;\n  }\n  protected getComponentOptions<T extends boolean = false>(\n    component: Type<unknown> & MiniProgramComponentOptions\n  ) {\n    return component.mpComponentOptions as WechatMiniprogram.Component.Options<\n      {},\n      {},\n      {},\n      {},\n      T\n    >;\n  }\n}\n\nexport const MiniProgramCore = new MiniProgramCoreFactory();\n"
  },
  {
    "path": "src/library/platform/default/token.ts",
    "content": "import { InjectionToken } from '@angular/core';\n\nexport const PAGE_TOKEN = new InjectionToken<unknown>('PAGE_TOKEN');\n"
  },
  {
    "path": "src/library/platform/http/README.md",
    "content": "# 小程序 HTTP\n\n## 注意事项\n\n### 导入\n\n```ts\nimport { HttpClientModule } from 'angular-miniprogram';\n\n@NgModule({\n  imports: [\n    HttpClientModule\n  ]\n})\nexport class AppModule { }\n```\n\n或\n\n```ts\nimport { provideHttpClient } from 'angular-miniprogram';\n\nbootstrapApplication(AppComponent, {\n  providers: [\n    provideHttpClient()\n  ]\n});\n```\n\n### 小程序额外参数\n\n为保持 API 的统一，需要借助 `HttpContext` 来传递小程序额外的参数。\n\n```ts\nimport {\n  UPLOAD_FILE_TOKEN,\n  DOWNLOAD_FILE_TOKEN,\n  REQUSET_TOKEN,\n} from 'angular-miniprogram';\nimport { HttpContext, HttpContextToken } from 'angular-miniprogram/common/http';\n\n// ...\n\n// 小程序开启 HTTP2\nhttp.get('url', {\n  context: new HttpContext().set(REQUSET_TOKEN, {\n    enableHttp2: true,\n  }),\n});\n\n// 小程序文件上传\nhttp.post('url', null, {\n  context: new HttpContext().set(UPLOAD_FILE_TOKEN, {\n    filePath: 'filePath',\n    fileName: 'fileName',\n  }),\n});\n\n// 小程序文件下载\nhttp.get('url', {\n  context: new HttpContext().set(DOWNLOAD_FILE_TOKEN, {\n    filePath: 'filePath',\n  }),\n});\n```\n"
  },
  {
    "path": "src/library/platform/http/backend.ts",
    "content": "import {\n  HttpBackend,\n  HttpContextToken,\n  HttpDownloadProgressEvent,\n  HttpErrorResponse,\n  HttpEvent,\n  HttpEventType,\n  HttpHeaderResponse,\n  HttpHeaders,\n  HttpRequest,\n  HttpResponse,\n  HttpUploadProgressEvent,\n} from 'angular-miniprogram/common/http';\nimport { MiniProgramCore } from 'angular-miniprogram/platform/wx';\nimport { Observable, Observer } from 'rxjs';\nimport {\n  MiniProgramHttpDownloadResponse,\n  MiniProgramHttpResponse,\n} from './response';\ndeclare const Zone: any;\n/** Use this token to pass additional `wx.uploadFile()` parameter */\nexport const UPLOAD_FILE_TOKEN = new HttpContextToken<{\n  filePath?: string;\n  name?: string;\n  timeout?: number;\n}>(() => ({}));\n\n/** Use this token to pass additional `wx.downloadFile()` parameter */\nexport const DOWNLOAD_FILE_TOKEN = new HttpContextToken<{\n  filePath?: string;\n  timeout?: number;\n}>(() => ({}));\n\n/** Use this token to pass additional `wx.request()` parameter */\nexport const REQUSET_TOKEN = new HttpContextToken<{\n  enableCache?: boolean;\n  enableHttp2?: boolean;\n  enableQuic?: boolean;\n  timeout?: number;\n}>(() => ({}));\n\nexport class MiniprogramHttpBackend implements HttpBackend {\n  handle(request: HttpRequest<any>): Observable<HttpEvent<any>> {\n    if (\n      request.method === 'POST' &&\n      request.context.has(UPLOAD_FILE_TOKEN)\n    ) {\n      return this.upload(request);\n    }\n\n    if (\n      request.method === 'GET' &&\n      request.context.has(DOWNLOAD_FILE_TOKEN)\n    ) {\n      return this.download(request);\n    }\n\n    return this.request(request);\n  }\n\n  /**\n   * wx upload file\n   * @param request\n   */\n  private upload(request: HttpRequest<any>): Observable<HttpEvent<any>> {\n    return new Observable((observer: Observer<HttpEvent<any>>) => {\n      let currentZone = Zone.current;\n      // The response header event handler\n      const onHeadersReceived: WechatMiniprogram.DownloadTaskOnHeadersReceivedCallback = ({\n        header,\n      }) => {\n        currentZone.run(() => {\n          observer.next(\n            new HttpHeaderResponse({\n              url: request.url,\n              headers: new HttpHeaders(header),\n            })\n          );\n        });\n      };\n\n      // The upload progress event handler\n      const onUpProgressUpdate: WechatMiniprogram.UploadTaskOnProgressUpdateCallback =\n        ({ totalBytesSent, totalBytesExpectedToSend }) => {\n          currentZone.run(() => {\n            observer.next({\n              type: HttpEventType.UploadProgress,\n              loaded: totalBytesSent,\n              total: totalBytesExpectedToSend,\n            } as HttpUploadProgressEvent);\n          });\n        };\n\n      const { filePath, name, timeout } =\n        request.context.get(UPLOAD_FILE_TOKEN);\n      const task = MiniProgramCore.MINIPROGRAM_GLOBAL.uploadFile({\n        url: request.urlWithParams,\n        filePath: filePath!,\n        name: name!,\n        header: this.buildHeaders(request),\n        formData: request.body,\n        timeout: timeout,\n        success: ({ data, statusCode: status, errMsg: statusText }) => {\n          currentZone.run(() => {\n            let ok = status >= 200 && status < 300;\n            let body: any | null = null;\n\n            if (\n              request.responseType === 'json' &&\n              typeof data === 'string' &&\n              data !== ''\n            ) {\n              try {\n                body = JSON.parse(data);\n              } catch (error) {\n                if (ok) {\n                  ok = false;\n                  body = { error, text: body };\n                }\n              }\n            }\n\n            if (ok) {\n              observer.next(\n                new HttpResponse({\n                  url: request.url,\n                  body,\n                  status,\n                  statusText,\n                })\n              );\n              observer.complete();\n            } else {\n              observer.error(\n                new HttpErrorResponse({\n                  url: request.url,\n                  error: body,\n                  status,\n                  statusText,\n                })\n              );\n            }\n          });\n        },\n        fail: ({ errMsg }: WechatMiniprogram.GeneralCallbackResult) => {\n          currentZone.run(() => {\n            observer.error(\n              new HttpErrorResponse({\n                url: request.url,\n                statusText: errMsg,\n              })\n            );\n          });\n        },\n      });\n\n      observer.next({ type: HttpEventType.Sent });\n\n      if (request.reportProgress) {\n        task.onHeadersReceived(onHeadersReceived);\n        task.onProgressUpdate(onUpProgressUpdate);\n      }\n\n      return () => {\n        if (request.reportProgress) {\n          task.offHeadersReceived(onHeadersReceived);\n          task.offProgressUpdate(onUpProgressUpdate);\n        }\n\n        task.abort();\n      };\n    });\n  }\n\n  /**\n   * wx download file\n   * @param request\n   */\n  private download(request: HttpRequest<any>): Observable<HttpEvent<any>> {\n    return new Observable((observer: Observer<HttpEvent<any>>) => {\n      let currentZone = Zone.current;\n      // The response header event handler\n      const onHeadersReceived: WechatMiniprogram.DownloadTaskOnHeadersReceivedCallback = ({\n        header,\n      }) => {\n        currentZone.run(() => {\n          observer.next(\n            new HttpHeaderResponse({\n              url: request.url,\n              headers: new HttpHeaders(header),\n            })\n          );\n        });\n      };\n\n      // The download progress event handler\n      const onDownProgressUpdate: WechatMiniprogram.DownloadTaskOnProgressUpdateCallback =\n        ({ totalBytesWritten, totalBytesExpectedToWrite }) => {\n          currentZone.run(() => {\n            observer.next({\n              type: HttpEventType.DownloadProgress,\n              loaded: totalBytesWritten,\n              total: totalBytesExpectedToWrite,\n            } as HttpDownloadProgressEvent);\n          });\n        };\n\n      const { filePath, timeout } = request.context.get(DOWNLOAD_FILE_TOKEN);\n      const task = MiniProgramCore.MINIPROGRAM_GLOBAL.downloadFile({\n        url: request.urlWithParams,\n        filePath: filePath,\n        header: this.buildHeaders(request),\n        timeout: timeout,\n        success: ({\n          statusCode: status,\n          errMsg: statusText,\n          filePath,\n          tempFilePath,\n          profile,\n        }) => {\n          Zone.run(() => {\n            const ok = status >= 200 && status < 300;\n\n            if (ok) {\n              observer.next(\n                new MiniProgramHttpDownloadResponse({\n                  url: request.url,\n                  status,\n                  statusText,\n                  filePath,\n                  tempFilePath,\n                  profile,\n                })\n              );\n              observer.complete();\n            } else {\n              observer.error(\n                new HttpErrorResponse({\n                  url: request.url,\n                  status,\n                  statusText,\n                })\n              );\n            }\n          });\n        },\n        fail: ({ errMsg }: WechatMiniprogram.GeneralCallbackResult) => {\n          currentZone.run(() => {\n            observer.error(\n              new HttpErrorResponse({\n                url: request.url,\n                statusText: errMsg,\n              })\n            );\n          });\n        },\n      });\n\n      observer.next({ type: HttpEventType.Sent });\n\n      if (request.reportProgress) {\n        task.onHeadersReceived(onHeadersReceived);\n        task.onProgressUpdate(onDownProgressUpdate);\n      }\n\n      return () => {\n        if (request.reportProgress) {\n          task.offHeadersReceived(onHeadersReceived);\n          task.offProgressUpdate(onDownProgressUpdate);\n        }\n\n        task.abort();\n      };\n    });\n  }\n\n  /**\n   * wx http request\n   * @param request\n   */\n  private request(request: HttpRequest<any>): Observable<HttpEvent<any>> {\n    if (['PATCH', 'JSONP'].includes(request.method)) {\n      throw Error(\n        'WeChat MiniProgram does not support http method as ' + request.method\n      );\n    }\n    return new Observable((observer: Observer<HttpEvent<any>>) => {\n      let currentZone = Zone.current;\n      // The response header event handler\n      const onHeadersReceived: WechatMiniprogram.DownloadTaskOnHeadersReceivedCallback = ({\n        header,\n      }) => {\n        currentZone.run(() => {\n          observer.next(\n            new HttpHeaderResponse({\n              url: request.url,\n              headers: new HttpHeaders(header),\n            })\n          );\n        });\n      };\n      const task = MiniProgramCore.MINIPROGRAM_GLOBAL.request({\n        url: request.urlWithParams,\n        method: request.method as WechatMiniprogram.RequestOption['method'],\n        data: request.body,\n        header: this.buildHeaders(request),\n        // wx 从 responseType 中拆分出 dataType，这里需要处理一下\n        responseType:\n          request.responseType === 'arraybuffer'\n            ? request.responseType\n            : 'text',\n        dataType:\n          request.responseType === 'json' ? request.responseType : '其他',\n        success: ({\n          data,\n          header,\n          statusCode: status,\n          errMsg: statusText,\n          cookies,\n          profile,\n        }) => {\n          currentZone.run(() => {\n            const ok = status >= 200 && status < 300;\n            const headers = new HttpHeaders(header);\n\n            if (ok) {\n              observer.next(\n                new MiniProgramHttpResponse({\n                  url: request.url,\n                  body: data,\n                  status,\n                  statusText,\n                  headers,\n                  cookies,\n                  profile,\n                })\n              );\n              observer.complete();\n            } else {\n              observer.error(\n                new HttpErrorResponse({\n                  url: request.url,\n                  error: data,\n                  status,\n                  statusText,\n                  headers,\n                })\n              );\n            }\n          });\n        },\n        fail: ({ errMsg }: WechatMiniprogram.GeneralCallbackResult) => {\n          currentZone.run(() => {\n            observer.error(\n              new HttpErrorResponse({\n                url: request.url,\n                statusText: errMsg,\n              })\n            );\n          });\n        },\n        ...request.context.get(REQUSET_TOKEN),\n      });\n\n      observer.next({ type: HttpEventType.Sent });\n\n      if (request.reportProgress) {\n        task.onHeadersReceived(onHeadersReceived);\n      }\n\n      return () => {\n        if (request.reportProgress) {\n          task.offHeadersReceived(onHeadersReceived);\n        }\n\n        task.abort();\n      };\n    });\n  }\n\n  private buildHeaders(request: HttpRequest<any>): { [key: string]: string } {\n    return request.headers.keys().reduce((headers, name) => {\n      headers[name] = request.headers.getAll(name)!.join(',');\n      return headers;\n    }, {} as { [key: string]: string });\n  }\n}\n"
  },
  {
    "path": "src/library/platform/http/index.ts",
    "content": "export * from './backend';\nexport * from './module';\nexport * from './provider';\nexport * from './response';\n"
  },
  {
    "path": "src/library/platform/http/module.ts",
    "content": "import { NgModule } from '@angular/core';\nimport { withInterceptorsFromDi } from 'angular-miniprogram/common/http';\nimport { provideHttpClient } from './provider';\n\n@NgModule({\n  providers: [\n    provideHttpClient(withInterceptorsFromDi())\n  ]\n})\nexport class HttpClientModule { }\n"
  },
  {
    "path": "src/library/platform/http/provider.ts",
    "content": "import { EnvironmentProviders, makeEnvironmentProviders } from '@angular/core';\nimport { HttpBackend, HttpFeature, HttpFeatureKind, provideHttpClient as ngProvideHttpClient } from 'angular-miniprogram/common/http';\nimport { MiniprogramHttpBackend } from './backend';\n\nexport function provideHttpClient(...features: HttpFeature<HttpFeatureKind>[]): EnvironmentProviders {\n  return makeEnvironmentProviders([\n    ngProvideHttpClient(...features),\n    MiniprogramHttpBackend,\n    { provide: HttpBackend, useExisting: MiniprogramHttpBackend }\n  ]);\n}\n"
  },
  {
    "path": "src/library/platform/http/response.ts",
    "content": "import { HttpHeaders, HttpResponse } from 'angular-miniprogram/common/http';\n\nexport class MiniProgramHttpResponse<T> extends HttpResponse<T> {\n  /**\n   * 开发者服务器返回的 cookies，格式为字符串数组\n   */\n  readonly cookies: string[] | null;\n  /**\n   * 网络请求过程中一些调试信息，[查看详细说明](https://developers.weixin.qq.com/miniprogram/dev/framework/performance/network.html)\n   */\n  readonly profile: WechatMiniprogram.RequestProfile | null;\n\n  /**\n   * Construct a new `WxHttpResponse`.\n   */\n  constructor(\n    init: {\n      body?: T | null;\n      headers?: HttpHeaders;\n      status?: number;\n      statusText?: string;\n      url?: string;\n      cookies?: string[];\n      profile?: WechatMiniprogram.RequestProfile;\n    } = {}\n  ) {\n    super(init);\n    this.cookies = init.cookies ?? null;\n    this.profile = init.profile ?? null;\n  }\n\n  clone(): MiniProgramHttpResponse<T>;\n  clone(update: {\n    headers?: HttpHeaders;\n    status?: number;\n    statusText?: string;\n    url?: string;\n    cookies?: string[];\n    profile?: WechatMiniprogram.RequestProfile;\n  }): MiniProgramHttpResponse<T>;\n  clone<V>(update: {\n    body?: V | null;\n    headers?: HttpHeaders;\n    status?: number;\n    statusText?: string;\n    url?: string;\n    cookies?: string[];\n    profile?: WechatMiniprogram.RequestProfile;\n  }): MiniProgramHttpResponse<V>;\n  clone(\n    update: {\n      body?: any | null;\n      headers?: HttpHeaders;\n      status?: number;\n      statusText?: string;\n      url?: string;\n      cookies?: string[];\n      profile?: WechatMiniprogram.RequestProfile;\n    } = {}\n  ): MiniProgramHttpResponse<any> {\n    return new MiniProgramHttpResponse<any>({\n      body: update.body !== undefined ? update.body : this.body,\n      headers: update.headers || this.headers,\n      status: update.status !== undefined ? update.status : this.status,\n      statusText: update.statusText || this.statusText,\n      url: update.url || this.url || undefined,\n      cookies: update.cookies || this.cookies || undefined,\n      profile: update.profile || this.profile || undefined,\n    });\n  }\n}\n\nexport class MiniProgramHttpDownloadResponse<T> extends HttpResponse<T> {\n  /** 用户文件路径 (本地路径)。传入 filePath 时会返回，跟传入的 filePath 一致 */\n  readonly filePath: string | null;\n  /** 临时文件路径 (本地路径)。没传入 filePath 指定文件存储路径时会返回，下载后的文件会存储到一个临时文件 */\n  readonly tempFilePath: string | null;\n  /**\n   * 网络请求过程中一些调试信息，[查看详细说明](https://developers.weixin.qq.com/miniprogram/dev/framework/performance/network.html)\n   */\n  readonly profile: WechatMiniprogram.RequestProfile | null;\n\n  /**\n   * Construct a new `WxHttpDownloadResponse`.\n   */\n  constructor(\n    init: {\n      body?: T | null;\n      headers?: HttpHeaders;\n      status?: number;\n      statusText?: string;\n      url?: string;\n      filePath?: string;\n      tempFilePath?: string;\n      profile?: WechatMiniprogram.RequestProfile;\n    } = {}\n  ) {\n    super(init);\n    this.filePath = init.filePath ?? null;\n    this.tempFilePath = init.tempFilePath ?? null;\n    this.profile = init.profile ?? null;\n  }\n\n  clone(): MiniProgramHttpDownloadResponse<T>;\n  clone(update: {\n    headers?: HttpHeaders;\n    status?: number;\n    statusText?: string;\n    url?: string;\n    filePath?: string;\n    tempFilePath?: string;\n    profile?: WechatMiniprogram.RequestProfile;\n  }): MiniProgramHttpDownloadResponse<T>;\n  clone<V>(update: {\n    body?: V | null;\n    headers?: HttpHeaders;\n    status?: number;\n    statusText?: string;\n    url?: string;\n    filePath?: string;\n    tempFilePath?: string;\n    profile?: WechatMiniprogram.RequestProfile;\n  }): MiniProgramHttpDownloadResponse<V>;\n  clone(\n    update: {\n      body?: any | null;\n      headers?: HttpHeaders;\n      status?: number;\n      statusText?: string;\n      url?: string;\n      filePath?: string;\n      tempFilePath?: string;\n      profile?: WechatMiniprogram.RequestProfile;\n    } = {}\n  ): MiniProgramHttpDownloadResponse<any> {\n    return new MiniProgramHttpDownloadResponse<any>({\n      body: update.body !== undefined ? update.body : this.body,\n      headers: update.headers || this.headers,\n      status: update.status !== undefined ? update.status : this.status,\n      statusText: update.statusText || this.statusText,\n      url: update.url || this.url || undefined,\n      filePath: update.filePath || this.filePath || undefined,\n      tempFilePath: update.tempFilePath || this.tempFilePath || undefined,\n      profile: update.profile || this.profile || undefined,\n    });\n  }\n}\n"
  },
  {
    "path": "src/library/platform/index.ts",
    "content": "import { MiniProgramCore } from 'angular-miniprogram/platform/wx';\n\nexport * from './http';\nexport * from './mini-program.module';\nexport * from './platform-miniprogram';\nexport {\n  propertyChange,\n  ComponentFinderService,\n} from 'angular-miniprogram/platform/wx';\nexport const pageStartup = MiniProgramCore.pageStartup;\nexport const componentRegistry = MiniProgramCore.componentRegistry;\nexport * from './token';\nexport { PAGE_TOKEN } from 'angular-miniprogram/platform/wx';\n"
  },
  {
    "path": "src/library/platform/jd/index.ts",
    "content": "export * from './platform-core';\n"
  },
  {
    "path": "src/library/platform/jd/ng-package.json",
    "content": "{\n  \"$schema\": \"../../../node_modules/ng-packagr/ng-package.schema.json\",\n  \"lib\": {\n    \"entryFile\": \"./index.ts\"\n  }\n}\n"
  },
  {
    "path": "src/library/platform/jd/platform-core.ts",
    "content": "export * from 'angular-miniprogram/platform/default';\n"
  },
  {
    "path": "src/library/platform/mini-program.module.ts",
    "content": "import {\n  ApplicationModule,\n  ErrorHandler,\n  NgModule,\n  RendererFactory2,\n  ɵINJECTOR_SCOPE,\n} from '@angular/core';\nimport { CommonModule } from 'angular-miniprogram/common';\nimport {\n  ComponentFinderService,\n  MiniProgramRendererFactory,\n} from 'angular-miniprogram/platform/wx';\nimport { PageService } from './page.service';\n\nfunction errorHandler(): ErrorHandler {\n  return new ErrorHandler();\n}\n\n@NgModule({\n  declarations: [],\n  imports: [CommonModule, ApplicationModule],\n  providers: [\n    { provide: ɵINJECTOR_SCOPE, useValue: 'root' },\n    { provide: ErrorHandler, useFactory: errorHandler, deps: [] },\n    MiniProgramRendererFactory,\n    {\n      provide: RendererFactory2,\n      useExisting: MiniProgramRendererFactory,\n    },\n    PageService,\n    ComponentFinderService,\n  ],\n  exports: [CommonModule, ApplicationModule],\n})\nexport class MiniProgramModule {\n  constructor(pageService: PageService) {\n    pageService.register();\n  }\n}\n"
  },
  {
    "path": "src/library/platform/ng-package.json",
    "content": "{\n  \"$schema\": \"../../../node_modules/ng-packagr/ng-package.schema.json\",\n  \"lib\": {\n    \"entryFile\": \"./index.ts\"\n  }\n}\n"
  },
  {
    "path": "src/library/platform/page.service.ts",
    "content": "import {\n  ApplicationRef,\n  Inject,\n  Injectable,\n  Injector,\n  NgZone,\n  Type,\n  createNgModuleRef,\n} from '@angular/core';\nimport {\n  AppOptions,\n  MiniProgramComponentInstance,\n} from 'angular-miniprogram/platform/type';\nimport { PAGE_TOKEN } from 'angular-miniprogram/platform/wx';\nimport { APP_TOKEN } from './token';\n\n@Injectable()\nexport class PageService {\n  constructor(\n    private injector: Injector,\n    private applicationRef: ApplicationRef,\n    @Inject(APP_TOKEN) private app: AppOptions,\n    private ngZone: NgZone\n  ) {}\n\n  register() {\n    this.app.__ngStartPage = <M, C>(\n      module: Type<M>,\n      component: Type<C>,\n      miniProgramComponentInstance: MiniProgramComponentInstance\n    ) => {\n      return this.ngZone.run(() => {\n        const injector = Injector.create({\n          providers: [\n            { provide: PAGE_TOKEN, useValue: miniProgramComponentInstance },\n          ],\n          parent: this.injector,\n        });\n        const ngModuleRef = createNgModuleRef(module, injector);\n        const componentFactory =\n          ngModuleRef.componentFactoryResolver.resolveComponentFactory(\n            component\n          );\n        const componentRef = componentFactory.create(injector);\n        this.applicationRef.attachView(componentRef.hostView);\n        return { componentRef, ngModuleRef };\n      });\n    };\n    this.app.__ngStartPageResolve();\n  }\n}\n"
  },
  {
    "path": "src/library/platform/platform-miniprogram.ts",
    "content": "import {\n  StaticProvider,\n  createPlatformFactory,\n  platformCore,\n} from '@angular/core';\nimport { MiniProgramCore } from 'angular-miniprogram/platform/wx';\nimport { APP_TOKEN, MINIPROGRAM_GLOBAL_TOKEN } from './token';\n\nexport function platformMiniProgram<T>(\n  extraProviders: StaticProvider[] = [],\n  app?: T\n) {\n  return createPlatformFactory(platformCore, 'miniProgram', [\n    { provide: APP_TOKEN, useValue: MiniProgramCore.loadApp(app || {}) },\n    {\n      provide: MINIPROGRAM_GLOBAL_TOKEN,\n      useValue: MiniProgramCore.MINIPROGRAM_GLOBAL,\n    },\n  ])(extraProviders);\n}\n"
  },
  {
    "path": "src/library/platform/qq/index.ts",
    "content": "export * from './platform-core';\n"
  },
  {
    "path": "src/library/platform/qq/ng-package.json",
    "content": "{\n  \"$schema\": \"../../../node_modules/ng-packagr/ng-package.schema.json\",\n  \"lib\": {\n    \"entryFile\": \"./index.ts\"\n  }\n}\n"
  },
  {
    "path": "src/library/platform/qq/platform-core.ts",
    "content": "/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { MiniProgramCoreFactory as BaseFactory } from 'angular-miniprogram/platform/default';\n\ndeclare const getCurrentPages: Function;\nclass MiniProgramCoreFactory extends BaseFactory {}\nexport const MiniProgramCore = new MiniProgramCoreFactory();\n\nexport {\n  PAGE_TOKEN,\n  MiniProgramRenderer,\n  MiniProgramRendererFactory,\n  ComponentFinderService,\n  propertyChange,\n} from 'angular-miniprogram/platform/default';\n"
  },
  {
    "path": "src/library/platform/token.ts",
    "content": "import { InjectionToken } from '@angular/core';\n\nexport const APP_TOKEN = new InjectionToken<unknown>('APP_TOKEN');\nexport const MINIPROGRAM_GLOBAL_TOKEN = new InjectionToken<unknown>(\n  'MINIPROGRAM_GLOBAL_TOKEN'\n);\n"
  },
  {
    "path": "src/library/platform/type/index.ts",
    "content": "export * from './type';\nexport * from './internal-type';\n"
  },
  {
    "path": "src/library/platform/type/internal-type.ts",
    "content": "import type { ɵLContext } from '@angular/core';\n\nexport type LView = NonNullable<ɵLContext['lView']>;\n"
  },
  {
    "path": "src/library/platform/type/ng-package.json",
    "content": "{\n  \"$schema\": \"../../../node_modules/ng-packagr/ng-package.schema.json\",\n  \"lib\": {\n    \"entryFile\": \"./index.ts\"\n  }\n}\n"
  },
  {
    "path": "src/library/platform/type/type.ts",
    "content": "/* eslint-disable @typescript-eslint/no-explicit-any */\nimport type {\n  ComponentRef,\n  Injector,\n  NgModuleRef,\n  NgZone,\n  Type,\n  ViewRef,\n} from '@angular/core';\nimport type { LView } from './internal-type';\n\nexport interface AppOptions {\n  __ngStartPage<M, C>(\n    module: Type<M>,\n    component: Type<C>,\n    miniProgramComponentInstance: any\n  ): {\n    componentRef: ComponentRef<C>;\n    ngModuleRef: NgModuleRef<M>;\n  };\n  __ngStartPageResolve: Function;\n  __ngStartPagePromise: Promise<void>;\n}\n\nexport interface MiniProgramComponentVariable<NG_COMPONENT_INSTANCE = unknown> {\n  /** @public */\n  __ngComponentInstance: NG_COMPONENT_INSTANCE;\n  /** page使用 */\n  __ngComponentHostView: ViewRef;\n  __ngComponentInjector: Injector;\n  __ngZone: NgZone;\n  /** 小程序组件是否与lview链接成功 */\n  __isLink: boolean;\n  __lView: LView;\n  __nodePath: NodePath;\n  __nodeIndex: number;\n  __isDetachView: boolean;\n  __completePath: NodePath;\n  /** @public 等待链接完成,用于Component组件的created周期使用等待,其他的直接使用__ngComponentInstance获得实例 */\n  __waitLinkPromise: Promise<void>;\n  /** @private */\n  __waitLinkResolve: () => void;\n  /** @private */\n  __lifeTimePromiseObject: Record<\n    'onLoad' | 'onShow' | 'created',\n    Promise<void>\n  >;\n}\nexport interface MiniProgramComponentMethod {\n  __ngDestroy: () => void;\n}\n\nexport interface MPView {\n  nodeList: (MPView[] | MPElementData | MPTextData)[];\n  __templateName: string | undefined;\n  nodePath: NodePath;\n  index: number;\n  hasLoad?: boolean;\n}\nexport interface MPElementData {\n  class: string;\n  style: string;\n  property: Record<string, any>;\n}\n\nexport interface MPTextData {\n  value: string;\n}\n\nexport type NodePath = ('directive' | number)[];\nexport interface MiniProgramComponentBuiltIn {\n  getPageId(): string;\n  setData(data: Partial<Record<string, any>>): void;\n}\nexport type MiniProgramComponentInstance<NG_COMPONENT_INSTANCE = unknown> =\n  MiniProgramComponentVariable<NG_COMPONENT_INSTANCE> &\n    MiniProgramComponentMethod &\n    MiniProgramComponentBuiltIn &\n    MiniProgramPageOptions &\n    MiniProgramComponentOptions;\n\nexport interface MiniProgramPageOptions {\n  mpPageOptions?: any;\n}\nexport interface MiniProgramComponentOptions {\n  mpComponentOptions?: any;\n}\n"
  },
  {
    "path": "src/library/platform/wx/index.ts",
    "content": "export * from 'angular-miniprogram/platform/default'"
  },
  {
    "path": "src/library/platform/wx/ng-package.json",
    "content": "{\n  \"$schema\": \"../../../node_modules/ng-packagr/ng-package.schema.json\",\n  \"lib\": {\n    \"entryFile\": \"./index.ts\"\n  }\n}\n"
  },
  {
    "path": "src/library/platform/zfb/index.ts",
    "content": "export * from './platform-core';\n"
  },
  {
    "path": "src/library/platform/zfb/ng-package.json",
    "content": "{\n  \"$schema\": \"../../../node_modules/ng-packagr/ng-package.schema.json\",\n  \"lib\": {\n    \"entryFile\": \"./index.ts\"\n  }\n}\n"
  },
  {
    "path": "src/library/platform/zfb/platform-core.ts",
    "content": "/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { MiniProgramCoreFactory as BaseFactory } from 'angular-miniprogram/platform/default';\nimport type {\n  MiniProgramComponentInstance,\n  NodePath,\n} from 'angular-miniprogram/platform/type';\n\nclass MiniProgramCoreFactory extends BaseFactory {\n  override eventPrefixList = [\n    { listener: 'on', prefix: 'on' },\n    { listener: 'catch', prefix: 'catch' },\n  ];\n  override getListenerEventMapping(prefix: string, name: string) {\n    const upperName = name[0].toLocaleUpperCase() + name.substr(1);\n    const isOn = prefix === 'on';\n    return [\n      name,\n      prefix + name,\n      prefix + upperName,\n      ...(isOn\n        ? [\n            'mut-bind' + name,\n            'capture-bind' + name,\n            'bind' + name,\n            'mut-bind' + upperName,\n            'capture-bind' + upperName,\n            'bind' + upperName,\n          ]\n        : ['capture-catch' + name, 'capture-catch' + upperName]),\n    ];\n  }\n  override addNgComponentLinkLogic(config: any) {\n    const _this = this;\n    config.props = {\n      nodePath: undefined,\n      nodeIndex: undefined,\n    };\n    let addWait = false;\n    const oldOnInit = config.onInit;\n    config.onInit = function (\n      this: Record<string, any> & MiniProgramComponentInstance\n    ) {\n      let resolveFunction!: () => void;\n      this.__waitLinkPromise = new Promise<void>(\n        (resolve) => (resolveFunction = resolve)\n      );\n      this.__waitLinkResolve = resolveFunction;\n      addWait = true;\n      if (oldOnInit) {\n        oldOnInit.bind(this)();\n      }\n    };\n    const oldDidMount = config.didMount;\n    config.didMount = function (\n      this: Record<string, any> & MiniProgramComponentInstance\n    ) {\n      if (!addWait) {\n        addWait = true;\n        let resolveFunction!: () => void;\n        this.__waitLinkPromise = new Promise<void>(\n          (resolve) => (resolveFunction = resolve)\n        );\n        this.__waitLinkResolve = resolveFunction;\n      }\n      const nodePath: NodePath = (this.props.nodePath || []).map(\n        (item: string) => (item === 'directive' ? item : parseInt(item, 10))\n      );\n      const nodeIndex = parseInt(this.props.nodeIndex, 10);\n      if (this.__isLink) {\n        return;\n      }\n      this.__completePath = [...nodePath, nodeIndex];\n      _this.linkNgComponentWithPath(this, this.__completePath);\n      if (oldDidMount) {\n        oldDidMount.bind(this)();\n      }\n    };\n    return config;\n  }\n}\nexport const MiniProgramCore = new MiniProgramCoreFactory();\nexport {\n  PAGE_TOKEN,\n  MiniProgramRenderer,\n  MiniProgramRendererFactory,\n  ComponentFinderService,\n  propertyChange,\n} from 'angular-miniprogram/platform/default';\n"
  },
  {
    "path": "src/library/platform/zjtd/index.ts",
    "content": "export * from './platform-core';\n"
  },
  {
    "path": "src/library/platform/zjtd/ng-package.json",
    "content": "{\n  \"$schema\": \"../../../node_modules/ng-packagr/ng-package.schema.json\",\n  \"lib\": {\n    \"entryFile\": \"./index.ts\"\n  }\n}\n"
  },
  {
    "path": "src/library/platform/zjtd/platform-core.ts",
    "content": "export * from 'angular-miniprogram/platform/default';\n"
  },
  {
    "path": "test/hello-world-app/.browserslistrc",
    "content": "# This file is used by the build system to adjust CSS and JS output to support the specified browsers below.\n# For additional information regarding the format and rule options, please see:\n# https://github.com/browserslist/browserslist#queries\n\n# For the full list of supported browsers by the Angular framework, please see:\n# https://angular.io/guide/browser-support\n\n# You can see what browsers were selected by your queries by running:\n#   npx browserslist\n\nlast 1 Chrome version\nlast 1 Firefox version\nlast 2 Edge major versions\nlast 2 Safari major versions\nlast 2 iOS major versions\nFirefox ESR"
  },
  {
    "path": "test/hello-world-app/.gitignore",
    "content": "# Don't ignore node_modules, this project is not meant to be installed.\n# Also, ~ import path in styles does only looks in the first node_modules found.\n# /node_modules\n"
  },
  {
    "path": "test/hello-world-app/angular.json",
    "content": "{\n  \"$schema\": \"\",\n  \"version\": 1,\n  \"newProjectRoot\": \"./projects\",\n  \"cli\": {},\n  \"schematics\": {},\n  \"targets\": {},\n  \"projects\": {\n    \"app\": {\n      \"root\": \"src\",\n      \"sourceRoot\": \"src\",\n      \"projectType\": \"application\",\n      \"prefix\": \"app\",\n      \"schematics\": {},\n      \"targets\": {\n        \"build\": {\n          \"builder\": \"@angular-devkit/build-angular:browser\",\n          \"options\": {\n            \"outputPath\": \"dist\",\n            \"index\": \"src/index.html\",\n            \"main\": \"src/main.ts\",\n            \"polyfills\": \"src/polyfills.ts\",\n            \"tsConfig\": \"src/tsconfig.app.json\",\n            \"progress\": false,\n            \"assets\": [\"src/favicon.ico\", \"src/assets\"],\n            \"styles\": [\"src/styles.css\"],\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            \"inline-critical-css\": {\n              \"optimization\": {\n                \"styles\": {\n                  \"minify\": true,\n                  \"inlineCritical\": true\n                },\n                \"scripts\": true,\n                \"fonts\": true\n              }\n            }\n          }\n        },\n        \"server\": {\n          \"builder\": \"@angular-devkit/build-angular:server\",\n          \"options\": {\n            \"outputPath\": \"dist-server\",\n            \"main\": \"src/main.server.ts\",\n            \"tsConfig\": \"src/tsconfig.server.json\",\n            \"progress\": false\n          }\n        },\n        \"app-shell\": {\n          \"builder\": \"@angular-devkit/build-angular:app-shell\",\n          \"options\": {\n            \"browserTarget\": \"app:build\",\n            \"serverTarget\": \"app:server\"\n          },\n          \"configurations\": {\n            \"production\": {\n              \"browserTarget\": \"app:build:production\"\n            }\n          }\n        },\n        \"serve\": {\n          \"builder\": \"@angular-devkit/build-angular:dev-server\",\n          \"options\": {\n            \"browserTarget\": \"app:build\",\n            \"watch\": false\n          },\n          \"configurations\": {\n            \"production\": {\n              \"browserTarget\": \"app:build:production\"\n            }\n          }\n        },\n        \"extract-i18n\": {\n          \"builder\": \"@angular-devkit/build-angular:extract-i18n\",\n          \"options\": {\n            \"browserTarget\": \"app:build\",\n            \"progress\": false,\n            \"outputPath\": \"src\"\n          }\n        },\n        \"test\": {\n          \"builder\": \"@angular-devkit/build-angular:karma\",\n          \"options\": {\n            \"main\": \"src/test.ts\",\n            \"polyfills\": \"src/polyfills.ts\",\n            \"tsConfig\": \"src/tsconfig.spec.json\",\n            \"karmaConfig\": \"karma.conf.js\",\n            \"browsers\": \"ChromeHeadlessCI\",\n            \"progress\": false,\n            \"watch\": false,\n            \"styles\": [\n              {\n                \"input\": \"src/styles.css\"\n              }\n            ],\n            \"scripts\": [],\n            \"assets\": [\"src/favicon.ico\", \"src/assets\"]\n          }\n        },\n        \"lint\": {\n          \"builder\": \"@angular-devkit/build-angular:tslint\",\n          \"options\": {\n            \"tsConfig\": [\"src/tsconfig.app.json\", \"src/tsconfig.spec.json\"],\n            \"exclude\": [\"**/node_modules/**\"]\n          }\n        },\n        \"lint-test\": {\n          \"builder\": \"@angular-devkit/build-angular:tslint\",\n          \"options\": {\n            \"tsConfig\": \"src/tsconfig.spec.json\",\n            \"exclude\": [\"**/node_modules/**\"]\n          }\n        }\n      }\n    },\n    \"test-library\": {\n      \"projectType\": \"library\",\n      \"root\": \"projects/test-library\",\n      \"sourceRoot\": \"projects/test-library/src\",\n      \"prefix\": \"lib\",\n      \"architect\": {\n        \"build\": {\n          \"builder\": \"@angular-devkit/build-angular:ng-packagr\",\n          \"options\": {\n            \"project\": \"projects/test-library/ng-package.json\"\n          },\n          \"configurations\": {\n            \"production\": {\n              \"tsConfig\": \"projects/test-library/tsconfig.lib.prod.json\"\n            },\n            \"development\": {\n              \"tsConfig\": \"projects/test-library/tsconfig.lib.json\"\n            }\n          },\n          \"defaultConfiguration\": \"production\"\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "test/hello-world-app/karma.conf.js",
    "content": "// Karma configuration file, see link for more information\n// https://karma-runner.github.io/1.0/config/configuration-file.html\n\nmodule.exports = function (config) {\n  config.set({\n    basePath: '',\n    frameworks: ['@angular-devkit/build-angular'],\n    plugins: [\n      // require('karma-coverage'),\n      require('../../src/builder/karma/plugin/index'),\n    ],\n    client: {\n      jasmine: {\n        // you can add configuration options for Jasmine here\n        // the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html\n        // for example, you can disable the random execution with `random: false`\n        // or set a specific seed with `seed: 4321`\n      },\n      clearContext: false, // leave Jasmine Spec Runner output visible in browser\n    },\n    jasmineHtmlReporter: {\n      suppressAll: true, // removes the duplicated traces\n    },\n    coverageReporter: {\n      dir: require('path').join(__dirname, './coverage/ng13-demo'),\n      subdir: '.',\n      reporters: [{ type: 'html' }, { type: 'text-summary' }],\n    },\n    reporters: ['progress'],\n    port: 9876,\n    colors: true,\n    logLevel: config.LOG_INFO,\n    autoWatch: true,\n    browsers: ['miniprogram'],\n    singleRun: false,\n    restartOnFileChange: true,\n    captureTimeout: 300_000,\n  });\n};\n"
  },
  {
    "path": "test/hello-world-app/projects/test-library/.browserslistrc",
    "content": "# This file is used by the build system to adjust CSS and JS output to support the specified browsers below.\n# For additional information regarding the format and rule options, please see:\n# https://github.com/browserslist/browserslist#queries\n\n# For the full list of supported browsers by the Angular framework, please see:\n# https://angular.io/guide/browser-support\n\n# You can see what browsers were selected by your queries by running:\n#   npx browserslist\n\nlast 1 Chrome version\nlast 1 Firefox version\nlast 2 Edge major versions\nlast 2 Safari major versions\nlast 2 iOS major versions\nFirefox ESR\n"
  },
  {
    "path": "test/hello-world-app/projects/test-library/ng-package.json",
    "content": "{\n  \"$schema\": \"../../node_modules/ng-packagr/ng-package.schema.json\",\n  \"dest\": \"../../dist/test-library\",\n  \"lib\": {\n    \"entryFile\": \"src/public-api.ts\"\n  }\n}\n"
  },
  {
    "path": "test/hello-world-app/projects/test-library/package.json",
    "content": "{\n  \"name\": \"test-library\",\n  \"version\": \"0.0.1\",\n  \"peerDependencies\": {\n    \"@angular/core\": \"^13.0.0\"\n  },\n  \"dependencies\": {\n    \"tslib\": \"^2.3.0\"\n  }\n}\n"
  },
  {
    "path": "test/hello-world-app/projects/test-library/src/directive/directive.module.ts",
    "content": "import { NgModule } from '@angular/core';\nimport { InputOutputDirective } from './input-output.directive';\n\n@NgModule({\n  declarations: [InputOutputDirective],\n  imports: [],\n  exports: [InputOutputDirective],\n  providers: [],\n})\nexport class DirectiveModule {}\n"
  },
  {
    "path": "test/hello-world-app/projects/test-library/src/directive/input-output.directive.ts",
    "content": "import { Directive, EventEmitter, Input, Output } from '@angular/core';\n\n@Directive({\n  selector: '[libInputOutput]',\n})\nexport class InputOutputDirective {\n  @Input() input1: string;\n  @Input() input2: number;\n  @Output() output1 = new EventEmitter();\n  @Output() output2 = new EventEmitter();\n}\n"
  },
  {
    "path": "test/hello-world-app/projects/test-library/src/global-self-template/global-self-template.component.css",
    "content": ""
  },
  {
    "path": "test/hello-world-app/projects/test-library/src/global-self-template/global-self-template.component.html",
    "content": "<app-outside-template\n  [template]=\"$$mp$$__self__$$libraryFirst\"\n></app-outside-template>\n<ng-template #$$mp$$__self__$$libraryFirst>\n  library内模板\n  <app-other></app-other>\n</ng-template>\n"
  },
  {
    "path": "test/hello-world-app/projects/test-library/src/global-self-template/global-self-template.component.ts",
    "content": "import { Component, OnInit } from '@angular/core';\n\n@Component({\n  selector: 'app-global-self-template',\n  templateUrl: './global-self-template.component.html',\n  styleUrls: ['./global-self-template.component.css'],\n})\nexport class GlobalSelfTemplateComponent implements OnInit {\n  constructor() {}\n\n  ngOnInit() {}\n}\n"
  },
  {
    "path": "test/hello-world-app/projects/test-library/src/global-self-template/global-self-template.module.ts",
    "content": "import { NgModule } from '@angular/core';\nimport { GlobalSelfTemplateComponent } from './global-self-template.component';\nimport { OutsideTemplateModule } from '../outside-template/outside-template.module';\nimport { OtherModule } from '../other/other.module';\n\n@NgModule({\n  imports: [OutsideTemplateModule, OtherModule],\n  declarations: [GlobalSelfTemplateComponent],\n  exports: [GlobalSelfTemplateComponent],\n})\nexport class GlobalSelfTemplateModule {}\n"
  },
  {
    "path": "test/hello-world-app/projects/test-library/src/lib/test-library.component.scss",
    "content": "body {\n  background-color: red;\n}\n"
  },
  {
    "path": "test/hello-world-app/projects/test-library/src/lib/test-library.component.spec.ts",
    "content": "import { ComponentFixture, TestBed } from '@angular/core/testing';\n\nimport { TestLibraryComponent } from './test-library.component';\n\ndescribe('TestLibraryComponent', () => {\n  let component: TestLibraryComponent;\n  let fixture: ComponentFixture<TestLibraryComponent>;\n\n  beforeEach(async () => {\n    await TestBed.configureTestingModule({\n      declarations: [TestLibraryComponent],\n    }).compileComponents();\n  });\n\n  beforeEach(() => {\n    fixture = TestBed.createComponent(TestLibraryComponent);\n    component = fixture.componentInstance;\n    fixture.detectChanges();\n  });\n\n  it('should create', () => {\n    expect(component).toBeTruthy();\n  });\n});\n"
  },
  {
    "path": "test/hello-world-app/projects/test-library/src/lib/test-library.component.ts",
    "content": "import { Component, HostBinding, Input, OnInit } from '@angular/core';\n\n@Component({\n  selector: 'lib-test-library',\n  template: ``,\n  styleUrls: ['./test-library.component.scss'],\n})\nexport class TestLibraryComponent implements OnInit {\n  @Input() input1;\n  @HostBinding('property1') property1;\n\n  constructor() {}\n\n  ngOnInit(): void {}\n}\n"
  },
  {
    "path": "test/hello-world-app/projects/test-library/src/lib/test-library.directive.ts",
    "content": "import { Directive, HostBinding, HostListener, Output } from '@angular/core';\n\n@Directive({\n  selector: '[libTestLibrary]',\n  host: {\n    '(tap)': 'hostTap($event)',\n  },\n})\nexport class TestLibraryDirective {\n  @HostListener('touchstart', ['$event']) methodDecoratorTouchstart(event) {\n    console.log('HostListener-touchstart', event);\n  }\n  @HostBinding('value') value;\n  constructor() {\n    setTimeout(() => {\n      this.value = 'sdfsdf';\n      console.log('数据更改');\n    }, 3000);\n  }\n  hostTap(event) {\n    console.log('tap', event);\n  }\n}\n"
  },
  {
    "path": "test/hello-world-app/projects/test-library/src/lib/test-library.module.ts",
    "content": "import { NgModule } from '@angular/core';\nimport { OtherModule } from '../other/other.module';\nimport { TestLibraryComponent } from './test-library.component';\nimport { TestLibraryDirective } from './test-library.directive';\n\n@NgModule({\n  declarations: [TestLibraryComponent, TestLibraryDirective],\n  imports: [OtherModule],\n  exports: [TestLibraryComponent, TestLibraryDirective],\n})\nexport class TestLibraryModule {}\n"
  },
  {
    "path": "test/hello-world-app/projects/test-library/src/lib/test-library.service.spec.ts",
    "content": "import { TestBed } from '@angular/core/testing';\n\nimport { TestLibraryService } from './test-library.service';\n\ndescribe('TestLibraryService', () => {\n  let service: TestLibraryService;\n\n  beforeEach(() => {\n    TestBed.configureTestingModule({});\n    service = TestBed.inject(TestLibraryService);\n  });\n\n  it('should be created', () => {\n    expect(service).toBeTruthy();\n  });\n});\n"
  },
  {
    "path": "test/hello-world-app/projects/test-library/src/lib/test-library.service.ts",
    "content": "import { Injectable } from '@angular/core';\n\n@Injectable({\n  providedIn: 'root',\n})\nexport class TestLibraryService {\n  constructor() {}\n}\n"
  },
  {
    "path": "test/hello-world-app/projects/test-library/src/lib-comp1/lib-comp1.component.css",
    "content": ""
  },
  {
    "path": "test/hello-world-app/projects/test-library/src/lib-comp1/lib-comp1.component.html",
    "content": "<p class=\"lib-comp1-content\">lib-comp1 works!</p>\n"
  },
  {
    "path": "test/hello-world-app/projects/test-library/src/lib-comp1/lib-comp1.component.ts",
    "content": "import { Component, HostListener, OnInit } from '@angular/core';\n\n@Component({\n  selector: 'app-lib-comp1',\n  templateUrl: './lib-comp1.component.html',\n  styleUrls: ['./lib-comp1.component.css'],\n})\nexport class LibComp1Component implements OnInit {\n  @HostListener('tap', ['$event']) tap1(event) {\n    console.log('library组件的tap事件', event);\n  }\n  @HostListener('bindtap', ['$event']) tap2(event) {\n    console.log('library组件的(bind)tap事件', event);\n  }\n  constructor() {}\n\n  ngOnInit() {}\n}\n"
  },
  {
    "path": "test/hello-world-app/projects/test-library/src/lib-comp1/lib-comp1.module.ts",
    "content": "import { NgModule } from '@angular/core';\nimport { CommonModule } from 'angular-miniprogram/common';\nimport { LibComp1Component } from './lib-comp1.component';\nimport { LibDir1Directive } from './lib-dir1.directive';\n\n@NgModule({\n  imports: [CommonModule],\n  declarations: [LibComp1Component, LibDir1Directive],\n  exports: [LibComp1Component, LibDir1Directive],\n})\nexport class LibComp1Module {}\n"
  },
  {
    "path": "test/hello-world-app/projects/test-library/src/lib-comp1/lib-dir1.directive.ts",
    "content": "import { Directive, HostListener } from '@angular/core';\n\n@Directive({\n  selector: '[appLibDir1]',\n})\nexport class LibDir1Directive {\n  @HostListener('tap', ['$event']) tap1(event) {\n    console.log('library指令的tap事件', event);\n  }\n  @HostListener('bindtap', ['$event']) tap2(event) {\n    console.log('library指令的(bind)tap事件', event);\n  }\n  constructor() {}\n}\n"
  },
  {
    "path": "test/hello-world-app/projects/test-library/src/other/other.component.css",
    "content": ""
  },
  {
    "path": "test/hello-world-app/projects/test-library/src/other/other.component.html",
    "content": "<p (tap)=\"click()\">other works!</p>\n"
  },
  {
    "path": "test/hello-world-app/projects/test-library/src/other/other.component.ts",
    "content": "import { Component, OnInit } from '@angular/core';\n\n@Component({\n  selector: 'app-other',\n  templateUrl: './other.component.html',\n  styleUrls: ['./other.component.css'],\n})\nexport class OtherComponent implements OnInit {\n  constructor() {}\n\n  ngOnInit() {}\n  click() {\n    console.log('other被点击');\n  }\n}\n"
  },
  {
    "path": "test/hello-world-app/projects/test-library/src/other/other.module.ts",
    "content": "import { NgModule } from '@angular/core';\nimport { OtherComponent } from './other.component';\n\n@NgModule({\n  imports: [],\n  declarations: [OtherComponent],\n  exports: [OtherComponent],\n})\nexport class OtherModule {}\n"
  },
  {
    "path": "test/hello-world-app/projects/test-library/src/outside-template/outside-template.component.css",
    "content": ""
  },
  {
    "path": "test/hello-world-app/projects/test-library/src/outside-template/outside-template.component.html",
    "content": "<div>下面将传入一个由外部提供的模板</div>\n<div *ngIf=\"template\">\n  <ng-container *ngTemplateOutlet=\"template\"></ng-container>\n</div>\n"
  },
  {
    "path": "test/hello-world-app/projects/test-library/src/outside-template/outside-template.component.ts",
    "content": "import { Component, Input, OnInit, TemplateRef } from '@angular/core';\n\n@Component({\n  selector: 'app-outside-template',\n  templateUrl: './outside-template.component.html',\n  styleUrls: ['./outside-template.component.css'],\n})\nexport class OutsideTemplateComponent implements OnInit {\n  @Input() template: TemplateRef<any>;\n  constructor() {}\n\n  ngOnInit() {}\n}\n"
  },
  {
    "path": "test/hello-world-app/projects/test-library/src/outside-template/outside-template.module.ts",
    "content": "import { NgModule } from '@angular/core';\nimport { CommonModule } from 'angular-miniprogram/common';\nimport { OutsideTemplateComponent } from './outside-template.component';\n\n@NgModule({\n  imports: [CommonModule],\n  declarations: [OutsideTemplateComponent],\n  exports: [OutsideTemplateComponent],\n})\nexport class OutsideTemplateModule {}\n"
  },
  {
    "path": "test/hello-world-app/projects/test-library/src/public-api.ts",
    "content": "/*\n * Public API Surface of test-library\n */\n\nexport * from './lib/test-library.service';\nexport * from './lib/test-library.component';\nexport * from './lib/test-library.module';\nexport * from './lib/test-library.directive';\nexport * from './other/other.component';\nexport * from './lib-comp1/lib-comp1.module';\nexport * from './lib-comp1/lib-comp1.component';\nexport * from './lib-comp1/lib-dir1.directive';\nexport * from './directive/directive.module';\nexport * from './directive/input-output.directive';\nexport * from './other/other.module';\nexport * from './outside-template/outside-template.module';\nexport * from './outside-template/outside-template.component';\nexport * from './global-self-template/global-self-template.module';\nexport * from './global-self-template/global-self-template.component';\n"
  },
  {
    "path": "test/hello-world-app/projects/test-library/tsconfig.lib.json",
    "content": "/* To learn more about this file see: https://angular.io/config/tsconfig. */\n{\n  \"extends\": \"../../tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"../../out-tsc/lib\",\n    \"declaration\": true,\n    \"declarationMap\": true,\n    \"inlineSources\": true,\n    \"types\": [],\n    \"target\": \"es2022\"\n  },\n  \"exclude\": [\"src/test.ts\", \"**/*.spec.ts\"]\n}\n"
  },
  {
    "path": "test/hello-world-app/projects/test-library/tsconfig.lib.prod.json",
    "content": "/* To learn more about this file see: https://angular.io/config/tsconfig. */\n{\n  \"extends\": \"./tsconfig.lib.json\",\n  \"compilerOptions\": {\n    \"declarationMap\": false\n  },\n  \"angularCompilerOptions\": {\n    \"compilationMode\": \"full\"\n  }\n}\n"
  },
  {
    "path": "test/hello-world-app/projects/test-library/tsconfig.spec.json",
    "content": "/* To learn more about this file see: https://angular.io/config/tsconfig. */\n{\n  \"extends\": \"../../tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"../../out-tsc/spec\",\n    \"types\": [\"jasmine\"]\n  },\n  \"files\": [\"src/test.ts\"],\n  \"include\": [\"**/*.spec.ts\", \"**/*.d.ts\"]\n}\n"
  },
  {
    "path": "test/hello-world-app/src/__components/component-need-template/component-need-template.component.css",
    "content": ""
  },
  {
    "path": "test/hello-world-app/src/__components/component-need-template/component-need-template.component.html",
    "content": "ngTemplateOutlet插入\n<ng-container *ngTemplateOutlet=\"templateRef\"></ng-container>\nngIf 插入\n<div *ngIf=\"templateRef; then templateRef\"></div>\n"
  },
  {
    "path": "test/hello-world-app/src/__components/component-need-template/component-need-template.component.ts",
    "content": "import { Component, Input, OnInit, TemplateRef } from '@angular/core';\n\n@Component({\n  selector: 'app-component-need-template',\n  templateUrl: './component-need-template.component.html',\n  styleUrls: ['./component-need-template.component.css'],\n})\nexport class ComponentNeedTemplateComponent implements OnInit {\n  @Input() templateRef: TemplateRef<any>;\n  constructor() {}\n\n  ngOnInit() {}\n}\n"
  },
  {
    "path": "test/hello-world-app/src/__components/component-need-template/component-need-template.entry.ts",
    "content": "import { componentRegistry } from 'angular-miniprogram';\nimport { ComponentNeedTemplateComponent } from './component-need-template.component';\n\ncomponentRegistry(ComponentNeedTemplateComponent);\n"
  },
  {
    "path": "test/hello-world-app/src/__components/component-need-template/component-need-template.module.ts",
    "content": "import { NgModule } from '@angular/core';\nimport { CommonModule } from 'angular-miniprogram/common';\nimport { ComponentNeedTemplateComponent } from './component-need-template.component';\n\n@NgModule({\n  imports: [CommonModule],\n  declarations: [ComponentNeedTemplateComponent],\n  exports: [ComponentNeedTemplateComponent],\n})\nexport class ComponentNeedTemplateModule {}\n"
  },
  {
    "path": "test/hello-world-app/src/__components/component1/component1.component.css",
    "content": ""
  },
  {
    "path": "test/hello-world-app/src/__components/component1/component1.component.html",
    "content": "<div>显示传入input1:{{ input1 }}</div>\n"
  },
  {
    "path": "test/hello-world-app/src/__components/component1/component1.component.ts",
    "content": "import { Component, Input, OnInit } from '@angular/core';\n\n@Component({\n  selector: 'app-component1',\n  templateUrl: './component1.component.html',\n  styleUrls: ['./component1.component.css'],\n})\nexport class Component1Component implements OnInit {\n  @Input() input1 = '';\n  constructor() {}\n\n  ngOnInit() {}\n}\n"
  },
  {
    "path": "test/hello-world-app/src/__components/component1/component1.entry.ts",
    "content": "import { componentRegistry } from 'angular-miniprogram';\nimport { Component1Component } from './component1.component';\n\ncomponentRegistry(Component1Component);\n"
  },
  {
    "path": "test/hello-world-app/src/__components/component1/component1.module.ts",
    "content": "import { NgModule } from '@angular/core';\nimport { CommonModule } from 'angular-miniprogram/common';\nimport { Component1Component } from './component1.component';\n\n@NgModule({\n  imports: [CommonModule],\n  declarations: [Component1Component],\n  exports: [Component1Component],\n})\nexport class Component1Module {}\n"
  },
  {
    "path": "test/hello-world-app/src/__components/component2/component2.component.css",
    "content": ""
  },
  {
    "path": "test/hello-world-app/src/__components/component2/component2.component.html",
    "content": "<app-component1 [input1]=\"cp2Input1\"></app-component1>\n"
  },
  {
    "path": "test/hello-world-app/src/__components/component2/component2.component.ts",
    "content": "import { Component, Input, OnInit } from '@angular/core';\n\n@Component({\n  selector: 'app-component2',\n  templateUrl: './component2.component.html',\n  styleUrls: ['./component2.component.css'],\n})\nexport class Component2Component implements OnInit {\n  @Input() cp2Input1 = '';\n  constructor() {}\n\n  ngOnInit() {}\n}\n"
  },
  {
    "path": "test/hello-world-app/src/__components/component2/component2.entry.ts",
    "content": "import { componentRegistry } from 'angular-miniprogram';\nimport { Component2Component } from './component2.component';\n\ncomponentRegistry(Component2Component);\n"
  },
  {
    "path": "test/hello-world-app/src/__components/component2/component2.module.ts",
    "content": "import { NgModule } from '@angular/core';\nimport { CommonModule } from 'angular-miniprogram/common';\nimport { Component2Component } from './component2.component';\nimport { Component1Module } from '../component1/component1.module';\n\n@NgModule({\n  imports: [CommonModule, Component1Module],\n  declarations: [Component2Component],\n  exports: [Component2Component],\n})\nexport class Component2Module {}\n"
  },
  {
    "path": "test/hello-world-app/src/__components/component3/component3.component.css",
    "content": ""
  },
  {
    "path": "test/hello-world-app/src/__components/component3/component3.component.html",
    "content": "<p>component3 works!</p>\n"
  },
  {
    "path": "test/hello-world-app/src/__components/component3/component3.component.ts",
    "content": "import { Component, HostListener, OnInit } from '@angular/core';\n\n@Component({\n  selector: 'app-component3',\n  templateUrl: './component3.component.html',\n  styleUrls: ['./component3.component.css'],\n  standalone: true,\n})\nexport class Component3Component implements OnInit {\n  @HostListener('tap', ['$event']) tap1(event) {\n    console.log('内置组件的tap事件', event);\n  }\n  @HostListener('bindtap', ['$event']) tap2(event) {\n    console.log('内置组件的(bind)tap事件', event);\n  }\n  constructor() {}\n\n  ngOnInit() {}\n}\n"
  },
  {
    "path": "test/hello-world-app/src/__components/component3/component3.entry.ts",
    "content": "import { componentRegistry } from 'angular-miniprogram';\nimport { Component3Component } from './component3.component';\n\ncomponentRegistry(Component3Component);\n"
  },
  {
    "path": "test/hello-world-app/src/__components/content/content.component.css",
    "content": ""
  },
  {
    "path": "test/hello-world-app/src/__components/content/content.component.html",
    "content": "<div>下面将会有投影内容</div>\n<ng-content></ng-content>\n"
  },
  {
    "path": "test/hello-world-app/src/__components/content/content.component.ts",
    "content": "import { Component, OnInit } from '@angular/core';\n\n@Component({\n  selector: 'app-content',\n  templateUrl: './content.component.html',\n  styleUrls: ['./content.component.css'],\n})\nexport class ContentComponent implements OnInit {\n  constructor() {}\n\n  ngOnInit() {}\n}\n"
  },
  {
    "path": "test/hello-world-app/src/__components/content/content.entry.ts",
    "content": "import { componentRegistry } from 'angular-miniprogram';\nimport { ContentComponent } from './content.component';\n\ncomponentRegistry(ContentComponent);\n"
  },
  {
    "path": "test/hello-world-app/src/__components/content/content.module.ts",
    "content": "import { NgModule } from '@angular/core';\nimport { CommonModule } from 'angular-miniprogram/common';\nimport { ContentComponent } from './content.component';\n\n@NgModule({\n  imports: [CommonModule],\n  declarations: [ContentComponent],\n  exports: [ContentComponent],\n})\nexport class ContentModule {}\n"
  },
  {
    "path": "test/hello-world-app/src/__components/content-multi/content-multi.component.css",
    "content": ""
  },
  {
    "path": "test/hello-world-app/src/__components/content-multi/content-multi.component.html",
    "content": "<div>下面将会有投影内容(多)</div>\n<div>这个是slot1插槽的</div>\n<ng-content select=\"[slot='slot1']\"></ng-content>\n<div>这个是slot2插槽的</div>\n<ng-content select=\"[slot='slot2']\"></ng-content>\n<div>---结束---</div>\n"
  },
  {
    "path": "test/hello-world-app/src/__components/content-multi/content-multi.component.ts",
    "content": "import { Component, OnInit } from '@angular/core';\n\n@Component({\n  selector: 'app-content-multi',\n  templateUrl: './content-multi.component.html',\n  styleUrls: ['./content-multi.component.css'],\n})\nexport class ContentMultiComponent implements OnInit {\n  constructor() {}\n\n  ngOnInit() {}\n}\n"
  },
  {
    "path": "test/hello-world-app/src/__components/content-multi/content-multi.entry.ts",
    "content": "import { componentRegistry } from 'angular-miniprogram';\nimport { ContentMultiComponent } from './content-multi.component';\n\ncomponentRegistry(ContentMultiComponent);\n"
  },
  {
    "path": "test/hello-world-app/src/__components/content-multi/content-multi.module.ts",
    "content": "import { NgModule } from '@angular/core';\nimport { CommonModule } from 'angular-miniprogram/common';\nimport { ContentMultiComponent } from './content-multi.component';\n\n@NgModule({\n  imports: [CommonModule],\n  declarations: [ContentMultiComponent],\n  exports: [ContentMultiComponent],\n})\nexport class ContentMultiModule {}\n"
  },
  {
    "path": "test/hello-world-app/src/__components/life-time/life-time.component.html",
    "content": "组件生命周期\n"
  },
  {
    "path": "test/hello-world-app/src/__components/life-time/life-time.component.ts",
    "content": "import { Component, OnInit } from '@angular/core';\nimport { MiniProgramComponentInstance } from 'angular-miniprogram/platform/type';\n\n@Component({\n  selector: 'app-life-time-component',\n  templateUrl: './life-time.component.html',\n  standalone: true,\n})\nexport class LifeTimeComponent implements OnInit {\n  static mpComponentOptions: WechatMiniprogram.Component.Options<{}, {}, {}> = {\n    lifetimes: {\n      created: function (this: MiniProgramComponentInstance) {\n        console.log('created(component)');\n      },\n      attached: function () {\n        console.log('attached(component)');\n      },\n      ready: function () {\n        console.log('ready(component)');\n      },\n      moved: function () {\n        console.log('moved(component)');\n      },\n      detached: function () {\n        console.log('detached(component)');\n      },\n      error: function () {\n        console.log('error(component)');\n      },\n    },\n    pageLifetimes: {\n      show: function () {\n        console.log('page-show(component)');\n      },\n      hide: function () {\n        console.log('page-hide(component)');\n      },\n      resize: function () {\n        console.log('page-resize(component)');\n      },\n    },\n  };\n  constructor() {\n    console.log('ng-constructor(component)');\n  }\n\n  ngOnInit() {\n    console.log('ng-ngOnInit(component)');\n  }\n  ngAfterViewInit(): void {\n    console.log('ng-ngAfterViewInit(component)');\n  }\n  ngAfterContentInit(): void {\n    console.log('ng-ngAfterContentInit(component)');\n  }\n}\n"
  },
  {
    "path": "test/hello-world-app/src/__components/life-time/life-time.entry.ts",
    "content": "import { componentRegistry, pageStartup } from 'angular-miniprogram';\nimport { LifeTimeComponent } from './life-time.component';\ncomponentRegistry(LifeTimeComponent);\n"
  },
  {
    "path": "test/hello-world-app/src/__pages/base-component/base-component.component.css",
    "content": ""
  },
  {
    "path": "test/hello-world-app/src/__pages/base-component/base-component.component.html",
    "content": "<div>测试引入组件</div>\n<app-component1 [input1]=\"componentInput1\"></app-component1>\n<div>component2中引入了component1</div>\n<app-component2\n  [cp2Input1]=\"componentInput1 + 'component2引入'\"\n></app-component2>\n"
  },
  {
    "path": "test/hello-world-app/src/__pages/base-component/base-component.component.ts",
    "content": "import { Component, OnInit } from '@angular/core';\n\n@Component({\n  selector: 'app-base-component',\n  templateUrl: './base-component.component.html',\n  styleUrls: ['./base-component.component.css'],\n})\nexport class BaseComponentComponent implements OnInit {\n  componentInput1 = '由父组件传入';\n  constructor() {}\n\n  ngOnInit() {}\n}\n"
  },
  {
    "path": "test/hello-world-app/src/__pages/base-component/base-component.entry.ts",
    "content": "import { pageStartup } from 'angular-miniprogram';\nimport { BaseComponentComponent } from './base-component.component';\nimport { BaseComponentModule } from './base-component.module';\n\npageStartup(BaseComponentModule, BaseComponentComponent);\n"
  },
  {
    "path": "test/hello-world-app/src/__pages/base-component/base-component.module.ts",
    "content": "import { NgModule } from '@angular/core';\nimport { CommonModule } from 'angular-miniprogram/common';\nimport { BaseComponentComponent } from './base-component.component';\nimport { Component1Module } from '../../__components/component1/component1.module';\nimport { Component2Module } from '../../__components/component2/component2.module';\n\n@NgModule({\n  imports: [CommonModule, Component1Module, Component2Module],\n  declarations: [BaseComponentComponent],\n})\nexport class BaseComponentModule {}\n"
  },
  {
    "path": "test/hello-world-app/src/__pages/base-directive/base-directive.component.css",
    "content": ""
  },
  {
    "path": "test/hello-world-app/src/__pages/base-directive/base-directive.component.html",
    "content": "<p appDirective1>颜色会变,有tap反应</p>\n<div>---测试内部属性屏蔽---</div>\n<p\n  libInputOutput\n  [input1]=\"'1'\"\n  [input2]=\"1\"\n  (output1)=\"event1()\"\n  (output2)=\"event1()\"\n></p>\n"
  },
  {
    "path": "test/hello-world-app/src/__pages/base-directive/base-directive.component.ts",
    "content": "import { Component, OnInit } from '@angular/core';\n\n@Component({\n  selector: 'app-base-directive',\n  templateUrl: './base-directive.component.html',\n  styleUrls: ['./base-directive.component.css'],\n})\nexport class BaseDirectiveComponent implements OnInit {\n  constructor() {}\n\n  ngOnInit() {}\n\n  event1() {}\n}\n"
  },
  {
    "path": "test/hello-world-app/src/__pages/base-directive/base-directive.entry.ts",
    "content": "import { pageStartup } from 'angular-miniprogram';\nimport { BaseDirectiveComponent } from './base-directive.component';\nimport { BaseDirectiveModule } from './base-directive.module';\n\npageStartup(BaseDirectiveModule, BaseDirectiveComponent);\n"
  },
  {
    "path": "test/hello-world-app/src/__pages/base-directive/base-directive.module.ts",
    "content": "import { NgModule } from '@angular/core';\nimport { CommonModule } from 'angular-miniprogram/common';\nimport { BaseDirectiveComponent } from './base-directive.component';\nimport { Directive1Directive } from './directive1.directive';\nimport { DirectiveModule } from 'test-library';\n\n@NgModule({\n  imports: [CommonModule, DirectiveModule],\n  declarations: [BaseDirectiveComponent, Directive1Directive],\n})\nexport class BaseDirectiveModule {}\n"
  },
  {
    "path": "test/hello-world-app/src/__pages/base-directive/directive1.directive.ts",
    "content": "import { Directive, HostBinding, HostListener } from '@angular/core';\n\n@Directive({\n  selector: '[appDirective1]',\n})\nexport class Directive1Directive {\n  @HostBinding('style.color') color = 'red';\n  @HostListener('tap', ['$event']) tap(event) {\n    console.log('tap事件', event);\n    this.color = 'green';\n  }\n  constructor() {}\n}\n"
  },
  {
    "path": "test/hello-world-app/src/__pages/base-forms/base-forms.component.css",
    "content": ""
  },
  {
    "path": "test/hello-world-app/src/__pages/base-forms/base-forms.component.html",
    "content": "<input type=\"text\" [(ngModel)]=\"value\" (ngModelChange)=\"modelChange($event)\" />\n<checkbox-group [(ngModel)]=\"checked\" (ngModelChange)=\"checkboxChange($event)\">\n  <checkbox [value]=\"'1'\"></checkbox>\n</checkbox-group>\n"
  },
  {
    "path": "test/hello-world-app/src/__pages/base-forms/base-forms.component.ts",
    "content": "import { Component, OnInit } from '@angular/core';\n\n@Component({\n  selector: 'app-base-forms',\n  templateUrl: './base-forms.component.html',\n  styleUrls: ['./base-forms.component.css'],\n})\nexport class BaseFormsComponent implements OnInit {\n  value = '默认值';\n  checked = ['1'];\n  constructor() {}\n\n  ngOnInit() {}\n  modelChange(e) {\n    console.log('数据变更', e);\n  }\n  checkboxChange(e) {\n    console.log(e);\n  }\n}\n"
  },
  {
    "path": "test/hello-world-app/src/__pages/base-forms/base-forms.entry.ts",
    "content": "import { pageStartup } from 'angular-miniprogram';\nimport { BaseFormsComponent } from './base-forms.component';\nimport { BaseFormsModule } from './base-forms.module';\n\npageStartup(BaseFormsModule, BaseFormsComponent);\n"
  },
  {
    "path": "test/hello-world-app/src/__pages/base-forms/base-forms.module.ts",
    "content": "import { NgModule, NO_ERRORS_SCHEMA } from '@angular/core';\nimport { CommonModule } from 'angular-miniprogram/common';\nimport { BaseFormsComponent } from './base-forms.component';\nimport { FormsModule } from 'angular-miniprogram/forms';\n@NgModule({\n  imports: [CommonModule, FormsModule],\n  declarations: [BaseFormsComponent],\n  schemas: [NO_ERRORS_SCHEMA],\n})\nexport class BaseFormsModule {}\n"
  },
  {
    "path": "test/hello-world-app/src/__pages/base-http/base-http.component.css",
    "content": ""
  },
  {
    "path": "test/hello-world-app/src/__pages/base-http/base-http.component.html",
    "content": "<button (tap)=\"request()\">点击请求</button>\n"
  },
  {
    "path": "test/hello-world-app/src/__pages/base-http/base-http.component.ts",
    "content": "import { Component, OnInit } from '@angular/core';\nimport { HttpClient } from 'angular-miniprogram/common/http';\n\n@Component({\n  selector: 'app-base-http',\n  templateUrl: './base-http.component.html',\n  styleUrls: ['./base-http.component.css'],\n})\nexport class BaseHttpComponent implements OnInit {\n  constructor(private http: HttpClient) {}\n\n  ngOnInit() {}\n  request() {\n    this.http\n      .get('https://api.realworld.io/api/articles?limit=10&offset=0')\n      .subscribe((item) => {\n        console.log(item);\n      });\n  }\n}\n"
  },
  {
    "path": "test/hello-world-app/src/__pages/base-http/base-http.entry.ts",
    "content": "import { pageStartup } from 'angular-miniprogram';\nimport { BaseHttpComponent } from './base-http.component';\nimport { BaseHttpModule } from './base-http.module';\n\npageStartup(BaseHttpModule, BaseHttpComponent);\n"
  },
  {
    "path": "test/hello-world-app/src/__pages/base-http/base-http.module.ts",
    "content": "import { NgModule } from '@angular/core';\nimport { HttpClientModule } from 'angular-miniprogram';\nimport { CommonModule } from 'angular-miniprogram/common';\nimport { BaseHttpComponent } from './base-http.component';\n\n@NgModule({\n  imports: [CommonModule, HttpClientModule],\n  declarations: [BaseHttpComponent],\n})\nexport class BaseHttpModule {}\n"
  },
  {
    "path": "test/hello-world-app/src/__pages/base-tap/base-tap.component.css",
    "content": ""
  },
  {
    "path": "test/hello-world-app/src/__pages/base-tap/base-tap.component.html",
    "content": "直接插值({{ interpolation }})\n<view>原生组件需要在module加入`schemas:[NO_ERRORS_SCHEMA]`</view>\n<div>div组件转换为view</div>\n<span>span组件转换为view</span>\n<div (tap)=\"tap1($event)\">组件定义的点击</div>\n<div [style.color]=\"'red'\">字符串->字体颜色红色</div>\n<div [style.color]=\"color\">变量->字体颜色红色</div>\n<div [style.backgroundColor]=\"'green'\">字符串->颜色背景绿色</div>\n<div [style.backgroundColor]=\"backgroundColor\">变量->颜色背景绿色</div>\n\n<div (mut-bindtap)=\"mutBindTap1($event)\">mut-bind使用</div>\n<div (catchtap)=\"catchTap1($event)\">catch使用</div>\n<div (capture-bindtap)=\"captureBindTap1($event)\">capture-bind使用</div>\n<!-- <div (capture-catch)=\"captureCatchTap1($event)\">capture-catch使用</div> -->\n"
  },
  {
    "path": "test/hello-world-app/src/__pages/base-tap/base-tap.component.ts",
    "content": "import { Component, OnInit } from '@angular/core';\n\n@Component({\n  selector: 'app-base-tap',\n  templateUrl: './base-tap.component.html',\n  styleUrls: ['./base-tap.component.css'],\n})\nexport class BaseTagComponent implements OnInit {\n  color = 'red';\n  backgroundColor = 'green';\n  interpolation = '这个是插值内容';\n  constructor() {}\n\n  ngOnInit() {}\n  tap1(event) {\n    console.log('tap事件', event);\n  }\n  mutBindTap1(event) {\n    console.log('mut-bindtap事件', event);\n  }\n  catchTap1(event) {\n    console.log('catchtap事件', event);\n  }\n  captureBindTap1(event) {\n    console.log('capture-bind事件', event);\n  }\n  // captureCatchTap1(event) {\n  //   console.log('capture-catch事件', event);\n  // }\n}\n"
  },
  {
    "path": "test/hello-world-app/src/__pages/base-tap/base-tap.entry.ts",
    "content": "import { pageStartup } from 'angular-miniprogram';\nimport { BaseTagComponent } from './base-tap.component';\nimport { BaseTagModule } from './base-tap.module';\n\npageStartup(BaseTagModule, BaseTagComponent);\n"
  },
  {
    "path": "test/hello-world-app/src/__pages/base-tap/base-tap.module.ts",
    "content": "import { NgModule, NO_ERRORS_SCHEMA } from '@angular/core';\nimport { CommonModule } from 'angular-miniprogram/common';\nimport { BaseTagComponent } from './base-tap.component';\n\n@NgModule({\n  imports: [CommonModule],\n  declarations: [BaseTagComponent],\n  schemas: [NO_ERRORS_SCHEMA],\n})\nexport class BaseTagModule {}\n"
  },
  {
    "path": "test/hello-world-app/src/__pages/complex-property-event/app-dir1.directive.ts",
    "content": "import { Directive, HostListener } from '@angular/core';\n\n@Directive({\n  selector: '[appDir1]',\n})\nexport class AppDir1Directive {\n  @HostListener('tap', ['$event']) tap1(event) {\n    console.log('内置指令的tap事件', event);\n  }\n  @HostListener('bindtap', ['$event']) tap2(event) {\n    console.log('内置指令的(bind)tap事件', event);\n  }\n  constructor() {}\n}\n"
  },
  {
    "path": "test/hello-world-app/src/__pages/complex-property-event/complex-property-event.component.css",
    "content": ""
  },
  {
    "path": "test/hello-world-app/src/__pages/complex-property-event/complex-property-event.component.html",
    "content": "<div appDir1 appLibDir1>指令事件</div>\n<div>内置组件+内置指令+library指令</div>\n<app-component3 appDir1 appLibDir1></app-component3>\n<div>library组件+内置指令+library指令</div>\n<app-lib-comp1 appDir1 appLibDir1></app-lib-comp1>\n"
  },
  {
    "path": "test/hello-world-app/src/__pages/complex-property-event/complex-property-event.component.ts",
    "content": "import { Component, OnInit } from '@angular/core';\n\n@Component({\n  selector: 'app-complex-property-event',\n  templateUrl: './complex-property-event.component.html',\n  styleUrls: ['./complex-property-event.component.css'],\n})\nexport class ComplexPropertyEventComponent implements OnInit {\n  constructor() {}\n\n  ngOnInit() {}\n}\n"
  },
  {
    "path": "test/hello-world-app/src/__pages/complex-property-event/complex-property-event.entry.ts",
    "content": "import { pageStartup } from 'angular-miniprogram';\nimport { ComplexPropertyEventComponent } from './complex-property-event.component';\nimport { ComplexPropertyEventModule } from './complex-property-event.module';\n\npageStartup(ComplexPropertyEventModule, ComplexPropertyEventComponent);\n"
  },
  {
    "path": "test/hello-world-app/src/__pages/complex-property-event/complex-property-event.module.ts",
    "content": "import { NgModule } from '@angular/core';\nimport { CommonModule } from 'angular-miniprogram/common';\nimport { ComplexPropertyEventComponent } from './complex-property-event.component';\nimport { AppDir1Directive } from './app-dir1.directive';\nimport { LibComp1Module } from 'test-library';\nimport { Component3Component } from '../../__components/component3/component3.component';\n\n@NgModule({\n  imports: [CommonModule, LibComp1Module, Component3Component],\n  declarations: [ComplexPropertyEventComponent, AppDir1Directive],\n})\nexport class ComplexPropertyEventModule {}\n"
  },
  {
    "path": "test/hello-world-app/src/__pages/complex-structure/complex-structure.component.css",
    "content": ""
  },
  {
    "path": "test/hello-world-app/src/__pages/complex-structure/complex-structure.component.html",
    "content": "<div>ngIf->ngIf</div>\n<div *ngIf=\"true\" [style.color]=\"'red'\">\n  第一层\n  <div *ngIf=\"true\" [style.color]=\"'yellow'\">第二层</div>\n</div>\n<div>ngIf->ngFor</div>\n<div *ngIf=\"true\">\n  <div *ngFor=\"let item of list; let i = index\">\n    内容:item:{{ item }},index:{{ i }}\n  </div>\n</div>\n<div>ngFor->ngFor</div>\n<div *ngFor=\"let item1 of list\">\n  <div *ngFor=\"let item2 of list\">内容item1:{{ item1 }},item2:{{ item2 }}</div>\n</div>\n\n<div>ngFor->ng-content</div>\n<div *ngFor=\"let item of list; let i = index\">\n  <app-content> 投影内容:{{ item }} </app-content>\n</div>\n"
  },
  {
    "path": "test/hello-world-app/src/__pages/complex-structure/complex-structure.component.ts",
    "content": "import { Component, OnInit } from '@angular/core';\n\n@Component({\n  selector: 'app-complex-structure',\n  templateUrl: './complex-structure.component.html',\n  styleUrls: ['./complex-structure.component.css'],\n})\nexport class ComplexStructureComponent implements OnInit {\n  list = [1, 2, 3];\n  constructor() {}\n\n  ngOnInit() {}\n}\n"
  },
  {
    "path": "test/hello-world-app/src/__pages/complex-structure/complex-structure.entry.ts",
    "content": "import { pageStartup } from 'angular-miniprogram';\n\nimport { ComplexStructureComponent } from './complex-structure.component';\nimport { ComplexStructureModule } from './complex-structure.module';\n\npageStartup(ComplexStructureModule, ComplexStructureComponent);\n"
  },
  {
    "path": "test/hello-world-app/src/__pages/complex-structure/complex-structure.module.ts",
    "content": "import { NgModule } from '@angular/core';\nimport { CommonModule } from 'angular-miniprogram/common';\nimport { ComplexStructureComponent } from './complex-structure.component';\nimport { ContentModule } from '../../__components/content/content.module';\n\n@NgModule({\n  imports: [CommonModule, ContentModule],\n  declarations: [ComplexStructureComponent],\n})\nexport class ComplexStructureModule {}\n"
  },
  {
    "path": "test/hello-world-app/src/__pages/component-use-template/component-use-template.component.css",
    "content": ""
  },
  {
    "path": "test/hello-world-app/src/__pages/component-use-template/component-use-template.component.html",
    "content": "<ng-template #$$mp$$TestLibrary$$first>\n  这个是外部定义模板 引入组件<app-component1\n    [input1]=\"'外部模板'\"\n  ></app-component1>\n</ng-template>\n<app-outside-template\n  [template]=\"$$mp$$TestLibrary$$first\"\n></app-outside-template>\n<div>下面的是调用library内组件的其他组件模板</div>\n<app-global-self-template></app-global-self-template>\n"
  },
  {
    "path": "test/hello-world-app/src/__pages/component-use-template/component-use-template.component.ts",
    "content": "import { Component, OnInit } from '@angular/core';\n\n@Component({\n  selector: 'app-component-use-template',\n  templateUrl: './component-use-template.component.html',\n  styleUrls: ['./component-use-template.component.css'],\n})\nexport class ComponentUseTemplateComponent implements OnInit {\n  constructor() {}\n\n  ngOnInit() {}\n}\n"
  },
  {
    "path": "test/hello-world-app/src/__pages/component-use-template/component-use-template.entry.ts",
    "content": "import { pageStartup } from 'angular-miniprogram';\nimport { ComponentUseTemplateComponent } from './component-use-template.component';\nimport { ComponentUseTemplateModule } from './component-use-template.module';\n\npageStartup(ComponentUseTemplateModule, ComponentUseTemplateComponent);\n"
  },
  {
    "path": "test/hello-world-app/src/__pages/component-use-template/component-use-template.module.ts",
    "content": "import { NgModule } from '@angular/core';\nimport { GlobalSelfTemplateModule } from 'test-library';\nimport { OutsideTemplateModule } from 'test-library';\nimport { Component1Module } from '../../__components/component1/component1.module';\nimport { ComponentUseTemplateComponent } from './component-use-template.component';\n\n@NgModule({\n  imports: [OutsideTemplateModule, Component1Module, GlobalSelfTemplateModule],\n  declarations: [ComponentUseTemplateComponent],\n})\nexport class ComponentUseTemplateModule {}\n"
  },
  {
    "path": "test/hello-world-app/src/__pages/custom-structural-directive/custom-structural-directive.component.css",
    "content": ""
  },
  {
    "path": "test/hello-world-app/src/__pages/custom-structural-directive/custom-structural-directive.component.html",
    "content": "<ng-container *appStructural1=\"template1; name: 'template1'\"></ng-container>\n<ng-template #template1 let-name=\"__templateName\">\n  使用自定义指令显示的模板->模板名:{{ name }}\n</ng-template>\n"
  },
  {
    "path": "test/hello-world-app/src/__pages/custom-structural-directive/custom-structural-directive.component.ts",
    "content": "import { Component, OnInit } from '@angular/core';\n\n@Component({\n  selector: 'app-custom-structural-directive',\n  templateUrl: './custom-structural-directive.component.html',\n  styleUrls: ['./custom-structural-directive.component.css'],\n})\nexport class CustomStructuralDirectiveComponent implements OnInit {\n  constructor() {}\n\n  ngOnInit() {}\n}\n"
  },
  {
    "path": "test/hello-world-app/src/__pages/custom-structural-directive/custom-structural-directive.entry.ts",
    "content": "import { pageStartup } from 'angular-miniprogram';\n\nimport { CustomStructuralDirectiveComponent } from './custom-structural-directive.component';\nimport { CustomStructuralDirectiveModule } from './custom-structural-directive.module';\n\npageStartup(\n  CustomStructuralDirectiveModule,\n  CustomStructuralDirectiveComponent\n);\n"
  },
  {
    "path": "test/hello-world-app/src/__pages/custom-structural-directive/custom-structural-directive.module.ts",
    "content": "import { NgModule } from '@angular/core';\nimport { CommonModule } from 'angular-miniprogram/common';\nimport { CustomStructuralDirectiveComponent } from './custom-structural-directive.component';\nimport { Structural1Directive } from './structural1.directive';\n\n@NgModule({\n  imports: [CommonModule],\n  declarations: [CustomStructuralDirectiveComponent, Structural1Directive],\n})\nexport class CustomStructuralDirectiveModule {}\n"
  },
  {
    "path": "test/hello-world-app/src/__pages/custom-structural-directive/structural1.directive.ts",
    "content": "import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core';\n\n@Directive({\n  selector: '[appStructural1]',\n})\nexport class Structural1Directive {\n  @Input() appStructural1: TemplateRef<any>;\n  @Input() appStructural1Name: string;\n  constructor(private viewContainerRef: ViewContainerRef) {}\n  ngOnInit(): void {\n    this.viewContainerRef.createEmbeddedView(this.appStructural1, {\n      __templateName: this.appStructural1Name,\n    });\n  }\n}\n"
  },
  {
    "path": "test/hello-world-app/src/__pages/default-structural-directive/default-structural-directive.component.css",
    "content": ""
  },
  {
    "path": "test/hello-world-app/src/__pages/default-structural-directive/default-structural-directive.component.html",
    "content": "<div>\n  默认结构型指令为静态解析,所以模板将会在编译时固定,如果想有限的使用模板(当前组件内传递模板),可以先定义自定义结构型指令,或者后期有时间hook\n  common依赖库来实现\n</div>\n<div>语法糖ngIf显示测试</div>\n<button (tap)=\"ngIfControl()\">点击控制显示/隐藏</button>\n<div *ngIf=\"flag.if\">默认为显示</div>\n<div>语法糖ngIf else测试</div>\n<button (tap)=\"ngIfElseControl()\">点击控制显示/隐藏</button>\n<div *ngIf=\"flag.ifElse; else ngIfElseTemplate\">默认if为显示</div>\n<ng-template #ngIfElseTemplate>\n  <div>else时显示</div>\n</ng-template>\n<p>非语法糖ngIf显示测试</p>\n<button (tap)=\"ngIfDefault()\">点击控制显示/隐藏</button>\n<ng-template [ngIf]=\"flag.ifDefault\" [ngIfElse]=\"ngIfDefaultElseTemplate\"\n  >模板上默认if为显示</ng-template\n>\n<ng-template #ngIfDefaultElseTemplate>\n  <div>模板上else时显示</div>\n</ng-template>\n<div>------------------------</div>\n<div>ngfor测试</div>\n<button (tap)=\"addList()\">增加列表</button>\n<button (tap)=\"removeList()\">减少列表</button>\n<div *ngFor=\"let item of list\">{{ item }}</div>\n\n<div>-------------</div>\n<div>ngSwitch测试</div>\n<button (tap)=\"changeSwitch()\">修改显示</button>\n<span [ngSwitch]=\"ngSwitchValue\">\n  <p *ngSwitchCase=\"0\">0显示</p>\n  <p *ngSwitchCase=\"1\">1显示</p>\n  <p *ngSwitchDefault style=\"background-color: green\">(2)其他显示</p>\n</span>\n<div>-----------</div>\n<div>ngTemplateOutLet</div>\n<ng-template #outletTemplate>ngTemplateOutLet测试</ng-template>\n<ng-container *ngTemplateOutlet=\"outletTemplate\"></ng-container>\n<div>ngComponentOutLet暂时不支持(如果hook common组件库可能会有限支持)</div>\n"
  },
  {
    "path": "test/hello-world-app/src/__pages/default-structural-directive/default-structural-directive.component.ts",
    "content": "import { Component, OnInit } from '@angular/core';\n\n@Component({\n  selector: 'app-default-structural-directive',\n  templateUrl: './default-structural-directive.component.html',\n  styleUrls: ['./default-structural-directive.component.css'],\n})\nexport class DefaultStructuralDirectiveComponent implements OnInit {\n  flag = {\n    if: true,\n    ifElse: true,\n    ifDefault: true,\n  };\n  list = [0, 1, 2];\n  ngSwitchValue: boolean | number = 0;\n  ngSwitchValueList = [0, 1, 2];\n  ngSwitchValueIndex = 0;\n  constructor() {}\n\n  ngOnInit() {}\n  ngIfControl() {\n    this.flag.if = !this.flag.if;\n  }\n  ngIfElseControl() {\n    this.flag.ifElse = !this.flag.ifElse;\n  }\n  ngIfDefault() {\n    this.flag.ifDefault = !this.flag.ifDefault;\n  }\n  addList() {\n    this.list.push(this.list.length);\n    this.list = this.list.slice();\n  }\n  removeList() {\n    this.list.pop();\n    this.list = this.list.slice();\n  }\n  changeSwitch() {\n    this.ngSwitchValueIndex =\n      this.ngSwitchValueList.length === this.ngSwitchValueIndex + 1\n        ? 0\n        : ++this.ngSwitchValueIndex;\n    this.ngSwitchValue = this.ngSwitchValueList[this.ngSwitchValueIndex];\n    console.log(this.ngSwitchValue);\n  }\n}\n"
  },
  {
    "path": "test/hello-world-app/src/__pages/default-structural-directive/default-structural-directive.entry.ts",
    "content": "import { pageStartup } from 'angular-miniprogram';\n\nimport { DefaultStructuralDirectiveComponent } from './default-structural-directive.component';\nimport { DefaultStructuralDirectiveModule } from './default-structural-directive.module';\n\npageStartup(\n  DefaultStructuralDirectiveModule,\n  DefaultStructuralDirectiveComponent\n);\n"
  },
  {
    "path": "test/hello-world-app/src/__pages/default-structural-directive/default-structural-directive.module.ts",
    "content": "import { NgModule } from '@angular/core';\nimport { CommonModule } from 'angular-miniprogram/common';\nimport { DefaultStructuralDirectiveComponent } from './default-structural-directive.component';\n\n@NgModule({\n  imports: [CommonModule],\n  declarations: [DefaultStructuralDirectiveComponent],\n})\nexport class DefaultStructuralDirectiveModule {}\n"
  },
  {
    "path": "test/hello-world-app/src/__pages/life-time-page/life-time-page.entry.ts",
    "content": "import { pageStartup } from 'angular-miniprogram';\nimport { LifeTimePageModule } from './life-time.module';\nimport { LifeTimePage } from './life-time.component';\npageStartup(LifeTimePageModule, LifeTimePage);\n"
  },
  {
    "path": "test/hello-world-app/src/__pages/life-time-page/life-time.component.html",
    "content": "<app-life-time-component></app-life-time-component> 页面显示\n"
  },
  {
    "path": "test/hello-world-app/src/__pages/life-time-page/life-time.component.ts",
    "content": "import { Component, OnInit } from '@angular/core';\nimport { MiniProgramComponentInstance } from 'angular-miniprogram/platform/type';\n\n@Component({\n  selector: 'app-life-time',\n  templateUrl: './life-time.component.html',\n})\nexport class LifeTimePage implements OnInit {\n  static mpPageOptions: WechatMiniprogram.Page.Options<{}, {}> = {\n    onLoad: function (this: MiniProgramComponentInstance) {\n      console.log('mp-onLoad', this.__ngComponentInstance);\n    },\n    onShow: function () {\n      console.log('mp-onShow', this.__ngComponentInstance);\n    },\n    onReady: function (\n      this: WechatMiniprogram.Page.Instance<{}, {}> &\n        MiniProgramComponentInstance<LifeTimePage>\n    ) {\n      console.log('mp-onReady');\n    },\n  };\n  constructor() {\n    console.log('ng-constructor');\n  }\n\n  ngOnInit() {\n    console.log('ng-ngOnInit');\n  }\n  ngAfterViewInit(): void {\n    console.log('ng-ngAfterViewInit');\n  }\n  ngAfterContentInit(): void {\n    console.log('ng-ngAfterContentInit');\n  }\n}\n"
  },
  {
    "path": "test/hello-world-app/src/__pages/life-time-page/life-time.module.ts",
    "content": "import { NgModule } from '@angular/core';\nimport { CommonModule } from 'angular-miniprogram/common';\nimport { LifeTimeComponent } from '../../__components/life-time/life-time.component';\nimport { LifeTimePage } from './life-time.component';\n\n@NgModule({\n  imports: [CommonModule, LifeTimeComponent],\n  declarations: [LifeTimePage],\n})\nexport class LifeTimePageModule {}\n"
  },
  {
    "path": "test/hello-world-app/src/__pages/life-time-page-use-component/life-time-page-use-component.entry.ts",
    "content": "import { pageStartup } from 'angular-miniprogram';\nimport { LifeTimePageModule } from './life-time.module';\nimport { LifeTimePage } from './life-time.component';\npageStartup(LifeTimePageModule, LifeTimePage, { useComponent: true });\n"
  },
  {
    "path": "test/hello-world-app/src/__pages/life-time-page-use-component/life-time.component.html",
    "content": "<app-life-time-component></app-life-time-component> 页面显示\n"
  },
  {
    "path": "test/hello-world-app/src/__pages/life-time-page-use-component/life-time.component.ts",
    "content": "import { Component, OnInit } from '@angular/core';\nimport { MiniProgramComponentInstance } from 'angular-miniprogram/platform/type';\n\n@Component({\n  selector: 'app-life-time',\n  templateUrl: './life-time.component.html',\n})\nexport class LifeTimePage implements OnInit {\n  static mpComponentOptions: WechatMiniprogram.Component.Options<\n    {},\n    {},\n    {},\n    {},\n    true\n  > = {\n    lifetimes: {\n      created: function (this: MiniProgramComponentInstance) {\n        console.log('created(use-component)');\n      },\n      attached: function () {\n        console.log('attached(use-component)');\n      },\n      ready: function () {\n        console.log('ready(use-component)');\n      },\n      moved: function () {\n        console.log('moved(use-component)');\n      },\n      detached: function () {\n        console.log('detached(use-component)');\n      },\n      error: function () {\n        console.log('error(use-component)');\n      },\n    },\n    pageLifetimes: {\n      show: function () {\n        console.log('page-show(use-component)');\n      },\n      hide: function () {\n        console.log('page-hide(use-component)');\n      },\n      resize: function () {\n        console.log('page-resize(use-component)');\n      },\n    },\n    methods: {\n      onLoad: () => {\n        console.log('onLoad(use-component)');\n      },\n      onShow: () => {\n        console.log('onShow(use-component)');\n      },\n      onReady: () => {\n        console.log('onReady(use-component)');\n      },\n    },\n  };\n  constructor() {\n    console.log('ng-constructor(use-component)');\n  }\n\n  ngOnInit() {\n    console.log('ng-ngOnInit(use-component)');\n  }\n  ngAfterViewInit(): void {\n    console.log('ng-ngAfterViewInit(use-component)');\n  }\n  ngAfterContentInit(): void {\n    console.log('ng-ngAfterContentInit(use-component)');\n  }\n}\n"
  },
  {
    "path": "test/hello-world-app/src/__pages/life-time-page-use-component/life-time.module.ts",
    "content": "import { NgModule } from '@angular/core';\nimport { CommonModule } from 'angular-miniprogram/common';\nimport { LifeTimeComponent } from '../../__components/life-time/life-time.component';\nimport { LifeTimePage } from './life-time.component';\n\n@NgModule({\n  imports: [CommonModule, LifeTimeComponent],\n  declarations: [LifeTimePage],\n})\nexport class LifeTimePageModule {}\n"
  },
  {
    "path": "test/hello-world-app/src/__pages/ng-content/ng-content.component.css",
    "content": ""
  },
  {
    "path": "test/hello-world-app/src/__pages/ng-content/ng-content.component.html",
    "content": "<app-content> 这个是投影内容 </app-content>\n<app-content-multi>\n  <div slot=\"slot1\">插槽1内容</div>\n  <div slot=\"slot2\">插槽2内容</div>\n</app-content-multi>\n"
  },
  {
    "path": "test/hello-world-app/src/__pages/ng-content/ng-content.component.ts",
    "content": "import { Component, OnInit } from '@angular/core';\n\n@Component({\n  selector: 'app-ng-content',\n  templateUrl: './ng-content.component.html',\n  styleUrls: ['./ng-content.component.css'],\n})\nexport class NgContentComponent implements OnInit {\n  constructor() {}\n\n  ngOnInit() {}\n}\n"
  },
  {
    "path": "test/hello-world-app/src/__pages/ng-content/ng-content.entry.ts",
    "content": "import { pageStartup } from 'angular-miniprogram';\n\nimport { NgContentComponent } from './ng-content.component';\nimport { NgContentModule } from './ng-content.module';\n\npageStartup(NgContentModule, NgContentComponent);\n"
  },
  {
    "path": "test/hello-world-app/src/__pages/ng-content/ng-content.module.ts",
    "content": "import { NgModule } from '@angular/core';\nimport { CommonModule } from 'angular-miniprogram/common';\nimport { NgContentComponent } from './ng-content.component';\nimport { ContentModule } from '../../__components/content/content.module';\nimport { ContentMultiModule } from '../../__components/content-multi/content-multi.module';\n\n@NgModule({\n  imports: [CommonModule, ContentModule, ContentMultiModule],\n  declarations: [NgContentComponent],\n})\nexport class NgContentModule {}\n"
  },
  {
    "path": "test/hello-world-app/src/__pages/root/root.component.css",
    "content": ""
  },
  {
    "path": "test/hello-world-app/src/__pages/root/root.component.html",
    "content": "<button (tap)=\"baseTag()\">基础tap</button>\n<button (tap)=\"baseComponent()\">基础组件</button>\n<button (tap)=\"baseDirective()\">基础指令</button>\n<button (tap)=\"baseHttp()\">基础请求</button>\n<button (tap)=\"ngContent()\">ng-content</button>\n<button (tap)=\"defaultStructuralDirective()\">默认结构型指令</button>\n<button (tap)=\"customStructuralDirective()\">自定义结构型指令</button>\n<button (tap)=\"complexStructure()\">复杂结构</button>\n<button (tap)=\"complexPropertyEvent()\">复杂属性与事件</button>\n<button (tap)=\"baseForms()\">基础表单</button>\n<button (tap)=\"componentUseTemplate()\">使用模板传入组件</button>\n<button (tap)=\"selfComponent()\">使用self模板</button>\n<button (tap)=\"lifeTime()\">生命周期</button>\n<button (tap)=\"lifeTimeUseComponent()\">生命周期-useComponent</button>\n"
  },
  {
    "path": "test/hello-world-app/src/__pages/root/root.component.ts",
    "content": "import { Component, Inject, OnInit } from '@angular/core';\nimport { MINIPROGRAM_GLOBAL_TOKEN } from 'angular-miniprogram';\n\n@Component({\n  selector: 'app-root',\n  templateUrl: './root.component.html',\n  styleUrls: ['./root.component.css'],\n})\nexport class RootComponent implements OnInit {\n  constructor(@Inject(MINIPROGRAM_GLOBAL_TOKEN) private global: any) {}\n\n  ngOnInit() {}\n  baseTag() {\n    this.global.navigateTo({ url: '/pages/base-tap/base-tap-entry' });\n  }\n  baseComponent() {\n    this.global.navigateTo({\n      url: '/pages/base-component/base-component-entry',\n    });\n  }\n  baseDirective() {\n    this.global.navigateTo({\n      url: '/pages/base-directive/base-directive-entry',\n    });\n  }\n  ngContent() {\n    this.global.navigateTo({ url: '/pages/ng-content/ng-content-entry' });\n  }\n  defaultStructuralDirective() {\n    this.global.navigateTo({\n      url: '/pages/default-structural-directive/default-structural-directive-entry',\n    });\n  }\n  customStructuralDirective() {\n    this.global.navigateTo({\n      url: '/pages/custom-structural-directive/custom-structural-directive-entry',\n    });\n  }\n  complexStructure() {\n    this.global.navigateTo({\n      url: '/pages/complex-structure/complex-structure-entry',\n    });\n  }\n  complexPropertyEvent() {\n    this.global.navigateTo({\n      url: '/pages/complex-property-event/complex-property-event-entry',\n    });\n  }\n  baseForms() {\n    this.global.navigateTo({\n      url: '/pages/base-forms/base-forms-entry',\n    });\n  }\n  componentUseTemplate() {\n    this.global.navigateTo({\n      url: '/pages/component-use-template/component-use-template-entry',\n    });\n  }\n  baseHttp() {\n    this.global.navigateTo({\n      url: '/pages/base-http/base-http-entry',\n    });\n  }\n  selfComponent() {\n    this.global.navigateTo({\n      url: '/pages/self-component/self-component-entry',\n    });\n  }\n  lifeTime() {\n    this.global.navigateTo({\n      url: '/pages/life-time-page/life-time-page-entry',\n    });\n  }\n  lifeTimeUseComponent() {\n    this.global.navigateTo({\n      url: '/pages/life-time-page-use-component/life-time-page-use-component-entry',\n    });\n  }\n}\n"
  },
  {
    "path": "test/hello-world-app/src/__pages/root/root.entry.ts",
    "content": "import { pageStartup } from 'angular-miniprogram';\nimport { RootComponent } from './root.component';\nimport { RootModule } from './root.module';\n\npageStartup(RootModule, RootComponent, { useComponent: true });\n"
  },
  {
    "path": "test/hello-world-app/src/__pages/root/root.module.ts",
    "content": "import { NgModule } from '@angular/core';\nimport { CommonModule } from 'angular-miniprogram/common';\nimport { RootComponent } from './root.component';\n\n@NgModule({\n  imports: [CommonModule],\n  declarations: [RootComponent],\n})\nexport class RootModule {}\n"
  },
  {
    "path": "test/hello-world-app/src/__pages/self-component/self-component.component.css",
    "content": ""
  },
  {
    "path": "test/hello-world-app/src/__pages/self-component/self-component.component.html",
    "content": "<ng-template #$$mp$$__self__$$self1> 传入模板测试 </ng-template>\n<app-component-need-template\n  [templateRef]=\"$$mp$$__self__$$self1\"\n></app-component-need-template>\n"
  },
  {
    "path": "test/hello-world-app/src/__pages/self-component/self-component.component.ts",
    "content": "import { Component, OnInit } from '@angular/core';\n\n@Component({\n  selector: 'app-self-component',\n  templateUrl: './self-component.component.html',\n  styleUrls: ['./self-component.component.css'],\n})\nexport class SelfComponentComponent implements OnInit {\n  constructor() {}\n\n  ngOnInit() {}\n}\n"
  },
  {
    "path": "test/hello-world-app/src/__pages/self-component/self-component.entry.ts",
    "content": "import { pageStartup } from 'angular-miniprogram';\nimport { SelfComponentComponent } from './self-component.component';\nimport { SelfComponentModule } from './self-component.module';\n\npageStartup(SelfComponentModule, SelfComponentComponent);\n"
  },
  {
    "path": "test/hello-world-app/src/__pages/self-component/self-component.module.ts",
    "content": "import { NgModule } from '@angular/core';\nimport { CommonModule } from 'angular-miniprogram/common';\nimport { ComponentNeedTemplateModule } from '../../__components/component-need-template/component-need-template.module';\nimport { SelfComponentComponent } from './self-component.component';\n\n@NgModule({\n  imports: [CommonModule, ComponentNeedTemplateModule],\n  declarations: [SelfComponentComponent],\n})\nexport class SelfComponentModule {}\n"
  },
  {
    "path": "test/hello-world-app/src/app.json",
    "content": "{\n  \"pages\": [],\n  \"window\": {\n    \"backgroundTextStyle\": \"light\",\n    \"navigationBarBackgroundColor\": \"#fff\",\n    \"navigationBarTitleText\": \"Weixin\",\n    \"navigationBarTextStyle\": \"black\"\n  },\n  \"style\": \"v2\"\n}\n"
  },
  {
    "path": "test/hello-world-app/src/assets/.gitkeep",
    "content": ""
  },
  {
    "path": "test/hello-world-app/src/environments/environment.prod.ts",
    "content": "/**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nexport const environment = {\n  production: true,\n};\n"
  },
  {
    "path": "test/hello-world-app/src/environments/environment.ts",
    "content": "/**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n// The file contents for the current environment will overwrite these during build.\n// The build system defaults to the dev environment which uses `environment.ts`, but if you do\n// `ng build --env=prod` then `environment.prod.ts` will be used instead.\n// The list of which env maps to which file can be found in `.angular-cli.json`.\n\nexport const environment = {\n  production: false,\n};\n"
  },
  {
    "path": "test/hello-world-app/src/main-test.module.ts",
    "content": "import { NgModule } from '@angular/core';\nimport { DoBootstrap } from '@angular/core';\nimport { MiniProgramModule } from 'angular-miniprogram';\n@NgModule({\n  declarations: [],\n  imports: [MiniProgramModule],\n  exports: [],\n  providers: [],\n})\nexport class MainTestModule implements DoBootstrap {\n  constructor() {}\n  ngDoBootstrap() {}\n}\n"
  },
  {
    "path": "test/hello-world-app/src/main.module.ts",
    "content": "import { NgModule } from '@angular/core';\nimport { DoBootstrap } from '@angular/core';\nimport { MiniProgramModule } from 'angular-miniprogram';\n@NgModule({\n  declarations: [],\n  imports: [MiniProgramModule],\n  exports: [],\n  providers: [],\n})\nexport class MainModule implements DoBootstrap {\n  constructor() {}\n  ngDoBootstrap() {}\n}\n"
  },
  {
    "path": "test/hello-world-app/src/main.ts",
    "content": "import { enableProdMode } from '@angular/core';\n\nimport { MainModule } from './main.module';\nimport { environment } from './environments/environment';\nimport { platformMiniProgram } from 'angular-miniprogram';\nimport 'zone.js';\nif (environment.production) {\n  enableProdMode();\n}\n\nplatformMiniProgram()\n  .bootstrapModule(MainModule)\n  .then((e) => {\n    console.log(e);\n  });\n"
  },
  {
    "path": "test/hello-world-app/src/project.config.json",
    "content": "{\n  \"description\": \"项目配置文件\",\n  \"packOptions\": {\n    \"ignore\": []\n  },\n  \"miniprogramRoot\": \"/\",\n  \"compileType\": \"miniprogram\",\n  \"libVersion\": \"2.8.2\",\n  \"projectname\": \"miniprogram-1\",\n  \"scripts\": {\n    \"beforeCompile\": \"\",\n    \"beforePreview\": \"\",\n    \"beforeUpload\": \"\"\n  },\n  \"setting\": {\n    \"urlCheck\": true,\n    \"es6\": false,\n    \"enhance\": false,\n    \"postcss\": false,\n    \"preloadBackgroundData\": false,\n    \"minified\": false,\n    \"newFeature\": false,\n    \"coverView\": true,\n    \"nodeModules\": false,\n    \"autoAudits\": false,\n    \"showShadowRootInWxmlPanel\": false,\n    \"scopeDataCheck\": false,\n    \"uglifyFileName\": false,\n    \"checkInvalidKey\": true,\n    \"checkSiteMap\": true,\n    \"uploadWithSourceMap\": true,\n    \"compileHotReLoad\": false,\n    \"useMultiFrameRuntime\": true,\n    \"useApiHook\": true,\n    \"useApiHostProcess\": true,\n    \"babelSetting\": {\n      \"ignore\": [],\n      \"disablePlugins\": [],\n      \"outputPath\": \"\"\n    },\n    \"enableEngineNative\": false,\n    \"useIsolateContext\": true,\n    \"useCompilerModule\": true,\n    \"userConfirmedUseCompilerModuleSwitch\": false,\n    \"userConfirmedBundleSwitch\": false,\n    \"packNpmManually\": false,\n    \"packNpmRelationList\": [],\n    \"minifyWXSS\": false\n  },\n  \"simulatorType\": \"wechat\",\n  \"simulatorPluginLibVersion\": {},\n  \"appid\": \"touristappid\",\n  \"condition\": {}\n}\n"
  },
  {
    "path": "test/hello-world-app/src/spec/empty/empty.component.ts",
    "content": "import { Component, OnInit } from '@angular/core';\n\n@Component({\n  selector: 'app-empty',\n  template: '',\n})\nexport class EmptyComponent {}\n"
  },
  {
    "path": "test/hello-world-app/src/spec/empty/empty.entry.ts",
    "content": "import { pageStartup } from 'angular-miniprogram';\nimport { EmptyModule } from './empty.module';\nimport { EmptyComponent } from './empty.component';\npageStartup(EmptyModule, EmptyComponent);\n"
  },
  {
    "path": "test/hello-world-app/src/spec/empty/empty.module.ts",
    "content": "import { NgModule } from '@angular/core';\n\nimport { EmptyComponent } from './empty.component';\n\n@NgModule({\n  imports: [],\n  declarations: [EmptyComponent],\n})\nexport class EmptyModule {}\n"
  },
  {
    "path": "test/hello-world-app/src/spec/http-spec/http-spec.entry.ts",
    "content": "import { pageStartup } from 'angular-miniprogram';\nimport { HttpSpecModule } from './http.module';\nimport { HttpSpecComponent } from './http.component';\n\npageStartup(HttpSpecModule, HttpSpecComponent);\n"
  },
  {
    "path": "test/hello-world-app/src/spec/http-spec/http.component.ts",
    "content": "import { Component, OnInit } from '@angular/core';\nimport { HttpClient } from 'angular-miniprogram/common/http';\nimport { BehaviorSubject } from 'rxjs';\n\n@Component({\n  selector: 'app-http-spec',\n  template: ``,\n})\nexport class HttpSpecComponent implements OnInit {\n  testFinish$$ = new BehaviorSubject(undefined);\n\n  constructor(private http: HttpClient) {}\n\n  ngOnInit() {\n    this.request();\n  }\n  request() {\n    this.http\n      .get('https://api.realworld.io/api/articles?limit=10&offset=0')\n      .subscribe((item) => {\n        expect(item).toBeTruthy();\n        expect(typeof item).toBe('object');\n        this.testFinish$$.complete();\n      });\n  }\n}\n"
  },
  {
    "path": "test/hello-world-app/src/spec/http-spec/http.module.ts",
    "content": "import { NgModule } from '@angular/core';\nimport { HttpClientModule } from 'angular-miniprogram';\nimport { CommonModule } from 'angular-miniprogram/common';\nimport { HttpSpecComponent } from './http.component';\n@NgModule({\n  imports: [CommonModule, HttpClientModule],\n  declarations: [HttpSpecComponent],\n})\nexport class HttpSpecModule {}\n"
  },
  {
    "path": "test/hello-world-app/src/spec/http-spec/http.spec.ts",
    "content": "import { componentTestComplete, getComponent, openComponent } from '../util';\nimport { HttpSpecComponent } from './http.component';\n\ndescribe('http', () => {\n  let oldTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL;\n  beforeEach(async () => {\n    jasmine.DEFAULT_TIMEOUT_INTERVAL = 100 * 1000;\n    await openComponent(`/spec/http-spec/http-spec-entry`);\n  });\n  it('run', (done) => {\n    let pages = getCurrentPages();\n    let page = pages[0];\n    let component = getComponent<HttpSpecComponent>(page);\n    componentTestComplete(component.testFinish$$).then(() => {\n      done();\n      jasmine.DEFAULT_TIMEOUT_INTERVAL = oldTimeout;\n    });\n  });\n});\n"
  },
  {
    "path": "test/hello-world-app/src/spec/life-time-spec/life-time-spec.entry.ts",
    "content": "import { pageStartup } from 'angular-miniprogram';\nimport { LifeTimeSpecModule } from './life-time.module';\nimport { LifeTimeSPecComponent } from './life-time.component';\n\npageStartup(LifeTimeSpecModule, LifeTimeSPecComponent);\n"
  },
  {
    "path": "test/hello-world-app/src/spec/life-time-spec/life-time.component.ts",
    "content": "import { Component, NgZone, ViewChild } from '@angular/core';\nimport { ComponentFinderService } from 'angular-miniprogram';\nimport { MiniProgramComponentInstance } from 'angular-miniprogram/platform/type';\nimport { BehaviorSubject } from 'rxjs';\nimport { LifeTimeComponent } from '../../spec-component/life-time/life-time.component';\nimport { nodeExist } from '../util';\n\n@Component({\n  selector: 'app-life-time-spec',\n  template: `<app-life-time #instance></app-life-time>`,\n})\nexport class LifeTimeSPecComponent {\n  testFinish$$ = new BehaviorSubject(undefined);\n  static mpPageOptions: WechatMiniprogram.Page.Options<{}, {}> = {\n    onLoad: function () {\n      console.log('test-onLoad');\n    },\n    onShow: function () {\n      console.log('test-onShow');\n    },\n    onReady: function (\n      this: WechatMiniprogram.Page.Instance<{}, {}> &\n        MiniProgramComponentInstance<LifeTimeSPecComponent>\n    ) {\n      console.log('test-onReady');\n      this.__ngComponentInstance.testFinish$$.complete();\n    },\n  };\n  @ViewChild('instance', { static: true }) instance: LifeTimeComponent;\n  constructor(\n    private componentFinderService: ComponentFinderService,\n    private ngZone: NgZone\n  ) {}\n  ngOnInit(): void {\n    console.log('test-ngOnInit');\n    this.ngZone.runOutsideAngular(() => {\n      setTimeout(() => {\n        this.testFinish$$.complete();\n      }, 3000);\n    });\n  }\n}\n"
  },
  {
    "path": "test/hello-world-app/src/spec/life-time-spec/life-time.module.ts",
    "content": "import { NgModule } from '@angular/core';\n\nimport { LifeTimeModule } from '../../spec-component/life-time/life-time.module';\nimport { LifeTimeSPecComponent } from './life-time.component';\n@NgModule({\n  imports: [LifeTimeModule],\n  declarations: [LifeTimeSPecComponent],\n  exports: [LifeTimeSPecComponent],\n})\nexport class LifeTimeSpecModule {}\n"
  },
  {
    "path": "test/hello-world-app/src/spec/life-time-spec/life-time.spec.ts",
    "content": "import { componentTestComplete, getComponent, openComponent } from '../util';\nimport { LifeTimeSPecComponent } from './life-time.component';\ndescribe('LifeTimeSPecComponent', () => {\n  beforeEach(async () => {\n    await openComponent(`/spec/life-time-spec/life-time-spec-entry`);\n  });\n  it('run', (done) => {\n    let pages = getCurrentPages();\n    let page = pages[0];\n    let component = getComponent<LifeTimeSPecComponent>(page);\n    componentTestComplete(component.testFinish$$).then(() => {\n      done();\n    });\n  });\n});\n"
  },
  {
    "path": "test/hello-world-app/src/spec/ng-content-spec/ng-content-spec.entry.ts",
    "content": "import { pageStartup } from 'angular-miniprogram';\nimport { NgContentSpecModule } from './ng-content.module';\nimport { NgContentSpecComponent } from './ng-content.component';\npageStartup(NgContentSpecModule, NgContentSpecComponent);\n"
  },
  {
    "path": "test/hello-world-app/src/spec/ng-content-spec/ng-content.component.ts",
    "content": "import { Component, OnInit, ViewChild } from '@angular/core';\nimport { ComponentFinderService } from 'angular-miniprogram';\nimport { MiniProgramComponentInstance } from 'angular-miniprogram/platform/type';\nimport { BehaviorSubject } from 'rxjs';\nimport { NgContentComponent } from '../../spec-component/ng-content/ng-content.component';\nimport { nodeExist, nodeNotEmpty } from '../util';\n\n@Component({\n  selector: 'app-ng-content-spec',\n  template: `<app-ng-content #instance\n    ><div class=\"container\">container</div></app-ng-content\n  >`,\n})\nexport class NgContentSpecComponent {\n  testFinish$$ = new BehaviorSubject(undefined);\n  static mpPageOptions: WechatMiniprogram.Page.Options<{}, {}> = {\n    onReady: function (\n      this: WechatMiniprogram.Page.Instance<{}, {}> &\n        MiniProgramComponentInstance<NgContentSpecComponent>\n    ) {\n      this.__ngComponentInstance.componentFinderService\n        .get(this.__ngComponentInstance.instance)\n        .then(\n          async (\n            item: WechatMiniprogram.Page.Instance<\n              WechatMiniprogram.IAnyObject,\n              WechatMiniprogram.IAnyObject\n            >\n          ) => {\n            let query = item.createSelectorQuery();\n            expect(await nodeExist(query, '.wrapper-1'))\n              .withContext('wrapper')\n              .toBe(true);\n            // 投影进去的元素没有被正确的查询到,原因未知,但是父级元素高度却产生了变化\n            expect(await nodeNotEmpty(query, '.wrapper-1'))\n              .withContext('wrapper-1')\n              .toBe(true);\n            expect(await nodeNotEmpty(query, '.wrapper-2'))\n              .withContext('wrapper-2')\n              .toBe(false);\n            this.__ngComponentInstance.testFinish$$.complete();\n          }\n        );\n    },\n  };\n  @ViewChild('instance', { static: true }) instance: NgContentComponent;\n  constructor(private componentFinderService: ComponentFinderService) {}\n  ngOnInit(): void {}\n}\n"
  },
  {
    "path": "test/hello-world-app/src/spec/ng-content-spec/ng-content.module.ts",
    "content": "import { NgModule } from '@angular/core';\nimport { NgContentModule } from '../../spec-component/ng-content/ng-content.module';\nimport { NgContentSpecComponent } from './ng-content.component';\n\n@NgModule({\n  imports: [NgContentModule],\n  declarations: [NgContentSpecComponent],\n})\nexport class NgContentSpecModule {}\n"
  },
  {
    "path": "test/hello-world-app/src/spec/ng-content-spec/ng-content.spec.ts",
    "content": "import { componentTestComplete, getComponent, openComponent } from '../util';\nimport { NgContentSpecComponent } from './ng-content.component';\ndescribe('NgContentSpecComponent', () => {\n  beforeEach(async () => {\n    await openComponent(`/spec/ng-content-spec/ng-content-spec-entry`);\n  });\n  it('run', (done) => {\n    let pages = getCurrentPages();\n    let page = pages[0];\n    let component = getComponent<NgContentSpecComponent>(page);\n    componentTestComplete(component.testFinish$$).then(() => {\n      done();\n    });\n  });\n});\n"
  },
  {
    "path": "test/hello-world-app/src/spec/ng-for-spec/ng-for-spec.entry.ts",
    "content": "import { pageStartup } from 'angular-miniprogram';\nimport { NgForSpecModule } from './ng-for.module';\nimport { NgForSPecComponent } from './ng-for.component';\n\npageStartup(NgForSpecModule, NgForSPecComponent);\n"
  },
  {
    "path": "test/hello-world-app/src/spec/ng-for-spec/ng-for.component.ts",
    "content": "import { Component, OnInit, ViewChild } from '@angular/core';\nimport { ComponentFinderService } from 'angular-miniprogram';\nimport { MiniProgramComponentInstance } from 'angular-miniprogram/platform/type';\nimport { BehaviorSubject } from 'rxjs';\nimport { NgForComponent } from '../../spec-component/ng-for/ng-for.component';\nimport { nodeExist } from '../util';\n\n@Component({\n  selector: 'app-ng-for-spec',\n  template: `<app-ng-for #instance [list]=\"list\"></app-ng-for>`,\n})\nexport class NgForSPecComponent {\n  list = ['item1', 'item2', 'item3'];\n  testFinish$$ = new BehaviorSubject(undefined);\n  static mpPageOptions: WechatMiniprogram.Page.Options<{}, {}> = {\n    onReady: function (\n      this: WechatMiniprogram.Page.Instance<{}, {}> &\n        MiniProgramComponentInstance<NgForSPecComponent>\n    ) {\n      this.__ngComponentInstance.componentFinderService\n        .get(this.__ngComponentInstance.instance)\n        .then(\n          async (\n            item: WechatMiniprogram.Page.Instance<\n              WechatMiniprogram.IAnyObject,\n              WechatMiniprogram.IAnyObject\n            >\n          ) => {\n            let query = item.createSelectorQuery();\n            for (let i = 0; i < this.__ngComponentInstance.list.length; i++) {\n              expect(await nodeExist(query, `.ng-for-${i}`)).toBe(true);\n            }\n\n            this.__ngComponentInstance.testFinish$$.complete();\n          }\n        );\n    },\n  };\n  @ViewChild('instance', { static: true }) instance: NgForComponent;\n  constructor(private componentFinderService: ComponentFinderService) {}\n  ngOnInit(): void {}\n}\n"
  },
  {
    "path": "test/hello-world-app/src/spec/ng-for-spec/ng-for.module.ts",
    "content": "import { NgModule } from '@angular/core';\n\nimport { NgForModule } from '../../spec-component/ng-for/ng-for.module';\nimport { NgForSPecComponent } from './ng-for.component';\n@NgModule({\n  imports: [NgForModule],\n  declarations: [NgForSPecComponent],\n  exports: [NgForSPecComponent],\n})\nexport class NgForSpecModule {}\n"
  },
  {
    "path": "test/hello-world-app/src/spec/ng-for-spec/ng-for.spec.ts",
    "content": "import { componentTestComplete, getComponent, openComponent } from '../util';\nimport { NgForSPecComponent } from './ng-for.component';\ndescribe('NgForSPecComponent', () => {\n  beforeEach(async () => {\n    await openComponent(`/spec/ng-for-spec/ng-for-spec-entry`);\n  });\n  it('run', (done) => {\n    let pages = getCurrentPages();\n    let page = pages[0];\n    let component = getComponent<NgForSPecComponent>(page);\n    componentTestComplete(component.testFinish$$).then(() => {\n      done();\n    });\n  });\n});\n"
  },
  {
    "path": "test/hello-world-app/src/spec/ng-if-spec/ng-if-spec.entry.ts",
    "content": "import { pageStartup } from 'angular-miniprogram';\nimport { NgIfSpecModule } from './ng-if.module';\nimport { NgIfSPecComponent } from './ng-if.component';\n\npageStartup(NgIfSpecModule, NgIfSPecComponent);\n"
  },
  {
    "path": "test/hello-world-app/src/spec/ng-if-spec/ng-if.component.ts",
    "content": "import { Component, ViewChild } from '@angular/core';\nimport { ComponentFinderService } from 'angular-miniprogram';\nimport { MiniProgramComponentInstance } from 'angular-miniprogram/platform/type';\nimport { BehaviorSubject } from 'rxjs';\nimport { NgIfComponent } from '../../spec-component/ng-if/ng-if.component';\nimport { nodeExist } from '../util';\n\n@Component({\n  selector: 'app-ng-if-spec',\n  template: `<app-ng-if #instance></app-ng-if>`,\n})\nexport class NgIfSPecComponent {\n  testFinish$$ = new BehaviorSubject(undefined);\n  static mpPageOptions: WechatMiniprogram.Page.Options<{}, {}> = {\n    onReady: function (\n      this: WechatMiniprogram.Page.Instance<{}, {}> &\n        MiniProgramComponentInstance<NgIfSPecComponent>\n    ) {\n      this.__ngComponentInstance.componentFinderService\n        .get(this.__ngComponentInstance.instance)\n        .then(\n          async (\n            item: WechatMiniprogram.Page.Instance<{}, {}> &\n              MiniProgramComponentInstance<NgIfSPecComponent>\n          ) => {\n            let query = item.createSelectorQuery();\n\n            expect(await nodeExist(query, '.true-1')).toBe(true);\n            expect(await nodeExist(query, '.false-1')).toBe(false);\n            this.__ngComponentInstance.testFinish$$.complete();\n          }\n        );\n    },\n  };\n  @ViewChild('instance', { static: true }) instance: NgIfComponent;\n  constructor(private componentFinderService: ComponentFinderService) {}\n  ngOnInit(): void {}\n}\n"
  },
  {
    "path": "test/hello-world-app/src/spec/ng-if-spec/ng-if.module.ts",
    "content": "import { NgModule } from '@angular/core';\n\nimport { NgIfModule } from '../../spec-component/ng-if/ng-if.module';\nimport { NgIfSPecComponent } from './ng-if.component';\n@NgModule({\n  imports: [NgIfModule],\n  declarations: [NgIfSPecComponent],\n  exports: [NgIfSPecComponent],\n})\nexport class NgIfSpecModule {}\n"
  },
  {
    "path": "test/hello-world-app/src/spec/ng-if-spec/ng-if.spec.ts",
    "content": "import { componentTestComplete, getComponent, openComponent } from '../util';\nimport { NgIfSPecComponent } from './ng-if.component';\ndescribe('NgIfSPecComponent', () => {\n  beforeEach(async () => {\n    await openComponent(`/spec/ng-if-spec/ng-if-spec-entry`);\n  });\n  it('run', (done) => {\n    let pages = getCurrentPages();\n    let page = pages[0];\n    let component = getComponent<NgIfSPecComponent>(page);\n    componentTestComplete(component.testFinish$$).then(() => {\n      done();\n    });\n  });\n});\n"
  },
  {
    "path": "test/hello-world-app/src/spec/ng-library-import-spec/ng-library-import-spec.entry.ts",
    "content": "import { pageStartup } from 'angular-miniprogram';\nimport { NgLibraryImportSpecModule } from './ng-library-import.module';\nimport { NgLibraryImportSPecComponent } from './ng-library-import.component';\n\npageStartup(NgLibraryImportSpecModule, NgLibraryImportSPecComponent);\n"
  },
  {
    "path": "test/hello-world-app/src/spec/ng-library-import-spec/ng-library-import.component.ts",
    "content": "import { Component, ViewChild } from '@angular/core';\nimport { ComponentFinderService } from 'angular-miniprogram';\nimport { MiniProgramComponentInstance } from 'angular-miniprogram/platform/type';\nimport { BehaviorSubject } from 'rxjs';\nimport { NgLibraryImportComponent } from '../../spec-component/ng-library-import/ng-library-import.component';\nimport { nodeExist } from '../util';\n\n@Component({\n  selector: 'app-ng-library-import-spec',\n  template: `<app-ng-library-import #instance></app-ng-library-import>`,\n})\nexport class NgLibraryImportSPecComponent {\n  testFinish$$ = new BehaviorSubject(undefined);\n  static mpPageOptions: WechatMiniprogram.Page.Options<{}, {}> = {\n    onReady: function (\n      this: WechatMiniprogram.Page.Instance<{}, {}> &\n        MiniProgramComponentInstance<NgLibraryImportSPecComponent>\n    ) {\n      this.__ngComponentInstance.componentFinderService\n        .get(this.__ngComponentInstance.instance.libComp1)\n        .then(\n          async (\n            item: WechatMiniprogram.Page.Instance<\n              WechatMiniprogram.IAnyObject,\n              WechatMiniprogram.IAnyObject\n            >\n          ) => {\n            let query = item.createSelectorQuery();\n\n            expect(await nodeExist(query, '.lib-comp1-content')).toBe(true);\n\n            this.__ngComponentInstance.testFinish$$.complete();\n          }\n        );\n    },\n  };\n  @ViewChild('instance', { static: true }) instance: NgLibraryImportComponent;\n  constructor(private componentFinderService: ComponentFinderService) {}\n  ngOnInit(): void {}\n}\n"
  },
  {
    "path": "test/hello-world-app/src/spec/ng-library-import-spec/ng-library-import.module.ts",
    "content": "import { NgModule } from '@angular/core';\n\nimport { NgLibraryImportSPecComponent } from './ng-library-import.component';\nimport { NgLibraryImportModule } from '../../spec-component/ng-library-import/ng-library-import.module';\n@NgModule({\n  imports: [NgLibraryImportModule],\n  declarations: [NgLibraryImportSPecComponent],\n})\nexport class NgLibraryImportSpecModule {}\n"
  },
  {
    "path": "test/hello-world-app/src/spec/ng-library-import-spec/ng-library-import.spec.ts",
    "content": "import { componentTestComplete, getComponent, openComponent } from '../util';\nimport { NgLibraryImportSPecComponent } from './ng-library-import.component';\ndescribe('NgLibraryImportSPecComponent', () => {\n  beforeEach(async () => {\n    await openComponent(\n      `/spec/ng-library-import-spec/ng-library-import-spec-entry`\n    );\n  });\n  it('run', (done) => {\n    let pages = getCurrentPages();\n    let page = pages[0];\n    let component = getComponent<NgLibraryImportSPecComponent>(page);\n    componentTestComplete(component.testFinish$$).then(() => {\n      done();\n    });\n  });\n});\n"
  },
  {
    "path": "test/hello-world-app/src/spec/ng-switch-spec/ng-switch-spec.entry.ts",
    "content": "import { pageStartup } from 'angular-miniprogram';\nimport { NgSwitchSpecModule } from './ng-switch.module';\nimport { NgSwitchSPecComponent } from './ng-switch.component';\n\npageStartup(NgSwitchSpecModule, NgSwitchSPecComponent);\n"
  },
  {
    "path": "test/hello-world-app/src/spec/ng-switch-spec/ng-switch.component.ts",
    "content": "import { Component, ViewChild } from '@angular/core';\nimport { ComponentFinderService } from 'angular-miniprogram';\nimport { MiniProgramComponentInstance } from 'angular-miniprogram/platform/type';\nimport { BehaviorSubject } from 'rxjs';\nimport { NgSwitchComponent } from '../../spec-component/ng-switch/ng-switch.component';\nimport { nodeExist } from '../util';\n\n@Component({\n  selector: 'app-ng-switch-spec',\n  template: `<app-ng-switch #instance></app-ng-switch>`,\n})\nexport class NgSwitchSPecComponent {\n  testFinish$$ = new BehaviorSubject(undefined);\n  static mpPageOptions: WechatMiniprogram.Page.Options<{}, {}> = {\n    onReady: function (\n      this: WechatMiniprogram.Page.Instance<{}, {}> &\n        MiniProgramComponentInstance<NgSwitchSPecComponent>\n    ) {\n      this.__ngComponentInstance.componentFinderService\n        .get(this.__ngComponentInstance.instance)\n        .then(\n          async (\n            item: WechatMiniprogram.Page.Instance<\n              WechatMiniprogram.IAnyObject,\n              WechatMiniprogram.IAnyObject\n            >\n          ) => {\n            let query = item.createSelectorQuery();\n\n            expect(await nodeExist(query, '.switch-case1')).toBe(true);\n            expect(await nodeExist(query, '.switch-case2')).toBe(false);\n            expect(await nodeExist(query, '.switch-default')).toBe(false);\n            this.__ngComponentInstance.testFinish$$.complete();\n          }\n        );\n    },\n  };\n  @ViewChild('instance', { static: true }) instance: NgSwitchComponent;\n  constructor(private componentFinderService: ComponentFinderService) {}\n  ngOnInit(): void {}\n}\n"
  },
  {
    "path": "test/hello-world-app/src/spec/ng-switch-spec/ng-switch.module.ts",
    "content": "import { NgModule } from '@angular/core';\n\nimport { NgSwitchModule } from '../../spec-component/ng-switch/ng-switch.module';\nimport { NgSwitchSPecComponent } from './ng-switch.component';\n@NgModule({\n  imports: [NgSwitchModule],\n  declarations: [NgSwitchSPecComponent],\n  exports: [NgSwitchSPecComponent],\n})\nexport class NgSwitchSpecModule {}\n"
  },
  {
    "path": "test/hello-world-app/src/spec/ng-switch-spec/ng-switch.spec.ts",
    "content": "import { componentTestComplete, getComponent, openComponent } from '../util';\nimport { NgSwitchSPecComponent } from './ng-switch.component';\ndescribe('NgSwitchSPecComponent', () => {\n  beforeEach(async () => {\n    await openComponent(`/spec/ng-switch-spec/ng-switch-spec-entry`);\n  });\n  it('run', (done) => {\n    let pages = getCurrentPages();\n    let page = pages[0];\n    let component = getComponent<NgSwitchSPecComponent>(page);\n    componentTestComplete(component.testFinish$$).then(() => {\n      done();\n    });\n  });\n});\n"
  },
  {
    "path": "test/hello-world-app/src/spec/ng-template-outlet-spec/ng-template-outlet-spec.entry.ts",
    "content": "import { pageStartup } from 'angular-miniprogram';\nimport { NgTemplateOutletSpecModule } from './ng-template-outlet.module';\nimport { NgTemplateOutletSPecComponent } from './ng-template-outlet.component';\n\npageStartup(NgTemplateOutletSpecModule, NgTemplateOutletSPecComponent);\n"
  },
  {
    "path": "test/hello-world-app/src/spec/ng-template-outlet-spec/ng-template-outlet.component.ts",
    "content": "import { Component, ViewChild } from '@angular/core';\nimport { ComponentFinderService } from 'angular-miniprogram';\nimport { MiniProgramComponentInstance } from 'angular-miniprogram/platform/type';\nimport { BehaviorSubject } from 'rxjs';\nimport { NgTemplateOutletComponent } from '../../spec-component/ng-template-outlet/ng-template-outlet.component';\nimport { nodeExist } from '../util';\n\n@Component({\n  selector: 'app-ng-template-outlet-spec',\n  template: `<app-ng-template-outlet #instance></app-ng-template-outlet>`,\n})\nexport class NgTemplateOutletSPecComponent {\n  testFinish$$ = new BehaviorSubject(undefined);\n  static mpPageOptions: WechatMiniprogram.Page.Options<{}, {}> = {\n    onReady: function (\n      this: WechatMiniprogram.Page.Instance<{}, {}> &\n        MiniProgramComponentInstance<NgTemplateOutletSPecComponent>\n    ) {\n      this.__ngComponentInstance.componentFinderService\n        .get(this.__ngComponentInstance.instance)\n        .then(\n          async (\n            item: WechatMiniprogram.Page.Instance<\n              WechatMiniprogram.IAnyObject,\n              WechatMiniprogram.IAnyObject\n            >\n          ) => {\n            let query = item.createSelectorQuery();\n\n            expect(await nodeExist(query, '.template-content-1')).toBe(true);\n            expect(await nodeExist(query, '.template-content-2')).toBe(false);\n            this.__ngComponentInstance.testFinish$$.complete();\n          }\n        );\n    },\n  };\n  @ViewChild('instance', { static: true }) instance: NgTemplateOutletComponent;\n  constructor(private componentFinderService: ComponentFinderService) {}\n  ngOnInit(): void {}\n}\n"
  },
  {
    "path": "test/hello-world-app/src/spec/ng-template-outlet-spec/ng-template-outlet.module.ts",
    "content": "import { NgModule } from '@angular/core';\n\nimport { NgTemplateOutletModule } from '../../spec-component/ng-template-outlet/ng-template-outlet.module';\nimport { NgTemplateOutletSPecComponent } from './ng-template-outlet.component';\n@NgModule({\n  imports: [NgTemplateOutletModule],\n  declarations: [NgTemplateOutletSPecComponent],\n  exports: [NgTemplateOutletSPecComponent],\n})\nexport class NgTemplateOutletSpecModule {}\n"
  },
  {
    "path": "test/hello-world-app/src/spec/ng-template-outlet-spec/ng-template-outlet.spec.ts",
    "content": "import { componentTestComplete, getComponent, openComponent } from '../util';\nimport { NgTemplateOutletSPecComponent } from './ng-template-outlet.component';\ndescribe('NgTemplateOutletSPecComponent', () => {\n  beforeEach(async () => {\n    await openComponent(\n      `/spec/ng-template-outlet-spec/ng-template-outlet-spec-entry`\n    );\n  });\n  it('run', (done) => {\n    let pages = getCurrentPages();\n    let page = pages[0];\n    let component = getComponent<NgTemplateOutletSPecComponent>(page);\n    componentTestComplete(component.testFinish$$).then(() => {\n      done();\n    });\n  });\n});\n"
  },
  {
    "path": "test/hello-world-app/src/spec/self-template-spec/self-template-spec.entry.ts",
    "content": "import { pageStartup } from 'angular-miniprogram';\nimport { SelfTemplateSpecModule } from './self-template.module';\nimport { SelfTemplateSPecComponent } from './self-template.component';\n\npageStartup(SelfTemplateSpecModule, SelfTemplateSPecComponent);\n"
  },
  {
    "path": "test/hello-world-app/src/spec/self-template-spec/self-template.component.ts",
    "content": "import { Component, ViewChild } from '@angular/core';\nimport { ComponentFinderService } from 'angular-miniprogram';\nimport { MiniProgramComponentInstance } from 'angular-miniprogram/platform/type';\nimport { BehaviorSubject } from 'rxjs';\nimport { SelfTemplateComponent } from '../../spec-component/self-template/self-template.component';\nimport { nodeExist } from '../util';\n\n@Component({\n  selector: 'app-self-template-spec',\n  template: ` <ng-template #$$mp$$__self__$$self1\n      ><div class=\"content-1\">content-1</div></ng-template\n    >\n    <app-self-template\n      #instance\n      [template1]=\"$$mp$$__self__$$self1\"\n    ></app-self-template>`,\n})\nexport class SelfTemplateSPecComponent {\n  testFinish$$ = new BehaviorSubject(undefined);\n  static mpPageOptions: WechatMiniprogram.Page.Options<{}, {}> = {\n    onReady: function (\n      this: WechatMiniprogram.Page.Instance<{}, {}> &\n        MiniProgramComponentInstance<SelfTemplateSPecComponent>\n    ) {\n      this.__ngComponentInstance.componentFinderService\n        .get(this.__ngComponentInstance.instance)\n        .then(\n          async (\n            item: WechatMiniprogram.Page.Instance<\n              WechatMiniprogram.IAnyObject,\n              WechatMiniprogram.IAnyObject\n            >\n          ) => {\n            let query = item.createSelectorQuery();\n\n            expect(await nodeExist(query, '.container-1 .content-1')).toBe(\n              true\n            );\n            this.__ngComponentInstance.testFinish$$.complete();\n          }\n        );\n    },\n  };\n  @ViewChild('instance', { static: true }) instance: SelfTemplateComponent;\n  constructor(private componentFinderService: ComponentFinderService) {}\n  ngOnInit(): void {}\n}\n"
  },
  {
    "path": "test/hello-world-app/src/spec/self-template-spec/self-template.module.ts",
    "content": "import { NgModule } from '@angular/core';\n\nimport { SelfTemplateModule } from '../../spec-component/self-template/self-template.module';\nimport { SelfTemplateSPecComponent } from './self-template.component';\n@NgModule({\n  imports: [SelfTemplateModule],\n  declarations: [SelfTemplateSPecComponent],\n  exports: [SelfTemplateSPecComponent],\n})\nexport class SelfTemplateSpecModule {}\n"
  },
  {
    "path": "test/hello-world-app/src/spec/self-template-spec/self-template.spec.ts",
    "content": "import { componentTestComplete, getComponent, openComponent } from '../util';\nimport { SelfTemplateSPecComponent } from './self-template.component';\ndescribe('SelfTemplateSPecComponent', () => {\n  beforeEach(async () => {\n    await openComponent(`/spec/self-template-spec/self-template-spec-entry`);\n  });\n  it('run', (done) => {\n    let pages = getCurrentPages();\n    let page = pages[0];\n    let component = getComponent<SelfTemplateSPecComponent>(page);\n    componentTestComplete(component.testFinish$$).then(() => {\n      done();\n    });\n  });\n});\n"
  },
  {
    "path": "test/hello-world-app/src/spec/style-class-spec/style-class-spec.component.ts",
    "content": "import { Component, OnInit, ViewChild } from '@angular/core';\nimport { ComponentFinderService } from 'angular-miniprogram';\nimport { MiniProgramComponentInstance } from 'angular-miniprogram/platform/type';\nimport { BehaviorSubject } from 'rxjs';\nimport { StyleClassComponent } from '../../spec-component/style-class/style-class.component';\nimport { fields, nodeExist } from '../util';\n\n@Component({\n  selector: 'app-style-class-spec',\n  template: `<app-style-class #instance></app-style-class>`,\n})\nexport class StyleClassSpecComponent {\n  testFinish$$ = new BehaviorSubject(undefined);\n  static mpPageOptions: WechatMiniprogram.Page.Options<{}, {}> = {\n    onReady: function (\n      this: WechatMiniprogram.Page.Instance<{}, {}> &\n        MiniProgramComponentInstance<StyleClassSpecComponent>\n    ) {\n      this.__ngComponentInstance.componentFinderService\n        .get(this.__ngComponentInstance.instance)\n        .then(\n          async (\n            item: WechatMiniprogram.Page.Instance<\n              WechatMiniprogram.IAnyObject,\n              WechatMiniprogram.IAnyObject\n            >\n          ) => {\n            let query = item.createSelectorQuery();\n\n            expect(await nodeExist(query, '.class-1')).toBe(true, 'class-1');\n            expect(await nodeExist(query, '.class-2')).toBe(true, 'class-2');\n            let result = await fields(query, '.class-2', {\n              computedStyle: ['backgroundColor'],\n            });\n            expect(result).toEqual({ backgroundColor: 'rgb(255, 0, 0)' });\n            this.__ngComponentInstance.testFinish$$.complete();\n          }\n        );\n    },\n  };\n  @ViewChild('instance', { static: true }) instance: StyleClassComponent;\n  constructor(private componentFinderService: ComponentFinderService) {}\n}\n"
  },
  {
    "path": "test/hello-world-app/src/spec/style-class-spec/style-class-spec.entry.ts",
    "content": "import { pageStartup } from 'angular-miniprogram';\nimport { StyleClassSpecModule } from './style-class-spec.module';\nimport { StyleClassSpecComponent } from './style-class-spec.component';\npageStartup(StyleClassSpecModule, StyleClassSpecComponent);\n"
  },
  {
    "path": "test/hello-world-app/src/spec/style-class-spec/style-class-spec.module.ts",
    "content": "import { NgModule } from '@angular/core';\nimport { StyleClassModule } from 'src/spec-component/style-class/style-class.module';\n\nimport { StyleClassSpecComponent } from './style-class-spec.component';\n\n@NgModule({\n  imports: [StyleClassModule],\n  declarations: [StyleClassSpecComponent],\n})\nexport class StyleClassSpecModule {}\n"
  },
  {
    "path": "test/hello-world-app/src/spec/style-class-spec/style-class-spec.spec.ts",
    "content": "import { componentTestComplete, getComponent, openComponent } from '../util';\nimport { StyleClassSpecComponent } from './style-class-spec.component';\n\ndescribe('StyleClassSpecComponent', () => {\n  beforeEach(async () => {\n    await openComponent(`/spec/style-class-spec/style-class-spec-entry`);\n  });\n  it('run', (done) => {\n    let pages = getCurrentPages();\n    let page = pages[0];\n    let component = getComponent<StyleClassSpecComponent>(page);\n    componentTestComplete(component.testFinish$$).then(() => {\n      done();\n    });\n  });\n});\n"
  },
  {
    "path": "test/hello-world-app/src/spec/tag-view-convert-spec/tag-view-convert-spec.entry.ts",
    "content": "import { pageStartup } from 'angular-miniprogram';\nimport { TagViewConvertSpecModule } from './tag-view-convert.module';\nimport { TagViewConvertSpecComponent } from './tag-view-convert.component';\npageStartup(TagViewConvertSpecModule, TagViewConvertSpecComponent);\n"
  },
  {
    "path": "test/hello-world-app/src/spec/tag-view-convert-spec/tag-view-convert.component.ts",
    "content": "import { Component, ViewChild } from '@angular/core';\nimport { ComponentFinderService } from 'angular-miniprogram';\nimport { MiniProgramComponentInstance } from 'angular-miniprogram/platform/type';\nimport { BehaviorSubject } from 'rxjs';\nimport { TagViewConvertComponent } from '../../spec-component/tag-view-convert/tag-view-convert.component';\nimport { nodeExist } from '../util';\n\n@Component({\n  selector: 'app-tag-view-convert-spec',\n  template: `<app-tag-view-convert #instance></app-tag-view-convert>`,\n})\nexport class TagViewConvertSpecComponent {\n  testFinish$$ = new BehaviorSubject(undefined);\n  static mpPageOptions: WechatMiniprogram.Page.Options<{}, {}> = {\n    onReady: function (\n      this: WechatMiniprogram.Page.Instance<{}, {}> &\n        MiniProgramComponentInstance<TagViewConvertSpecComponent>\n    ) {\n      this.__ngComponentInstance.componentFinderService\n        .get(this.__ngComponentInstance.instance)\n        .then(\n          async (\n            item: WechatMiniprogram.Page.Instance<\n              WechatMiniprogram.IAnyObject,\n              WechatMiniprogram.IAnyObject\n            >\n          ) => {\n            let query = item.createSelectorQuery();\n            expect(await nodeExist(query, '.tag-name-div')).toBe(true);\n            expect(await nodeExist(query, '.tag-name-span')).toBe(true);\n\n            this.__ngComponentInstance.testFinish$$.complete();\n          }\n        );\n    },\n  };\n  @ViewChild('instance', { static: true }) instance: TagViewConvertComponent;\n  constructor(private componentFinderService: ComponentFinderService) {}\n  ngOnInit(): void {}\n}\n"
  },
  {
    "path": "test/hello-world-app/src/spec/tag-view-convert-spec/tag-view-convert.module.ts",
    "content": "import { NgModule } from '@angular/core';\nimport { TagViewConvertModule } from '../../spec-component/tag-view-convert/tag-view-convert.module';\n\nimport { TagViewConvertSpecComponent } from './tag-view-convert.component';\n\n@NgModule({\n  imports: [TagViewConvertModule],\n  declarations: [TagViewConvertSpecComponent],\n})\nexport class TagViewConvertSpecModule {}\n"
  },
  {
    "path": "test/hello-world-app/src/spec/tag-view-convert-spec/tag-view-convert.spec.ts",
    "content": "import { componentTestComplete, getComponent, openComponent } from '../util';\nimport { TagViewConvertSpecComponent } from './tag-view-convert.component';\n\ndescribe('TagViewConvertSpecComponent', () => {\n  beforeEach(async () => {\n    await openComponent(\n      `/spec/tag-view-convert-spec/tag-view-convert-spec-entry`\n    );\n  });\n  it('run', (done) => {\n    let pages = getCurrentPages();\n    let page = pages[0];\n    let component = getComponent<TagViewConvertSpecComponent>(page);\n    componentTestComplete(component.testFinish$$).then(() => {\n      done();\n    });\n  });\n});\n"
  },
  {
    "path": "test/hello-world-app/src/spec/util/index.ts",
    "content": "export * from './open-component';\nexport * from './node-query';\nexport * from './page-info';\n"
  },
  {
    "path": "test/hello-world-app/src/spec/util/node-query.ts",
    "content": "export function nodeExist(\n  query: WechatMiniprogram.SelectorQuery,\n  selector: string\n) {\n  return new Promise<boolean>((res, rej) => {\n    try {\n      query\n        .select(selector)\n        .context((data) => {\n          res(!!data);\n        })\n        .exec();\n    } catch (error) {\n      rej(error);\n    }\n  });\n}\nexport function nodeNotEmpty(\n  query: WechatMiniprogram.SelectorQuery,\n  selector: string\n) {\n  return new Promise<boolean>((res, rej) => {\n    try {\n      query\n        .select(selector)\n        .boundingClientRect((data) => {\n          res(!!data.height);\n        })\n        .exec();\n    } catch (error) {\n      rej(error);\n    }\n  });\n}\n\nexport function fields(\n  query: WechatMiniprogram.SelectorQuery,\n  selector: string,\n  fields: WechatMiniprogram.Fields\n) {\n  return new Promise<any>((res, rej) => {\n    try {\n      query\n        .select(selector)\n        .fields(fields, (data) => {\n          res(data);\n        })\n        .exec();\n    } catch (error) {\n      rej(error);\n    }\n  });\n}\n"
  },
  {
    "path": "test/hello-world-app/src/spec/util/open-component.ts",
    "content": "import { Observable } from 'rxjs';\nimport { filter, take, tap } from 'rxjs/operators';\n\nexport function routeEvent() {\n  return new Observable<any>((ob) => {\n    (wx as any).onAppRoute((result) => {\n      ob.next(result);\n    });\n  });\n}\n\nexport async function openComponent(url: string) {\n  try {\n    await new Promise((res, rej) =>\n      wx.reLaunch({\n        url: url,\n        fail: rej,\n        success: res,\n      })\n    );\n  } catch (error) {\n    throw new Error(error);\n  }\n  await routeEvent()\n    .pipe(\n      tap((res) => {\n        console.log('生命周期', res);\n      }),\n      filter((item) => item.openType === 'reLaunch'),\n      take(1)\n    )\n    .toPromise();\n}\n"
  },
  {
    "path": "test/hello-world-app/src/spec/util/page-info.ts",
    "content": "import type { MiniProgramComponentVariable } from 'angular-miniprogram/platform/type';\nimport { BehaviorSubject } from 'rxjs';\n\nexport function assertMiniProgramComponent(\n  page\n): page is MiniProgramComponentVariable {\n  return page.__ngComponentInstance ? true : false;\n}\n\nexport function getComponent<T>(\n  page: WechatMiniprogram.Page.Instance<\n    WechatMiniprogram.IAnyObject,\n    WechatMiniprogram.IAnyObject\n  >\n): T {\n  return page.__ngComponentInstance;\n}\n\nexport function componentTestComplete(subject: BehaviorSubject<unknown>) {\n  return new Promise<void>((res) => {\n    subject.subscribe({\n      complete: () => {\n        res();\n      },\n    });\n  });\n}\n"
  },
  {
    "path": "test/hello-world-app/src/spec-component/life-time/life-time.component.ts",
    "content": "import { Component, OnInit } from '@angular/core';\nimport { MiniProgramComponentInstance } from 'angular-miniprogram/platform/type';\n\n@Component({\n  selector: 'app-life-time',\n  template: '',\n})\nexport class LifeTimeComponent implements OnInit {\n  static mpComponentOptions: WechatMiniprogram.Component.Options<{}, {}, {}> = {\n    lifetimes: {\n      created: function (this: MiniProgramComponentInstance) {\n        console.log('created', this.__isLink);\n      },\n      attached: function () {\n        console.log('attached', this.__isLink);\n      },\n      ready: function () {\n        console.log('ready');\n      },\n      moved: function () {\n        console.log('moved');\n      },\n      detached: function () {\n        console.log('detached');\n      },\n      error: function () {\n        console.log('error');\n      },\n    },\n    pageLifetimes: {\n      show: function () {\n        console.log('page-show');\n      },\n      hide: function () {\n        console.log('page-hide');\n      },\n      resize: function () {\n        console.log('page-resize');\n      },\n    },\n  };\n  constructor() {}\n\n  ngOnInit() {\n    console.log('ngOnInit');\n  }\n}\n"
  },
  {
    "path": "test/hello-world-app/src/spec-component/life-time/life-time.entry.ts",
    "content": "import { componentRegistry } from 'angular-miniprogram';\nimport { LifeTimeComponent } from './life-time.component';\ncomponentRegistry(LifeTimeComponent);\n"
  },
  {
    "path": "test/hello-world-app/src/spec-component/life-time/life-time.module.ts",
    "content": "import { NgModule } from '@angular/core';\nimport { LifeTimeComponent } from './life-time.component';\n\n@NgModule({\n  imports: [],\n  declarations: [LifeTimeComponent],\n  exports: [LifeTimeComponent],\n})\nexport class LifeTimeModule {}\n"
  },
  {
    "path": "test/hello-world-app/src/spec-component/ng-content/ng-content.component.html",
    "content": "<div class=\"wrapper-1\">\n  <ng-content></ng-content>\n</div>\n<div class=\"wrapper-2\">\n  <ng-content select=\"[slot='empty']\"></ng-content>\n</div>\n"
  },
  {
    "path": "test/hello-world-app/src/spec-component/ng-content/ng-content.component.ts",
    "content": "import { Component, OnInit } from '@angular/core';\n\n@Component({\n  selector: 'app-ng-content',\n  templateUrl: './ng-content.component.html',\n})\nexport class NgContentComponent implements OnInit {\n  constructor() {}\n\n  ngOnInit() {}\n}\n"
  },
  {
    "path": "test/hello-world-app/src/spec-component/ng-content/ng-content.entry.ts",
    "content": "import { componentRegistry } from 'angular-miniprogram';\nimport { NgContentComponent } from './ng-content.component';\ncomponentRegistry(NgContentComponent);\n"
  },
  {
    "path": "test/hello-world-app/src/spec-component/ng-content/ng-content.module.ts",
    "content": "import { NgModule } from '@angular/core';\nimport { NgContentComponent } from './ng-content.component';\n\n@NgModule({\n  imports: [],\n  declarations: [NgContentComponent],\n  exports: [NgContentComponent],\n})\nexport class NgContentModule {}\n"
  },
  {
    "path": "test/hello-world-app/src/spec-component/ng-for/ng-for.component.html",
    "content": "<div *ngFor=\"let item of list; let i = index\" [class]=\"'ng-for-' + i\">\n  {{ item }}\n</div>\n"
  },
  {
    "path": "test/hello-world-app/src/spec-component/ng-for/ng-for.component.ts",
    "content": "import { Component, Input, OnInit } from '@angular/core';\n\n@Component({\n  selector: 'app-ng-for',\n  templateUrl: './ng-for.component.html',\n})\nexport class NgForComponent implements OnInit {\n  @Input() list: string[];\n  constructor() {}\n\n  ngOnInit() {}\n}\n"
  },
  {
    "path": "test/hello-world-app/src/spec-component/ng-for/ng-for.entry.ts",
    "content": "import { componentRegistry } from 'angular-miniprogram';\nimport { NgForComponent } from './ng-for.component';\ncomponentRegistry(NgForComponent);\n"
  },
  {
    "path": "test/hello-world-app/src/spec-component/ng-for/ng-for.module.ts",
    "content": "import { NgModule } from '@angular/core';\nimport { CommonModule } from 'angular-miniprogram/common';\nimport { NgForComponent } from './ng-for.component';\n\n@NgModule({\n  imports: [CommonModule],\n  declarations: [NgForComponent],\n  exports: [NgForComponent],\n})\nexport class NgForModule {}\n"
  },
  {
    "path": "test/hello-world-app/src/spec-component/ng-if/ng-if.component.html",
    "content": "<div *ngIf=\"true\" class=\"true-1\">true</div>\n<div *ngIf=\"false\" class=\"false-1\">false</div>\n"
  },
  {
    "path": "test/hello-world-app/src/spec-component/ng-if/ng-if.component.ts",
    "content": "import { Component, OnInit } from '@angular/core';\n\n@Component({\n  selector: 'app-ng-if',\n  templateUrl: './ng-if.component.html',\n})\nexport class NgIfComponent implements OnInit {\n  constructor() {}\n\n  ngOnInit() {}\n}\n"
  },
  {
    "path": "test/hello-world-app/src/spec-component/ng-if/ng-if.entry.ts",
    "content": "import { componentRegistry } from 'angular-miniprogram';\nimport { NgIfComponent } from './ng-if.component';\ncomponentRegistry(NgIfComponent);\n"
  },
  {
    "path": "test/hello-world-app/src/spec-component/ng-if/ng-if.module.ts",
    "content": "import { NgModule } from '@angular/core';\nimport { CommonModule } from 'angular-miniprogram/common';\nimport { NgIfComponent } from './ng-if.component';\n\n@NgModule({\n  imports: [CommonModule],\n  declarations: [NgIfComponent],\n  exports: [NgIfComponent],\n})\nexport class NgIfModule {}\n"
  },
  {
    "path": "test/hello-world-app/src/spec-component/ng-library-import/ng-library-import.component.html",
    "content": "<app-lib-comp1 #libComp1></app-lib-comp1>\n"
  },
  {
    "path": "test/hello-world-app/src/spec-component/ng-library-import/ng-library-import.component.ts",
    "content": "import { Component, OnInit, ViewChild } from '@angular/core';\nimport { LibComp1Component } from 'test-library';\n@Component({\n  selector: 'app-ng-library-import',\n  templateUrl: './ng-library-import.component.html',\n})\nexport class NgLibraryImportComponent implements OnInit {\n  @ViewChild('libComp1', { static: true }) libComp1: LibComp1Component;\n  constructor() {}\n\n  ngOnInit() {}\n}\n"
  },
  {
    "path": "test/hello-world-app/src/spec-component/ng-library-import/ng-library-import.entry.ts",
    "content": "import { componentRegistry } from 'angular-miniprogram';\nimport { NgLibraryImportComponent } from './ng-library-import.component';\ncomponentRegistry(NgLibraryImportComponent);\n"
  },
  {
    "path": "test/hello-world-app/src/spec-component/ng-library-import/ng-library-import.module.ts",
    "content": "import { NgModule } from '@angular/core';\nimport { NgLibraryImportComponent } from './ng-library-import.component';\nimport { LibComp1Module } from 'test-library';\n@NgModule({\n  imports: [LibComp1Module],\n  declarations: [NgLibraryImportComponent],\n  exports: [NgLibraryImportComponent],\n})\nexport class NgLibraryImportModule {}\n"
  },
  {
    "path": "test/hello-world-app/src/spec-component/ng-switch/ng-switch.component.html",
    "content": "<ng-container [ngSwitch]=\"case1\">\n  <div *ngSwitchCase=\"'case1'\" class=\"switch-case1\">case1</div>\n  <div *ngSwitchCase=\"'case2'\" class=\"switch-case2\">case2</div>\n  <div *ngSwitchDefault class=\"switch-default\">default</div>\n</ng-container>\n"
  },
  {
    "path": "test/hello-world-app/src/spec-component/ng-switch/ng-switch.component.ts",
    "content": "import { Component, OnInit } from '@angular/core';\n\n@Component({\n  selector: 'app-ng-switch',\n  templateUrl: './ng-switch.component.html',\n})\nexport class NgSwitchComponent implements OnInit {\n  case1 = 'case1';\n  constructor() {}\n\n  ngOnInit() {}\n}\n"
  },
  {
    "path": "test/hello-world-app/src/spec-component/ng-switch/ng-switch.entry.ts",
    "content": "import { componentRegistry } from 'angular-miniprogram';\nimport { NgSwitchComponent } from './ng-switch.component';\ncomponentRegistry(NgSwitchComponent);\n"
  },
  {
    "path": "test/hello-world-app/src/spec-component/ng-switch/ng-switch.module.ts",
    "content": "import { NgModule } from '@angular/core';\nimport { CommonModule } from 'angular-miniprogram/common';\nimport { NgSwitchComponent } from './ng-switch.component';\n\n@NgModule({\n  imports: [CommonModule],\n  declarations: [NgSwitchComponent],\n  exports: [NgSwitchComponent],\n})\nexport class NgSwitchModule {}\n"
  },
  {
    "path": "test/hello-world-app/src/spec-component/ng-template-outlet/ng-template-outlet.component.html",
    "content": "<ng-template #template1>\n  <div class=\"template-content-1\">template-content-1</div>\n</ng-template>\n<ng-template #template2>\n  <div class=\"template-content-2\">template-content-1</div>\n</ng-template>\n<ng-container *ngTemplateOutlet=\"template1\"></ng-container>\n"
  },
  {
    "path": "test/hello-world-app/src/spec-component/ng-template-outlet/ng-template-outlet.component.ts",
    "content": "import { Component, OnInit } from '@angular/core';\n\n@Component({\n  selector: 'app-ng-template-outlet',\n  templateUrl: './ng-template-outlet.component.html',\n})\nexport class NgTemplateOutletComponent implements OnInit {\n  constructor() {}\n\n  ngOnInit() {}\n}\n"
  },
  {
    "path": "test/hello-world-app/src/spec-component/ng-template-outlet/ng-template-outlet.entry.ts",
    "content": "import { componentRegistry } from 'angular-miniprogram';\nimport { NgTemplateOutletComponent } from './ng-template-outlet.component';\ncomponentRegistry(NgTemplateOutletComponent);\n"
  },
  {
    "path": "test/hello-world-app/src/spec-component/ng-template-outlet/ng-template-outlet.module.ts",
    "content": "import { NgModule } from '@angular/core';\nimport { CommonModule } from 'angular-miniprogram/common';\nimport { NgTemplateOutletComponent } from './ng-template-outlet.component';\n\n@NgModule({\n  imports: [CommonModule],\n  declarations: [NgTemplateOutletComponent],\n  exports: [NgTemplateOutletComponent],\n})\nexport class NgTemplateOutletModule {}\n"
  },
  {
    "path": "test/hello-world-app/src/spec-component/self-template/self-template.component.html",
    "content": "<div class=\"container-1\">\n  <ng-container *ngTemplateOutlet=\"template1\"></ng-container>\n</div>\n"
  },
  {
    "path": "test/hello-world-app/src/spec-component/self-template/self-template.component.ts",
    "content": "import { Component, Input, OnInit, TemplateRef } from '@angular/core';\n\n@Component({\n  selector: 'app-self-template',\n  templateUrl: './self-template.component.html',\n})\nexport class SelfTemplateComponent implements OnInit {\n  @Input() template1: TemplateRef<any>;\n  constructor() {}\n\n  ngOnInit() {}\n}\n"
  },
  {
    "path": "test/hello-world-app/src/spec-component/self-template/self-template.entry.ts",
    "content": "import { componentRegistry } from 'angular-miniprogram';\nimport { SelfTemplateComponent } from './self-template.component';\ncomponentRegistry(SelfTemplateComponent);\n"
  },
  {
    "path": "test/hello-world-app/src/spec-component/self-template/self-template.module.ts",
    "content": "import { NgModule } from '@angular/core';\nimport { CommonModule } from 'angular-miniprogram/common';\nimport { SelfTemplateComponent } from './self-template.component';\n\n@NgModule({\n  imports: [CommonModule],\n  declarations: [SelfTemplateComponent],\n  exports: [SelfTemplateComponent],\n})\nexport class SelfTemplateModule {}\n"
  },
  {
    "path": "test/hello-world-app/src/spec-component/style-class/style-class.component.html",
    "content": "<div class=\"class-1\">class-1</div>\n<div class=\"class-2\" style=\"background-color: red\">class-2 style-1</div>\n"
  },
  {
    "path": "test/hello-world-app/src/spec-component/style-class/style-class.component.ts",
    "content": "import { Component, OnInit } from '@angular/core';\n\n@Component({\n  selector: 'app-style-class',\n  templateUrl: './style-class.component.html',\n})\nexport class StyleClassComponent implements OnInit {\n  constructor() {}\n\n  ngOnInit() {}\n}\n"
  },
  {
    "path": "test/hello-world-app/src/spec-component/style-class/style-class.entry.ts",
    "content": "import { componentRegistry } from 'angular-miniprogram';\nimport { StyleClassComponent } from './style-class.component';\ncomponentRegistry(StyleClassComponent);\n"
  },
  {
    "path": "test/hello-world-app/src/spec-component/style-class/style-class.module.ts",
    "content": "import { NgModule } from '@angular/core';\nimport { StyleClassComponent } from './style-class.component';\n\n@NgModule({\n  imports: [],\n  declarations: [StyleClassComponent],\n  exports: [StyleClassComponent],\n})\nexport class StyleClassModule {}\n"
  },
  {
    "path": "test/hello-world-app/src/spec-component/tag-view-convert/tag-view-convert.component.html",
    "content": "<div>div->view</div>\n<span>span->view</span>\n"
  },
  {
    "path": "test/hello-world-app/src/spec-component/tag-view-convert/tag-view-convert.component.ts",
    "content": "import { Component } from '@angular/core';\n\n@Component({\n  selector: 'app-tag-view-convert',\n  templateUrl: './tag-view-convert.component.html',\n})\nexport class TagViewConvertComponent {}\n"
  },
  {
    "path": "test/hello-world-app/src/spec-component/tag-view-convert/tag-view-convert.entry.ts",
    "content": "import { componentRegistry } from 'angular-miniprogram';\nimport { TagViewConvertComponent } from './tag-view-convert.component';\ncomponentRegistry(TagViewConvertComponent);\n"
  },
  {
    "path": "test/hello-world-app/src/spec-component/tag-view-convert/tag-view-convert.module.ts",
    "content": "import { NgModule } from '@angular/core';\nimport { TagViewConvertComponent } from './tag-view-convert.component';\n\n@NgModule({\n  imports: [],\n  declarations: [TagViewConvertComponent],\n  exports: [TagViewConvertComponent],\n})\nexport class TagViewConvertModule {}\n"
  },
  {
    "path": "test/hello-world-app/src/styles.css",
    "content": "/* You can add global styles to this file, and also import other style files */\n"
  },
  {
    "path": "test/hello-world-app/src/test.ts",
    "content": "import { platformMiniProgram } from 'angular-miniprogram';\nimport { startupTest } from 'angular-miniprogram/karma/client';\nimport { MainTestModule } from './main-test.module';\nimport 'zone.js';\n\nlet jasmineRequire = require('jasmine-core/lib/jasmine-core/jasmine.js');\n\nfunction bootWithoutGlobals() {\n  let jasmineInterface;\n  const jasmine = jasmineRequire.core(jasmineRequire);\n  const env = jasmine.getEnv({ suppressLoadErrors: true });\n  jasmineInterface = jasmineRequire.interface(jasmine, env);\n\n  return jasmineInterface;\n}\n\nlet obj = bootWithoutGlobals();\nfor (const key in obj) {\n  if (Object.prototype.hasOwnProperty.call(obj, key)) {\n    (wx as any).__global[key] = obj[key];\n  }\n}\njasmine.DEFAULT_TIMEOUT_INTERVAL = 10 * 1000;\n\nplatformMiniProgram()\n  .bootstrapModule(MainTestModule)\n  .then((e) => {});\n// Then we find all the tests.\n// And load the modules.\n// 因为ng修改了test的获取实例的时机,改为拼在最后面,而启动操作要在最后面的后面,所以使用了延时(网页端正常是因为spec=>component,而小程序目前设计是component spec平行)\nsetTimeout(() => {\n  startupTest();\n}, 1000);\n"
  },
  {
    "path": "test/hello-world-app/src/tsconfig.app.json",
    "content": "{\n  \"extends\": \"../tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"../out-tsc/app\",\n    \"types\": [],\n    \"skipLibCheck\": true,\n    \"target\": \"ES2022\"\n  },\n  \"files\": [\"main.ts\"],\n  \"include\": [\"**/*.d.ts\", \"pages/**/*.entry.ts\", \"components/**/*.entry.ts\"]\n}\n"
  },
  {
    "path": "test/hello-world-app/src/tsconfig.dev.json",
    "content": "{\n  \"extends\": \"../tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"../out-tsc/app\",\n    \"types\": [],\n    \"skipLibCheck\": true\n  },\n  \"files\": [\"main.ts\"],\n  \"include\": [\n    \"**/*.d.ts\",\n    \"__pages/**/*.entry.ts\",\n    \"__components/**/*.entry.ts\"\n  ]\n}\n"
  },
  {
    "path": "test/hello-world-app/src/tsconfig.spec.json",
    "content": "/* To learn more about this file see: https://angular.io/config/tsconfig. */\n{\n  \"extends\": \"../tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"./out-tsc/spec\",\n    \"types\": [\"jasmine\"],\n    \"skipLibCheck\": true,\n    \"target\": \"ES2022\"\n  },\n  \"files\": [\"test.ts\"],\n  \"include\": [\n    \"**/*.d.ts\",\n    \"spec/**/*.entry.ts\",\n    \"spec/**/*.spec.ts\",\n    \"spec-component/**/*.entry.ts\",\n    \"spec-component/**/*.module.ts\"\n  ]\n}\n"
  },
  {
    "path": "test/hello-world-app/src/typings.d.ts",
    "content": "/**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n/* SystemJS module definition */\nimport 'miniprogram-api-typings';\n// declare var module: NodeModule;\ninterface NodeModule {\n  id: string;\n}\n// declare interface Type<T> extends Function {\n//   new (...args: any[]): T;\n// }\n// declare function ngStartPage<M, C>(module: Type<M>, component: Type<C>): C;\ndeclare global {\n  const ngDevMode: null | any;\n}\n"
  },
  {
    "path": "test/hello-world-app/tsconfig.base.json",
    "content": "{\n  \"compileOnSave\": false,\n  \"compilerOptions\": {\n    \"baseUrl\": \"./\",\n    \"outDir\": \"./dist/out-tsc\",\n    \"sourceMap\": true,\n    \"declaration\": false,\n    \"moduleResolution\": \"node\",\n    \"emitDecoratorMetadata\": true,\n    \"experimentalDecorators\": true,\n    \"esModuleInterop\": true,\n    \"allowSyntheticDefaultImports\": true,\n    \"strictNullChecks\": true,\n    \"target\": \"es2022\",\n    \"module\": \"es2020\",\n    \"typeRoots\": [\"node_modules/@types\"],\n    \"lib\": [\"es2018\", \"dom\"],\n    \"paths\": {\n      \"angular-miniprogram\": [\"../../dist\"],\n      \"angular-miniprogram/platform\": [\"../../dist/platform\"],\n      \"angular-miniprogram/platform/type\": [\"../../dist/platform/type\"],\n      \"angular-miniprogram/platform/wx\": [\"../../dist/platform/wx\"],\n      \"angular-miniprogram/platform/default\": [\"../../dist/platform/default\"],\n      \"angular-miniprogram/platform/zjtd\": [\"../../dist/platform/zjtd\"],\n      \"angular-miniprogram/forms\": [\"../../dist/forms\"],\n      \"angular-miniprogram/common\": [\"../../dist/common\"],\n      \"angular-miniprogram/common/http\": [\"../../dist/common/http\"],\n      \"angular-miniprogram/karma/client\": [\"../../src/builder/karma/client\"]\n    }\n  }\n}\n"
  },
  {
    "path": "test/hello-world-app/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {},\n  \"include\": [],\n  \"files\": [],\n  \"references\": [\n    {\n      \"path\": \"./src/tsconfig.app.json\"\n    },\n    {\n      \"path\": \"./src/tsconfig.spec.json\"\n    },\n    {\n      \"path\": \"./src/tsconfig.dev.json\"\n    }\n  ]\n}\n"
  },
  {
    "path": "test/plugin-describe-builder/index.ts",
    "content": "/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport type { TestProjectHost } from '@angular-devkit/architect/testing';\n\nimport { Path, join, normalize } from '@angular-devkit/core';\nimport { virtualFs } from '@angular-devkit/core';\nimport type { Configuration } from 'webpack';\nlet { fileBufferToString, stringToFileBuffer } = virtualFs;\n\nexport interface TestContext {\n  buildSuccess: (webpackConfig: Configuration) => void;\n}\n\nexport class MyTestProjectHost {\n  constructor(private host: TestProjectHost) {}\n  async getFileList(dirPath: Path): Promise<string[]> {\n    const fileList: string[] = [];\n    const list = await this.host.list(dirPath).toPromise();\n    for (let i = 0; i < list.length; i++) {\n      const element = list[i];\n      const filePath = join(dirPath, element);\n      if (await this.host.isDirectory(filePath).toPromise()) {\n        fileList.push(...(await this.getFileList(filePath)));\n      } else {\n        fileList.push(filePath);\n      }\n    }\n    return fileList;\n  }\n\n  async importPathRename(list: string[]) {\n    for (let i = 0; i < list.length; i++) {\n      const element = list[i];\n      const content = await this.host.read(normalize(element)).toPromise();\n      let contentString = fileBufferToString(content);\n\n      contentString = contentString\n        .replace(/\\/__components\\//g, '/components/')\n        .replace(/\\/__pages\\//g, '/pages/');\n\n      await this.host\n        .write(normalize(element), stringToFileBuffer(contentString))\n        .toPromise();\n    }\n  }\n\n  async moveDir(list: string[], from: string, to: string) {\n    for (let i = 0; i < list.length; i++) {\n      const item = list[i];\n      await this.host\n        .rename(\n          normalize(join(this.host.root(), 'src', from, item)),\n          normalize(join(this.host.root(), 'src', to, item))\n        )\n        .toPromise();\n    }\n  }\n  async addPageEntry(list: string[]) {\n    const configPath = join(normalize(this.host.root()), 'src', 'app.json');\n    const file = await this.host.read(configPath).toPromise();\n    const json = JSON.parse(fileBufferToString(file));\n    const entryList = list.map((item) => `pages/${item}/${item}-entry`);\n    json.pages = entryList;\n    await this.host\n      .write(configPath, stringToFileBuffer(JSON.stringify(json)))\n      .toPromise();\n  }\n  async addSpecEntry(list: string[]) {\n    const configPath = join(normalize(this.host.root()), 'src', 'app.json');\n    const file = await this.host.read(configPath).toPromise();\n    const json = JSON.parse(fileBufferToString(file));\n    const entryList = list.map((item) => `spec/${item}/${item}-entry`);\n    json.pages = entryList;\n    await this.host\n      .write(configPath, stringToFileBuffer(JSON.stringify(json)))\n      .toPromise();\n  }\n}\nimport { setWorkspaceRoot } from 'cyia-ngx-devkit';\nexport * from 'cyia-ngx-devkit';\nsetWorkspaceRoot(join(normalize(__dirname), `../hello-world-app/`));\n"
  },
  {
    "path": "test/test-builder/index.ts",
    "content": "import { BuilderContext } from '@angular-devkit/architect';\nimport {\n  BrowserBuilderOptions,\n  ExecutionTransformer,\n  executeBrowserBuilder,\n  AssetPattern,\n  KarmaBuilderOptions,\n} from '@angular-devkit/build-angular';\nimport * as path from 'path';\nimport * as webpack from 'webpack';\nimport { PlatformType } from '../../src/builder/platform';\n\nexport type CustomWebpackBrowserSchema = BrowserBuilderOptions;\n\nexport function buildWebpackBrowserGenerate(\n  webpackConfiguration: (\n    options: BrowserBuilderOptions,\n    context: BuilderContext\n  ) => ExecutionTransformer<webpack.Configuration>\n) {\n  return (\n    options: CustomWebpackBrowserSchema,\n    context: BuilderContext\n  ): ReturnType<typeof executeBrowserBuilder> => {\n    return executeBrowserBuilder(options, context, {\n      webpackConfiguration: webpackConfiguration(options, context),\n    });\n  };\n}\n\nexport const BROWSER_BUILDER_INFO = {\n  name: 'test-builder:application',\n  schemaPath: path.resolve(__dirname, 'schema.json'),\n};\nexport const LIBRARY_BUILDER_INFO = {\n  name: 'test-builder:library',\n  schemaPath: path.resolve(__dirname, 'schema.library.json'),\n};\nexport const KARMA_BUILDER_INFO = {\n  name: 'test-builder:karma',\n  schemaPath: path.resolve(__dirname, 'schema.karma.json'),\n};\n\nexport const DEFAULT_ANGULAR_CONFIG = {\n  outputPath: 'dist/testProject',\n  index: '',\n  main: 'src/main.ts',\n  polyfills: '',\n  tsConfig: 'src/tsconfig.app.json',\n  progress: false,\n  assets: [\n    {\n      glob: 'project.config.json',\n      input: './src',\n      output: './',\n    },\n    {\n      glob: 'app.json',\n      input: './src',\n      output: './',\n    },\n  ],\n  components: [\n    { glob: '**/*.entry.ts', input: './src/components', output: 'components' },\n  ],\n  pages: [{ glob: '**/*.entry.ts', input: './src/pages', output: 'pages' }],\n  styles: [\n    {\n      input: 'src/styles.css',\n      bundleName: 'app1',\n      inject: false,\n    },\n  ],\n  scripts: [],\n  aot: true,\n};\nexport const DEFAULT_ANGULAR_KARMA_CONFIG: KarmaBuilderOptions & {\n  pages: AssetPattern[];\n\n  components: AssetPattern[];\n  platform: PlatformType;\n} = {\n  karmaConfig: 'karma.conf.js',\n  main: 'src/test.ts',\n  tsConfig: 'src/tsconfig.spec.json',\n  watch: false,\n  components: [\n    {\n      glob: '**/*.entry.ts',\n      input: './src/spec-component',\n      output: 'spec-component',\n    },\n  ],\n  styles: [\n    {\n      input: 'src/styles.css',\n      bundleName: 'app1',\n      inject: false,\n    },\n  ],\n  assets: [\n    {\n      glob: 'project.config.json',\n      input: './src',\n      output: './',\n    },\n    {\n      glob: 'app.json',\n      input: './src',\n      output: './',\n    },\n  ],\n  platform: PlatformType.wx,\n  sourceMap: false,\n  pages: [{ glob: '**/*.entry.ts', input: './src/spec', output: 'spec' }],\n};\nexport const DEFAULT_ANGULAR_LIBRARY_CONFIG = {\n  project: 'projects/test-library/ng-package.json',\n  tsConfig: 'projects/test-library/tsconfig.lib.json',\n};\n"
  },
  {
    "path": "test/test-builder/schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/schema\",\n  \"title\": \"Webpack browser schema for Build Facade.\",\n  \"description\": \"Browser target options\",\n  \"type\": \"object\",\n  \"properties\": {\n    \"pages\": {\n      \"type\": \"array\",\n      \"description\": \"页面配置\",\n      \"default\": [],\n      \"items\": {\n        \"$ref\": \"#/definitions/assetPattern\"\n      }\n    },\n    \"components\": {\n      \"type\": \"array\",\n      \"description\": \"组件配置\",\n      \"default\": [],\n      \"items\": {\n        \"$ref\": \"#/definitions/assetPattern\"\n      }\n    },\n    \"assets\": {\n      \"type\": \"array\",\n      \"description\": \"List of static application assets.\",\n      \"default\": [],\n      \"items\": {\n        \"$ref\": \"#/definitions/assetPattern\"\n      }\n    },\n    \"platform\": {\n      \"type\": \"string\",\n      \"description\": \"小程序平台\",\n      \"default\": \"wx\"\n    },\n    \"main\": {\n      \"type\": \"string\",\n      \"description\": \"The full path for the main entry point to the app, relative to the current workspace.\",\n      \"$valueDescription\": \"fileName\"\n    },\n    \"polyfills\": {\n      \"type\": \"string\",\n      \"description\": \"The full path for the polyfills file, relative to the current workspace.\"\n    },\n    \"tsConfig\": {\n      \"type\": \"string\",\n      \"description\": \"The full path for the TypeScript configuration file, relative to the current workspace.\"\n    },\n    \"scripts\": {\n      \"description\": \"Global scripts to be included in the build.\",\n      \"type\": \"array\",\n      \"default\": [],\n      \"items\": {\n        \"$ref\": \"#/definitions/extraEntryPoint\"\n      }\n    },\n    \"styles\": {\n      \"description\": \"Global styles to be included in the build.\",\n      \"type\": \"array\",\n      \"default\": [],\n      \"items\": {\n        \"$ref\": \"#/definitions/extraEntryPoint\"\n      }\n    },\n    \"stylePreprocessorOptions\": {\n      \"description\": \"Options to pass to style preprocessors.\",\n      \"type\": \"object\",\n      \"properties\": {\n        \"includePaths\": {\n          \"description\": \"Paths to include. Paths will be resolved to project root.\",\n          \"type\": \"array\",\n          \"items\": {\n            \"type\": \"string\"\n          },\n          \"default\": []\n        }\n      },\n      \"additionalProperties\": false\n    },\n    \"optimization\": {\n      \"description\": \"Enables optimization of the build output. Including minification of scripts and styles, tree-shaking, dead-code elimination, inlining of critical CSS and fonts inlining. For more information, see https://angular.io/guide/workspace-config#optimization-configuration.\",\n      \"x-user-analytics\": 16,\n      \"default\": false,\n      \"oneOf\": [\n        {\n          \"type\": \"object\",\n          \"properties\": {\n            \"scripts\": {\n              \"type\": \"boolean\",\n              \"description\": \"Enables optimization of the scripts output.\",\n              \"default\": true\n            },\n            \"styles\": {\n              \"description\": \"Enables optimization of the styles output.\",\n              \"default\": true,\n              \"oneOf\": [\n                {\n                  \"type\": \"object\",\n                  \"properties\": {\n                    \"minify\": {\n                      \"type\": \"boolean\",\n                      \"description\": \"Minify CSS definitions by removing extraneous whitespace and comments, merging identifiers and minimizing values.\",\n                      \"default\": true\n                    },\n                    \"inlineCritical\": {\n                      \"type\": \"boolean\",\n                      \"description\": \"Extract and inline critical CSS definitions to improve first paint time.\",\n                      \"default\": false\n                    }\n                  },\n                  \"additionalProperties\": false\n                },\n                {\n                  \"type\": \"boolean\"\n                }\n              ]\n            },\n            \"fonts\": {\n              \"description\": \"Enables optimization for fonts. This option requires internet access. `HTTPS_PROXY` environment variable can be used to specify a proxy server.\",\n              \"default\": true,\n              \"oneOf\": [\n                {\n                  \"type\": \"object\",\n                  \"properties\": {\n                    \"inline\": {\n                      \"type\": \"boolean\",\n                      \"description\": \"Reduce render blocking requests by inlining external Google fonts and icons CSS definitions in the application's HTML index file. This option requires internet access. `HTTPS_PROXY` environment variable can be used to specify a proxy server.\",\n                      \"default\": true\n                    }\n                  },\n                  \"additionalProperties\": false\n                },\n                {\n                  \"type\": \"boolean\"\n                }\n              ]\n            }\n          },\n          \"additionalProperties\": false\n        },\n        {\n          \"type\": \"boolean\"\n        }\n      ]\n    },\n    \"fileReplacements\": {\n      \"description\": \"Replace compilation source files with other compilation source files in the build.\",\n      \"type\": \"array\",\n      \"items\": {\n        \"$ref\": \"#/definitions/fileReplacement\"\n      },\n      \"default\": []\n    },\n    \"outputPath\": {\n      \"type\": \"string\",\n      \"description\": \"The full path for the new output directory, relative to the current workspace.\\n\\nBy default, writes output to a folder named dist/ in the current project.\"\n    },\n    \"resourcesOutputPath\": {\n      \"type\": \"string\",\n      \"description\": \"The path where style resources will be placed, relative to outputPath.\",\n      \"default\": \"\"\n    },\n    \"aot\": {\n      \"type\": \"boolean\",\n      \"description\": \"Build using Ahead of Time compilation.\",\n      \"x-user-analytics\": 13,\n      \"default\": false\n    },\n    \"sourceMap\": {\n      \"description\": \"Output source maps for scripts and styles. For more information, see https://angular.io/guide/workspace-config#source-map-configuration.\",\n      \"default\": true,\n      \"oneOf\": [\n        {\n          \"type\": \"object\",\n          \"properties\": {\n            \"scripts\": {\n              \"type\": \"boolean\",\n              \"description\": \"Output source maps for all scripts.\",\n              \"default\": true\n            },\n            \"styles\": {\n              \"type\": \"boolean\",\n              \"description\": \"Output source maps for all styles.\",\n              \"default\": true\n            },\n            \"hidden\": {\n              \"type\": \"boolean\",\n              \"description\": \"Output source maps used for error reporting tools.\",\n              \"default\": false\n            },\n            \"vendor\": {\n              \"type\": \"boolean\",\n              \"description\": \"Resolve vendor packages source maps.\",\n              \"default\": false\n            }\n          },\n          \"additionalProperties\": false\n        },\n        {\n          \"type\": \"boolean\"\n        }\n      ]\n    },\n    \"vendorChunk\": {\n      \"type\": \"boolean\",\n      \"description\": \"Generate a seperate bundle containing only vendor libraries. This option should only used for development.\",\n      \"default\": true\n    },\n    \"commonChunk\": {\n      \"type\": \"boolean\",\n      \"description\": \"Generate a seperate bundle containing code used across multiple bundles.\",\n      \"default\": true\n    },\n    \"baseHref\": {\n      \"type\": \"string\",\n      \"description\": \"Base url for the application being built.\"\n    },\n    \"deployUrl\": {\n      \"type\": \"string\",\n      \"description\": \"URL where files will be deployed.\"\n    },\n    \"verbose\": {\n      \"type\": \"boolean\",\n      \"description\": \"Adds more details to output logging.\",\n      \"default\": false\n    },\n    \"progress\": {\n      \"type\": \"boolean\",\n      \"description\": \"Log progress to the console while building.\",\n      \"default\": true\n    },\n    \"i18nFile\": {\n      \"type\": \"string\",\n      \"description\": \"Localization file to use for i18n.\",\n      \"x-deprecated\": \"Use 'locales' object in the project metadata instead.\"\n    },\n    \"i18nFormat\": {\n      \"type\": \"string\",\n      \"description\": \"Format of the localization file specified with --i18n-file.\",\n      \"x-deprecated\": \"No longer needed as the format will be determined automatically.\"\n    },\n    \"i18nLocale\": {\n      \"type\": \"string\",\n      \"description\": \"Locale to use for i18n.\",\n      \"x-deprecated\": \"Use 'localize' instead.\"\n    },\n    \"i18nMissingTranslation\": {\n      \"type\": \"string\",\n      \"description\": \"How to handle missing translations for i18n.\",\n      \"enum\": [\"warning\", \"error\", \"ignore\"],\n      \"default\": \"warning\"\n    },\n    \"localize\": {\n      \"description\": \"Translate the bundles in one or more locales.\",\n      \"oneOf\": [\n        {\n          \"type\": \"boolean\",\n          \"description\": \"Translate all locales.\"\n        },\n        {\n          \"type\": \"array\",\n          \"description\": \"List of locales ID's to translate.\",\n          \"minItems\": 1,\n          \"items\": {\n            \"type\": \"string\",\n            \"pattern\": \"^[a-zA-Z]{2,3}(-[a-zA-Z]{4})?(-([a-zA-Z]{2}|[0-9]{3}))?(-[a-zA-Z]{5,8})?(-x(-[a-zA-Z0-9]{1,8})+)?$\"\n          }\n        }\n      ]\n    },\n    \"extractCss\": {\n      \"type\": \"boolean\",\n      \"description\": \"Extract CSS from global styles into '.css' files instead of '.js'.\",\n      \"default\": true,\n      \"x-deprecated\": \"Deprecated since version 11.0. No longer required to disable CSS extraction for HMR.\"\n    },\n    \"watch\": {\n      \"type\": \"boolean\",\n      \"description\": \"Run build when files change.\",\n      \"default\": false\n    },\n    \"outputHashing\": {\n      \"type\": \"string\",\n      \"description\": \"Define the output filename cache-busting hashing mode.\",\n      \"default\": \"none\",\n      \"enum\": [\"none\", \"all\", \"media\", \"bundles\"]\n    },\n    \"poll\": {\n      \"type\": \"number\",\n      \"description\": \"Enable and define the file watching poll time period in milliseconds.\"\n    },\n    \"deleteOutputPath\": {\n      \"type\": \"boolean\",\n      \"description\": \"Delete the output path before building.\",\n      \"default\": true\n    },\n    \"preserveSymlinks\": {\n      \"type\": \"boolean\",\n      \"description\": \"Do not use the real path when resolving modules. If unset then will default to `true` if NodeJS option --preserve-symlinks is set.\"\n    },\n    \"extractLicenses\": {\n      \"type\": \"boolean\",\n      \"description\": \"Extract all licenses in a separate file.\",\n      \"default\": false\n    },\n    \"showCircularDependencies\": {\n      \"type\": \"boolean\",\n      \"description\": \"Show circular dependency warnings on builds.\",\n      \"default\": true\n    },\n    \"buildOptimizer\": {\n      \"type\": \"boolean\",\n      \"description\": \"Enables '@angular-devkit/build-optimizer' optimizations when using the 'aot' option.\",\n      \"default\": false\n    },\n    \"namedChunks\": {\n      \"type\": \"boolean\",\n      \"description\": \"Use file name for lazy loaded chunks.\",\n      \"default\": true\n    },\n    \"subresourceIntegrity\": {\n      \"type\": \"boolean\",\n      \"description\": \"Enables the use of subresource integrity validation.\",\n      \"default\": false\n    },\n    \"serviceWorker\": {\n      \"type\": \"boolean\",\n      \"description\": \"Generates a service worker config for production builds.\",\n      \"default\": false\n    },\n    \"ngswConfigPath\": {\n      \"type\": \"string\",\n      \"description\": \"Path to ngsw-config.json.\"\n    },\n    \"index\": {\n      \"description\": \"Configures the generation of the application's HTML index.\",\n      \"oneOf\": [\n        {\n          \"type\": \"string\",\n          \"description\": \"The path of a file to use for the application's HTML index. The filename of the specified path will be used for the generated file and will be created in the root of the application's configured output path.\"\n        },\n        {\n          \"type\": \"object\",\n          \"description\": \"\",\n          \"properties\": {\n            \"input\": {\n              \"type\": \"string\",\n              \"minLength\": 1,\n              \"description\": \"The path of a file to use for the application's generated HTML index.\"\n            },\n            \"output\": {\n              \"type\": \"string\",\n              \"minLength\": 1,\n              \"default\": \"index.html\",\n              \"description\": \"The output path of the application's generated HTML index file. The full provided path will be used and will be considered relative to the application's configured output path.\"\n            }\n          },\n          \"required\": [\"input\"]\n        }\n      ]\n    },\n    \"statsJson\": {\n      \"type\": \"boolean\",\n      \"description\": \"Generates a 'stats.json' file which can be analyzed using tools such as 'webpack-bundle-analyzer'.\",\n      \"default\": false\n    },\n    \"forkTypeChecker\": {\n      \"type\": \"boolean\",\n      \"description\": \"Run the TypeScript type checker in a forked process.\",\n      \"default\": true\n    },\n    \"lazyModules\": {\n      \"description\": \"List of additional NgModule files that will be lazy loaded. Lazy router modules will be discovered automatically.\",\n      \"type\": \"array\",\n      \"items\": {\n        \"type\": \"string\"\n      },\n      \"x-deprecated\": \"'SystemJsNgModuleLoader' is deprecated, and this is part of its usage. Use 'import()' syntax instead.\",\n      \"default\": []\n    },\n    \"budgets\": {\n      \"description\": \"Budget thresholds to ensure parts of your application stay within boundaries which you set.\",\n      \"type\": \"array\",\n      \"items\": {\n        \"$ref\": \"#/definitions/budget\"\n      },\n      \"default\": []\n    },\n    \"webWorkerTsConfig\": {\n      \"type\": \"string\",\n      \"description\": \"TypeScript configuration for Web Worker modules.\"\n    },\n    \"crossOrigin\": {\n      \"type\": \"string\",\n      \"description\": \"Define the crossorigin attribute setting of elements that provide CORS support.\",\n      \"default\": \"none\",\n      \"enum\": [\"none\", \"anonymous\", \"use-credentials\"]\n    },\n    \"experimentalRollupPass\": {\n      \"type\": \"boolean\",\n      \"description\": \"Concatenate modules with Rollup before bundling them with Webpack.\",\n      \"default\": false\n    },\n    \"allowedCommonJsDependencies\": {\n      \"description\": \"A list of CommonJS packages that are allowed to be used without a build time warning.\",\n      \"type\": \"array\",\n      \"items\": {\n        \"type\": \"string\"\n      },\n      \"default\": []\n    }\n  },\n  \"additionalProperties\": false,\n  \"required\": [\"outputPath\", \"index\", \"main\", \"tsConfig\"],\n  \"definitions\": {\n    \"assetPattern\": {\n      \"oneOf\": [\n        {\n          \"type\": \"object\",\n          \"properties\": {\n            \"followSymlinks\": {\n              \"type\": \"boolean\",\n              \"default\": false,\n              \"description\": \"Allow glob patterns to follow symlink directories. This allows subdirectories of the symlink to be searched.\"\n            },\n            \"glob\": {\n              \"type\": \"string\",\n              \"description\": \"The pattern to match.\"\n            },\n            \"input\": {\n              \"type\": \"string\",\n              \"description\": \"The input directory path in which to apply 'glob'. Defaults to the project root.\"\n            },\n            \"ignore\": {\n              \"description\": \"An array of globs to ignore.\",\n              \"type\": \"array\",\n              \"items\": {\n                \"type\": \"string\"\n              }\n            },\n            \"output\": {\n              \"type\": \"string\",\n              \"description\": \"Absolute path within the output.\"\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\"glob\", \"input\", \"output\"]\n        },\n        {\n          \"type\": \"string\"\n        }\n      ]\n    },\n    \"fileReplacement\": {\n      \"oneOf\": [\n        {\n          \"type\": \"object\",\n          \"properties\": {\n            \"src\": {\n              \"type\": \"string\",\n              \"pattern\": \"\\\\.(([cm]?j|t)sx?|json)$\"\n            },\n            \"replaceWith\": {\n              \"type\": \"string\",\n              \"pattern\": \"\\\\.(([cm]?j|t)sx?|json)$\"\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\"src\", \"replaceWith\"]\n        },\n        {\n          \"type\": \"object\",\n          \"properties\": {\n            \"replace\": {\n              \"type\": \"string\",\n              \"pattern\": \"\\\\.(([cm]?j|t)sx?|json)$\"\n            },\n            \"with\": {\n              \"type\": \"string\",\n              \"pattern\": \"\\\\.(([cm]?j|t)sx?|json)$\"\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\"replace\", \"with\"]\n        }\n      ]\n    },\n    \"extraEntryPoint\": {\n      \"oneOf\": [\n        {\n          \"type\": \"object\",\n          \"properties\": {\n            \"input\": {\n              \"type\": \"string\",\n              \"description\": \"The file to include.\"\n            },\n            \"bundleName\": {\n              \"type\": \"string\",\n              \"pattern\": \"^[\\\\w\\\\-.]*$\",\n              \"description\": \"The bundle name for this extra entry point.\"\n            },\n            \"inject\": {\n              \"type\": \"boolean\",\n              \"description\": \"If the bundle will be referenced in the HTML file.\",\n              \"default\": true\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\"input\"]\n        },\n        {\n          \"type\": \"string\",\n          \"description\": \"The file to include.\"\n        }\n      ]\n    },\n    \"budget\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"type\": {\n          \"type\": \"string\",\n          \"description\": \"The type of budget.\",\n          \"enum\": [\n            \"all\",\n            \"allScript\",\n            \"any\",\n            \"anyScript\",\n            \"anyComponentStyle\",\n            \"bundle\",\n            \"initial\"\n          ]\n        },\n        \"name\": {\n          \"type\": \"string\",\n          \"description\": \"The name of the bundle.\"\n        },\n        \"baseline\": {\n          \"type\": \"string\",\n          \"description\": \"The baseline size for comparison.\"\n        },\n        \"maximumWarning\": {\n          \"type\": \"string\",\n          \"description\": \"The maximum threshold for warning relative to the baseline.\"\n        },\n        \"maximumError\": {\n          \"type\": \"string\",\n          \"description\": \"The maximum threshold for error relative to the baseline.\"\n        },\n        \"minimumWarning\": {\n          \"type\": \"string\",\n          \"description\": \"The minimum threshold for warning relative to the baseline.\"\n        },\n        \"minimumError\": {\n          \"type\": \"string\",\n          \"description\": \"The minimum threshold for error relative to the baseline.\"\n        },\n        \"warning\": {\n          \"type\": \"string\",\n          \"description\": \"The threshold for warning relative to the baseline (min & max).\"\n        },\n        \"error\": {\n          \"type\": \"string\",\n          \"description\": \"The threshold for error relative to the baseline (min & max).\"\n        }\n      },\n      \"additionalProperties\": false,\n      \"required\": [\"type\"]\n    }\n  }\n}\n"
  },
  {
    "path": "test/test-builder/schema.karma.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema\",\n  \"title\": \"Karma Target\",\n  \"description\": \"Karma target options for Build Facade.\",\n  \"type\": \"object\",\n  \"properties\": {\n    \"pages\": {\n      \"type\": \"array\",\n      \"description\": \"页面配置\",\n      \"default\": [],\n      \"items\": {\n        \"$ref\": \"#/definitions/assetPattern\"\n      }\n    },\n    \"components\": {\n      \"type\": \"array\",\n      \"description\": \"组件配置\",\n      \"default\": [],\n      \"items\": {\n        \"$ref\": \"#/definitions/assetPattern\"\n      }\n    },\n    \"platform\": {\n      \"type\": \"string\",\n      \"description\": \"小程序平台\",\n      \"default\": \"wx\"\n    },\n    \"main\": {\n      \"type\": \"string\",\n      \"description\": \"The name of the main entry-point file.\"\n    },\n    \"tsConfig\": {\n      \"type\": \"string\",\n      \"description\": \"The name of the TypeScript configuration file.\"\n    },\n    \"karmaConfig\": {\n      \"type\": \"string\",\n      \"description\": \"The name of the Karma configuration file.\"\n    },\n    \"polyfills\": {\n      \"type\": \"string\",\n      \"description\": \"The name of the polyfills file.\"\n    },\n    \"assets\": {\n      \"type\": \"array\",\n      \"description\": \"List of static application assets.\",\n      \"default\": [],\n      \"items\": {\n        \"$ref\": \"#/definitions/assetPattern\"\n      }\n    },\n    \"scripts\": {\n      \"description\": \"Global scripts to be included in the build.\",\n      \"type\": \"array\",\n      \"default\": [],\n      \"items\": {\n        \"$ref\": \"#/definitions/extraEntryPoint\"\n      }\n    },\n    \"styles\": {\n      \"description\": \"Global styles to be included in the build.\",\n      \"type\": \"array\",\n      \"default\": [],\n      \"items\": {\n        \"$ref\": \"#/definitions/extraEntryPoint\"\n      }\n    },\n    \"inlineStyleLanguage\": {\n      \"description\": \"The stylesheet language to use for the application's inline component styles.\",\n      \"type\": \"string\",\n      \"default\": \"css\",\n      \"enum\": [\"css\", \"less\", \"sass\", \"scss\"]\n    },\n    \"stylePreprocessorOptions\": {\n      \"description\": \"Options to pass to style preprocessors\",\n      \"type\": \"object\",\n      \"properties\": {\n        \"includePaths\": {\n          \"description\": \"Paths to include. Paths will be resolved to workspace root.\",\n          \"type\": \"array\",\n          \"items\": {\n            \"type\": \"string\"\n          },\n          \"default\": []\n        }\n      },\n      \"additionalProperties\": false\n    },\n    \"include\": {\n      \"type\": \"array\",\n      \"items\": {\n        \"type\": \"string\"\n      },\n      \"description\": \"Globs of files to include, relative to workspace or project root. \\nThere are 2 special cases:\\n - when a path to directory is provided, all spec files ending \\\".spec.@(ts|tsx)\\\" will be included\\n - when a path to a file is provided, and a matching spec file exists it will be included instead\"\n    },\n    \"sourceMap\": {\n      \"description\": \"Output source maps for scripts and styles. For more information, see https://angular.io/guide/workspace-config#source-map-configuration.\",\n      \"default\": true,\n      \"oneOf\": [\n        {\n          \"type\": \"object\",\n          \"properties\": {\n            \"scripts\": {\n              \"type\": \"boolean\",\n              \"description\": \"Output source maps for all scripts.\",\n              \"default\": true\n            },\n            \"styles\": {\n              \"type\": \"boolean\",\n              \"description\": \"Output source maps for all styles.\",\n              \"default\": true\n            },\n            \"vendor\": {\n              \"type\": \"boolean\",\n              \"description\": \"Resolve vendor packages source maps.\",\n              \"default\": false\n            }\n          },\n          \"additionalProperties\": false\n        },\n        {\n          \"type\": \"boolean\"\n        }\n      ]\n    },\n    \"progress\": {\n      \"type\": \"boolean\",\n      \"description\": \"Log progress to the console while building.\",\n      \"default\": true\n    },\n    \"watch\": {\n      \"type\": \"boolean\",\n      \"description\": \"Run build when files change.\"\n    },\n    \"poll\": {\n      \"type\": \"number\",\n      \"description\": \"Enable and define the file watching poll time period in milliseconds.\"\n    },\n    \"preserveSymlinks\": {\n      \"type\": \"boolean\",\n      \"description\": \"Do not use the real path when resolving modules. If unset then will default to `true` if NodeJS option --preserve-symlinks is set.\"\n    },\n    \"browsers\": {\n      \"type\": \"string\",\n      \"description\": \"Override which browsers tests are run against.\"\n    },\n    \"codeCoverage\": {\n      \"type\": \"boolean\",\n      \"description\": \"Output a code coverage report.\",\n      \"default\": false\n    },\n    \"codeCoverageExclude\": {\n      \"type\": \"array\",\n      \"description\": \"Globs to exclude from code coverage.\",\n      \"items\": {\n        \"type\": \"string\"\n      },\n      \"default\": []\n    },\n    \"fileReplacements\": {\n      \"description\": \"Replace compilation source files with other compilation source files in the build.\",\n      \"type\": \"array\",\n      \"items\": {\n        \"oneOf\": [\n          {\n            \"type\": \"object\",\n            \"properties\": {\n              \"src\": {\n                \"type\": \"string\"\n              },\n              \"replaceWith\": {\n                \"type\": \"string\"\n              }\n            },\n            \"additionalProperties\": false,\n            \"required\": [\"src\", \"replaceWith\"]\n          },\n          {\n            \"type\": \"object\",\n            \"properties\": {\n              \"replace\": {\n                \"type\": \"string\"\n              },\n              \"with\": {\n                \"type\": \"string\"\n              }\n            },\n            \"additionalProperties\": false,\n            \"required\": [\"replace\", \"with\"]\n          }\n        ]\n      },\n      \"default\": []\n    },\n    \"reporters\": {\n      \"type\": \"array\",\n      \"description\": \"Karma reporters to use. Directly passed to the karma runner.\",\n      \"items\": {\n        \"type\": \"string\"\n      }\n    },\n    \"webWorkerTsConfig\": {\n      \"type\": \"string\",\n      \"description\": \"TypeScript configuration for Web Worker modules.\"\n    }\n  },\n  \"additionalProperties\": false,\n  \"required\": [\"main\", \"tsConfig\", \"karmaConfig\"],\n  \"definitions\": {\n    \"assetPattern\": {\n      \"oneOf\": [\n        {\n          \"type\": \"object\",\n          \"properties\": {\n            \"glob\": {\n              \"type\": \"string\",\n              \"description\": \"The pattern to match.\"\n            },\n            \"input\": {\n              \"type\": \"string\",\n              \"description\": \"The input directory path in which to apply 'glob'. Defaults to the project root.\"\n            },\n            \"output\": {\n              \"type\": \"string\",\n              \"description\": \"Absolute path within the output.\"\n            },\n            \"ignore\": {\n              \"description\": \"An array of globs to ignore.\",\n              \"type\": \"array\",\n              \"items\": {\n                \"type\": \"string\"\n              }\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\"glob\", \"input\", \"output\"]\n        },\n        {\n          \"type\": \"string\"\n        }\n      ]\n    },\n    \"extraEntryPoint\": {\n      \"oneOf\": [\n        {\n          \"type\": \"object\",\n          \"properties\": {\n            \"input\": {\n              \"type\": \"string\",\n              \"description\": \"The file to include.\"\n            },\n            \"bundleName\": {\n              \"type\": \"string\",\n              \"pattern\": \"^[\\\\w\\\\-.]*$\",\n              \"description\": \"The bundle name for this extra entry point.\"\n            },\n            \"inject\": {\n              \"type\": \"boolean\",\n              \"description\": \"If the bundle will be referenced in the HTML file.\",\n              \"default\": true\n            }\n          },\n          \"additionalProperties\": false,\n          \"required\": [\"input\"]\n        },\n        {\n          \"type\": \"string\",\n          \"description\": \"The file to include.\"\n        }\n      ]\n    }\n  }\n}\n"
  },
  {
    "path": "test/test-builder/schema.library.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema\",\n  \"title\": \"ng-packagr Target\",\n  \"description\": \"ng-packagr target options for Build Architect. Use to build library projects.\",\n  \"type\": \"object\",\n  \"properties\": {\n    \"project\": {\n      \"type\": \"string\",\n      \"description\": \"The file path for the ng-packagr configuration file, relative to the current workspace.\"\n    },\n    \"tsConfig\": {\n      \"type\": \"string\",\n      \"description\": \"The full path for the TypeScript configuration file, relative to the current workspace.\"\n    },\n    \"watch\": {\n      \"type\": \"boolean\",\n      \"description\": \"Run build when files change.\",\n      \"default\": false\n    }\n  },\n  \"additionalProperties\": false,\n  \"required\": [\"project\"]\n}\n"
  },
  {
    "path": "test/util/file.ts",
    "content": "export const ALL_PAGE_NAME_LIST = [\n  `root`,\n  `base-component`,\n  `base-directive`,\n  `base-tap`,\n  `complex-property-event`,\n  `complex-structure`,\n  `custom-structural-directive`,\n  `default-structural-directive`,\n  `ng-content`,\n  `base-forms`,\n  `component-use-template`,\n  `base-http`,\n  `self-component`,\n  `life-time-page`,\n  `life-time-page-use-component`,\n];\nexport const ALL_COMPONENT_NAME_LIST = [\n  `component1`,\n  `component2`,\n  `component3`,\n  `content`,\n  `content-multi`,\n  `component-need-template`,\n  `life-time`,\n];\n\nexport const TEST_LIBRARY_COMPONENT_LIST = [\n  'global-self-template-component',\n  'test-library-component',\n  'lib-comp1-component',\n  'other-component',\n  'outside-template-component',\n];\n"
  },
  {
    "path": "tsconfig.base.json",
    "content": "{\n  \"compilerOptions\": {\n    /* Visit https://aka.ms/tsconfig.json to read more about this file */\n\n    /* Basic Options */\n    // \"incremental\": true,                         /* Enable incremental compilation */\n    \"target\": \"ES2015\" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', 'ES2021', or 'ESNEXT'. */,\n    \"module\": \"commonjs\" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */,\n    \"lib\": [\n      \"ES2019\"\n    ] /* Specify library files to be included in the compilation. */,\n    // \"allowJs\": true,                             /* Allow javascript files to be compiled. */\n    // \"checkJs\": true,                             /* Report errors in .js files. */\n    // \"jsx\": \"preserve\",                           /* Specify JSX code generation: 'preserve', 'react-native', 'react', 'react-jsx' or 'react-jsxdev'. */\n    // \"declaration\": true,                         /* Generates corresponding '.d.ts' file. */\n    // \"declarationMap\": true,                      /* Generates a sourcemap for each corresponding '.d.ts' file. */\n    // \"sourceMap\": true,                           /* Generates corresponding '.map' file. */\n    // \"outFile\": \"./\",                             /* Concatenate and emit output to single file. */\n    \"outDir\": \"./\" /* Redirect output structure to the directory. */,\n    // \"rootDir\": \"./\",                             /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */\n    // \"composite\": true,                           /* Enable project compilation */\n    // \"tsBuildInfoFile\": \"./\",                     /* Specify file to store incremental compilation information */\n    // \"removeComments\": true,                      /* Do not emit comments to output. */\n    // \"noEmit\": true,                              /* Do not emit outputs. */\n    // \"importHelpers\": true,                       /* Import emit helpers from 'tslib'. */\n    // \"downlevelIteration\": true,                  /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */\n    // \"isolatedModules\": true,                     /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */\n\n    /* Strict Type-Checking Options */\n    \"strict\": false /* Enable all strict type-checking options. */,\n    // \"noImplicitAny\": true,                       /* Raise error on expressions and declarations with an implied 'any' type. */\n    // \"strictNullChecks\": true,                    /* Enable strict null checks. */\n    // \"strictFunctionTypes\": true,                 /* Enable strict checking of function types. */\n    // \"strictBindCallApply\": true,                 /* Enable strict 'bind', 'call', and 'apply' methods on functions. */\n    // \"strictPropertyInitialization\": true,        /* Enable strict checking of property initialization in classes. */\n    // \"noImplicitThis\": true,                      /* Raise error on 'this' expressions with an implied 'any' type. */\n    // \"alwaysStrict\": true,                        /* Parse in strict mode and emit \"use strict\" for each source file. */\n\n    /* Additional Checks */\n    // \"noUnusedLocals\": true,                      /* Report errors on unused locals. */\n    // \"noUnusedParameters\": true,                  /* Report errors on unused parameters. */\n    // \"noImplicitReturns\": true,                   /* Report error when not all code paths in function return a value. */\n    // \"noFallthroughCasesInSwitch\": true,          /* Report errors for fallthrough cases in switch statement. */\n    // \"noUncheckedIndexedAccess\": true,            /* Include 'undefined' in index signature results */\n    // \"noImplicitOverride\": true,                  /* Ensure overriding members in derived classes are marked with an 'override' modifier. */\n    // \"noPropertyAccessFromIndexSignature\": true,  /* Require undeclared properties from index signatures to use element accesses. */\n\n    /* Module Resolution Options */\n    \"moduleResolution\": \"node\" /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */,\n    // \"baseUrl\": \"./\",                             /* Base directory to resolve non-absolute module names. */\n    // \"paths\": {},                                 /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */\n    // \"rootDirs\": [],                              /* List of root folders whose combined content represents the structure of the project at runtime. */\n    // \"typeRoots\": [],                             /* List of folders to include type definitions from. */\n    // \"types\": [],                                 /* Type declaration files to be included in compilation. */\n    // \"allowSyntheticDefaultImports\": true,        /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */\n    \"esModuleInterop\": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */,\n    // \"preserveSymlinks\": true,                    /* Do not resolve the real path of symlinks. */\n    // \"allowUmdGlobalAccess\": true,                /* Allow accessing UMD globals from modules. */\n\n    /* Source Map Options */\n    // \"sourceRoot\": \"\",                            /* Specify the location where debugger should locate TypeScript files instead of source locations. */\n    // \"mapRoot\": \"\",                               /* Specify the location where debugger should locate map files instead of generated locations. */\n    // \"inlineSourceMap\": true,                     /* Emit a single file with source maps instead of having a separate file. */\n    // \"inlineSources\": true,                       /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */\n\n    /* Experimental Options */\n    \"experimentalDecorators\": true /* Enables experimental support for ES7 decorators. */,\n    // \"emitDecoratorMetadata\": true,               /* Enables experimental support for emitting type metadata for decorators. */\n\n    /* Advanced Options */\n    \"skipLibCheck\": true /* Skip type checking of declaration files. */,\n    \"forceConsistentCasingInFileNames\": true /* Disallow inconsistently-cased references to the same file. */\n  }\n}\n"
  },
  {
    "path": "tsconfig.builder.json",
    "content": "{\n  \"extends\": \"./tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"noImplicitThis\": true,\n    \"outDir\": \"./dist/builder\",\n    \"declaration\": false,\n    \"strict\": true\n  },\n  \"include\": [\"src/builder\"],\n  \"exclude\": [\n    \"./**/fixture\",\n    \"./**/*.template.ts\",\n    \"./**/*.d.ts\",\n    \"**/*.spec.ts\",\n    \"**/*.xspec.ts\",\n    \"**/*/karma/plugin/**/*\",\n    \"**/*/karma/client/**/*\"\n  ]\n}\n"
  },
  {
    "path": "tsconfig.doc.json",
    "content": "{\n  \"extends\": \"./tsconfig.base.json\",\n  \"files\": [\"./src/library/platform/index.ts\"],\n\n  \"compilerOptions\": {\n    \"baseUrl\": \"./src/library\",\n    \"noImplicitThis\": true,\n    \"outDir\": \"dist\",\n    \"declaration\": true,\n    \"target\": \"ES2015\",\n    \"module\": \"esnext\",\n    \"strict\": true,\n    \"useUnknownInCatchVariables\": false,\n    \"stripInternal\": true,\n    \"lib\": [\"es2019\", \"dom\"],\n    \"typeRoots\": [\"./src/library\"],\n    \"types\": [\"declaration\"],\n    \"paths\": {\n      \"angular-miniprogram/platform/default\": [\"./platform/default/index.ts\"],\n      \"angular-miniprogram/platform/wx\": [\"./platform/wx/index.ts\"],\n      \"angular-miniprogram/platform/type\": [\"./platform/type/index.ts\"],\n      \"angular-miniprogram/platform\": [\"./platform/index.ts\"],\n      \"angular-miniprogram/common\": [\"./common/index.ts\"],\n      \"angular-miniprogram/common/http\": [\"./common/http/index.ts\"]\n    }\n  },\n  \"exclude\": [\n    \"./src/**/*.template.ts\",\n    \"./src/**/*.d.ts\",\n    \"**/*.spec.ts\",\n    \"test\"\n  ],\n  \"angularCompilerOptions\": {\n    \"enableIvy\": true,\n    \"compilationMode\": \"full\"\n  }\n}\n"
  },
  {
    "path": "tsconfig.internal-schematics.json",
    "content": "{\n  \"extends\": \"./tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"sourceMap\": true\n  },\n  \"exclude\": [],\n  \"files\": [],\n  \"include\": [\"schematics/internal\"]\n}\n"
  },
  {
    "path": "tsconfig.json",
    "content": "{\n  \"compilerOptions\": {},\n  \"include\": [],\n  \"files\": [],\n  \"references\": [\n    { \"path\": \"./tsconfig.library.json\" },\n    { \"path\": \"./tsconfig.spec.json\" },\n    { \"path\": \"./tsconfig.builder.json\" }\n  ]\n}\n"
  },
  {
    "path": "tsconfig.library.json",
    "content": "{\n  \"extends\": \"./tsconfig.base.json\",\n  // \"files\": [\"./src/library/index.ts\"],\n  \"include\": [\n    \"./src/library\"\n  ],\n  \"compilerOptions\": {\n    \"baseUrl\": \"./src/library\",\n    \"noImplicitThis\": true,\n    \"outDir\": \"dist\",\n    \"declaration\": true,\n    \"target\": \"ES2015\",\n    \"module\": \"esnext\",\n    \"strict\": true,\n    \"useUnknownInCatchVariables\": false,\n    \"lib\": [\n      \"es2019\",\n      \"dom\"\n    ],\n    \"typeRoots\": [\n      \"./src/library\"\n    ],\n    \"types\": [\n      \"declaration\"\n    ],\n    \"paths\": {\n      \"angular-miniprogram/platform/default\": [\n        \"./platform/default/index.ts\"\n      ],\n      \"angular-miniprogram/platform/wx\": [\n        \"./platform/wx/index.ts\"\n      ],\n      \"angular-miniprogram/platform/type\": [\n        \"./platform/type/index.ts\"\n      ],\n      \"angular-miniprogram/platform\": [\n        \"./platform/index.ts\"\n      ],\n      \"angular-miniprogram/common\": [\n        \"./common/index.ts\"\n      ],\n      \"angular-miniprogram/common/http\": [\n        \"./common/http/index.ts\"\n      ],\n    }\n  },\n  \"exclude\": [\n    \"./src/**/*.template.ts\",\n    \"./src/**/*.d.ts\",\n    \"**/*.spec.ts\",\n    \"test\"\n  ],\n  \"angularCompilerOptions\": {\n    \"enableIvy\": true,\n    \"compilationMode\": \"full\"\n  }\n}"
  },
  {
    "path": "tsconfig.spec.json",
    "content": "{\n  \"extends\": \"./tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"sourceMap\": true,\n    \"paths\": {\n      \"angular-miniprogram/platform/default\": [\n        \"./src/library/platform/default/index.ts\"\n      ],\n      \"angular-miniprogram/platform/wx\": [\"./src/library/platform/wx/index.ts\"],\n      \"angular-miniprogram/platform/type\": [\n        \"./src/library/platform/type/index.ts\"\n      ],\n      \"angular-miniprogram/platform\": [\"./src/library/platform/index.ts\"],\n      \"angular-miniprogram/common\": [\"./src/library/common/index.ts\"],\n      \"angular-miniprogram/common/http\": [\"./src/library/common/http/index.ts\"]\n    }\n  },\n  \"exclude\": [\"**/fixture/**\"],\n  \"files\": [],\n  \"include\": [\"src/**/*.spec.ts\"]\n}\n"
  },
  {
    "path": "typedoc.json",
    "content": "{\n  \"entryPoints\": [\"./src/library/platform/index.ts\"],\n  \"out\": \"deploy/api-doc\",\n  \"tsconfig\": \"tsconfig.doc.json\",\n  \"excludePrivate\": true,\n  \"readme\": \"none\"\n}\n"
  }
]