[
  {
    "path": ".gitattributes",
    "content": "packages/core/template/** linguist-vendored\n"
  },
  {
    "path": ".github/FUNDING.yml",
    "content": "custom:\n  - 'https://afdian.com/a/flippedround'\n  - 'https://afdian.com/a/kejun'\n  - 'https://github.com/ModyQyW/sponsors'\n  - 'https://afdian.com/a/zguolee'\n"
  },
  {
    "path": ".github/workflows/core_release.yml",
    "content": "name: create-uni release CI\n\non:\n  push:\n    tags:\n      - 'core-v*'\n\njobs:\n  release:\n    name: Release\n    runs-on: ubuntu-latest\n\n    permissions:\n      contents: write\n      id-token: write\n\n    steps:\n      - name: Setup JS\n        uses: sxzz/workflows/setup-js@v1\n        with:\n          fetch-all: true\n\n      - name: Generate GitHub Changelog\n        run: pnpx changelogithub\n        continue-on-error: true\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n\n      - name: Publish to NPM\n        working-directory: packages/core\n        run: pnpm publish --access public --no-git-checks\n"
  },
  {
    "path": ".github/workflows/core_test.yml",
    "content": "name: create-uni Test CI\n\non:\n  push:\n    branches:\n      - main\n    tags-ignore:\n      - '**'\n    paths:\n      - 'packages/core/**'\n      - .github/workflows/core_test.yml\n\n  pull_request:\n    branches:\n      - main\n    paths:\n      - 'packages/core/**'\n      - .github/workflows/core_test.yml\n\njobs:\n  build:\n    runs-on: ${{ matrix.os }}\n\n    strategy:\n      matrix:\n        node: [20.x, 22.x]\n        os: [windows-latest, macos-latest]\n      fail-fast: false\n\n    steps:\n      - uses: actions/checkout@v4\n\n      - name: Install pnpm\n        uses: pnpm/action-setup@v2\n\n      - name: Set node ${{ matrix.node }}\n        uses: actions/setup-node@v4\n        with:\n          node-version: ${{ matrix.node }}\n          cache: pnpm\n\n      - name: Setup\n        run: npm i -g @antfu/ni\n\n      - name: Install\n        run: nci\n\n      - name: Build\n        run: nr build:core\n\n      - uses: actions/cache/save@v4\n        id: cache\n        with:\n          path: packages/core/dist/outfile.cjs\n          key: ${{ github.sha }}-${{ hashFiles('pnpm-lock.yaml') }}-${{ matrix.os }}-${{ matrix.node }}\n\n  test:\n    needs: build\n    strategy:\n      matrix:\n        flag-for-ts: ['', --ts]\n        flag-for-eslint: [-e]\n        flag-for-plugin: [-p import -p pages -p layouts -p manifest -p filePlatform -p root -p componentPlaceholder -m pinia -m unocss -m uniNetwork -m uniUse -m uniPromises -m uniEcharts -m zPaging -m vitest]\n        flag-for-ui: ['', -u uni, -u ano, -u wot, -u nut, -u uv, -u tdesign]\n\n        node: [20.x]\n        os: [windows-latest, macos-latest]\n\n    runs-on: ${{ matrix.os }}\n    env:\n      FEATURE_FLAGS: ${{ matrix.flag-for-ts }} ${{ matrix.flag-for-eslint }} ${{ matrix.flag-for-plugin }} ${{ matrix.flag-for-ui }}\n    steps:\n      - uses: actions/checkout@v4\n      - uses: pnpm/action-setup@v2\n        with:\n          version: 8\n      - uses: actions/setup-node@v4\n        with:\n          node-version: ${{ matrix.node }}\n          cache: pnpm\n      - uses: actions/cache/restore@v4\n        id: cache-restore\n        with:\n          path: packages/core/dist/outfile.cjs\n          key: ${{ github.sha }}-${{ hashFiles('pnpm-lock.yaml') }}-${{ matrix.os }}-${{ matrix.node }}\n      - name: 当没有缓存时，执行构建\n        if: steps.cache-restore.outputs.cache-hit != 'true'\n        run: pnpm install && pnpm build:core\n\n      - if: ${{ (contains(env.FEATURE_FLAGS, '-')) }}\n        name: 创建多参数项目\n        working-directory: ../\n        run: node ./create-uni/packages/core/dist/outfile.cjs sample-project ${{ env.FEATURE_FLAGS }}\n\n      - if: ${{ !(contains(env.FEATURE_FLAGS, '-')) }}\n        name: 创建基础项目\n        working-directory: ../\n        run: node ./create-uni/packages/core/dist/outfile.cjs sample-project\n\n      - name: 使用npm安装项目依赖\n        working-directory: ../sample-project\n        run: npm install --no-frozen-lockfile\n\n      - name: 移除node_modules\n        working-directory: ../sample-project\n        run: npx rimraf node_modules\n\n      - name: 使用pnpm安装项目依赖\n        working-directory: ../sample-project\n        run: pnpm install --no-frozen-lockfile\n\n      - name: 打包H5项目\n        working-directory: ../sample-project\n        run: pnpm build\n\n      - name: dev小程序项目\n        working-directory: ../sample-project\n        run: node ./../create-uni/scripts/dev.cjs\n\n      - name: 打包小程序项目\n        working-directory: ../sample-project\n        run: pnpm build mp-weixin\n\n      # - name: 输出环境信息\n      #   working-directory: ../sample-project\n      #   run: node ./../create-uni/packages/core/dist/outfile.cjs --info all\n"
  },
  {
    "path": ".github/workflows/core_test_template.yml",
    "content": "name: create-uni Test Template CI\n\non:\n  push:\n    branches:\n      - main\n    tags-ignore:\n      - '**'\n    paths:\n      - 'packages/core/**'\n      - .github/workflows/core_test.yml\n\n  pull_request:\n    branches:\n      - main\n    paths:\n      - 'packages/core/**'\n      - .github/workflows/core_test.yml\n\njobs:\n  build:\n    runs-on: ${{ matrix.os }}\n\n    strategy:\n      matrix:\n        node: [20.x, 22.x]\n        os: [windows-latest, macos-latest]\n      fail-fast: false\n\n    steps:\n      - uses: actions/checkout@v4\n\n      - name: Install pnpm\n        uses: pnpm/action-setup@v2\n\n      - name: Set node ${{ matrix.node }}\n        uses: actions/setup-node@v4\n        with:\n          node-version: ${{ matrix.node }}\n          cache: pnpm\n\n      - name: Setup\n        run: npm i -g @antfu/ni\n\n      - name: Install\n        run: nci\n\n      - name: Build\n        run: nr build:core\n\n      - uses: actions/cache/save@v4\n        id: cache\n        with:\n          path: packages/core/dist/outfile.cjs\n          key: ${{ github.sha }}-${{ hashFiles('pnpm-lock.yaml') }}-${{ matrix.os }}-${{ matrix.node }}\n\n  test:\n    needs: build\n    strategy:\n      fail-fast: false\n      matrix:\n        template: [-t vitesse]\n\n        node: [20.x]\n        os: [windows-latest, macos-latest]\n\n    runs-on: ${{ matrix.os }}\n    steps:\n      - uses: actions/checkout@v4\n      - uses: pnpm/action-setup@v2\n        with:\n          version: 8\n      - uses: actions/setup-node@v4\n        with:\n          node-version: ${{ matrix.node }}\n          cache: pnpm\n      - uses: actions/cache/restore@v4\n        id: cache-restore\n        with:\n          path: packages/core/dist/outfile.cjs\n          key: ${{ github.sha }}-${{ hashFiles('pnpm-lock.yaml') }}-${{ matrix.os }}-${{ matrix.node }}\n      - name: 当没有缓存时，执行构建\n        if: steps.cache-restore.outputs.cache-hit != 'true'\n        run: pnpm install && pnpm build:core\n\n      - name: 创建模板项目\n        working-directory: ../\n        run: node ./create-uni/packages/core/dist/outfile.cjs sample-project ${{ matrix.template }}\n\n      - name: 使用npm安装项目依赖\n        working-directory: ../sample-project\n        run: npm install --no-frozen-lockfile --legacy-peer-deps\n\n      - name: 移除node_modules\n        working-directory: ../sample-project\n        run: npx rimraf node_modules\n\n      - name: 使用pnpm安装项目依赖\n        working-directory: ../sample-project\n        run: pnpm install --no-frozen-lockfile\n\n      - name: 打包H5项目\n        working-directory: ../sample-project\n        run: pnpm build h5\n\n      - name: 打包小程序项目\n        working-directory: ../sample-project\n        run: pnpm build wx\n"
  },
  {
    "path": ".github/workflows/gui_release.yml",
    "content": "name: create-uni/gui CI\nenv:\n  DEBUG: napi:*\n  APP_NAME: create-uni/gui\n  MACOSX_DEPLOYMENT_TARGET: '10.13'\n  CARGO_INCREMENTAL: '1'\npermissions:\n  contents: write\n  id-token: write\non:\n  push:\n    branches:\n      - main\n    tags-ignore:\n      - '**'\n    paths:\n      - 'packages/gui/**'\n      - 'packages/ui/**'\n      - .github/workflows/gui_release.yml\n  pull_request: null\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref }}\n  cancel-in-progress: true\njobs:\n  build:\n    strategy:\n      fail-fast: false\n      matrix:\n        settings:\n          - host: macos-latest\n            target: x86_64-apple-darwin\n            build: pnpm build --target x86_64-apple-darwin\n          - host: macos-latest\n            target: aarch64-apple-darwin\n            build: pnpm build --target aarch64-apple-darwin\n          - host: windows-latest\n            build: pnpm build --target x86_64-pc-windows-msvc\n            target: x86_64-pc-windows-msvc\n          - host: windows-latest\n            build: pnpm build --target i686-pc-windows-msvc\n            target: i686-pc-windows-msvc\n          - host: windows-latest\n            target: aarch64-pc-windows-msvc\n            build: pnpm build --target aarch64-pc-windows-msvc\n    name: stable - ${{ matrix.settings.target }} - node@20\n    runs-on: ${{ matrix.settings.host }}\n    steps:\n      - uses: actions/checkout@v4\n      - name: setup pnpm\n        uses: pnpm/action-setup@v4\n      - name: Setup node\n        uses: actions/setup-node@v4\n        with:\n          node-version: 20\n          cache: pnpm\n      - name: Install\n        uses: dtolnay/rust-toolchain@stable\n        with:\n          toolchain: stable\n          targets: ${{ matrix.settings.target }}\n      - name: Cache cargo\n        uses: actions/cache@v4\n        with:\n          path: |\n            ~/.cargo/registry/index/\n            ~/.cargo/registry/cache/\n            ~/.cargo/git/db/\n            ~/.napi-rs\n            .cargo-cache\n            target/\n          key: ${{ matrix.settings.target }}-cargo-${{ matrix.settings.host }}\n\n      - name: build UI\n        working-directory: packages/ui\n        run: |\n          pnpm install\n          pnpm build\n\n      - name: Install dependencies\n        working-directory: packages/gui\n        run: pnpm install\n\n      - name: Setup node x86\n        uses: actions/setup-node@v4\n        if: matrix.settings.target == 'i686-pc-windows-msvc'\n        with:\n          node-version: 20\n          cache: pnpm\n          architecture: x86\n      - name: Build\n        working-directory: packages/gui\n        run: ${{ matrix.settings.build }}\n        shell: bash\n\n      - name: Upload artifact\n        uses: actions/upload-artifact@v4\n        with:\n          name: bindings-${{ matrix.settings.target }}\n          path: 'packages/gui/*.node'\n          if-no-files-found: error\n\n  publish:\n    name: Publish\n    runs-on: ubuntu-latest\n    needs:\n      - build\n    steps:\n      - uses: actions/checkout@v4\n      - name: setup pnpm\n        uses: pnpm/action-setup@v4\n      - name: Setup node\n        uses: actions/setup-node@v4\n        with:\n          node-version: 20\n          cache: pnpm\n\n      - name: Install dependencies\n        working-directory: packages/gui\n        run: pnpm install\n\n      - name: Download all artifacts\n        uses: actions/download-artifact@v4\n        with:\n          path: packages/gui/artifacts\n\n      - name: Move artifacts\n        working-directory: packages/gui\n        run: pnpm artifacts\n\n      - name: List packages\n        working-directory: packages/gui\n        run: ls -R ./npm\n        shell: bash\n\n      - name: Publish\n        working-directory: packages/gui\n        run: |\n          npm config set provenance true\n          if git log -1 --pretty=%B | grep \"^v\\?[0-9]\\+\\.[0-9]\\+\\.[0-9]\\+$\";\n          then\n            echo \"//registry.npmjs.org/:_authToken=$NPM_TOKEN\" >> ~/.npmrc\n            npm publish --access public\n          elif git log -1 --pretty=%B | grep \"^v\\?[0-9]\\+\\.[0-9]\\+\\.[0-9]\\+\";\n          then\n            echo \"//registry.npmjs.org/:_authToken=$NPM_TOKEN\" >> ~/.npmrc\n            npm publish --tag next --access public\n          else\n            echo \"Not a release, skipping publish\"\n          fi\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n          NPM_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }}\n"
  },
  {
    "path": ".github/workflows/info_release.yml",
    "content": "name: create-uni/info release CI\n\non:\n  push:\n    tags:\n      - 'info-v*'\n\njobs:\n  release:\n    name: Release\n    runs-on: ubuntu-latest\n\n    permissions:\n      contents: write\n      id-token: write\n\n    steps:\n      - name: Setup JS\n        uses: sxzz/workflows/setup-js@v1\n        with:\n          fetch-all: true\n\n      - name: Generate GitHub Changelog\n        run: pnpx changelogithub\n        continue-on-error: true\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n\n      - name: Publish to NPM\n        working-directory: packages/info\n        run: pnpm publish --access public --no-git-checks\n"
  },
  {
    "path": ".github/workflows/info_test.yml",
    "content": "name: create-uni/info Test CI\n\non:\n  push:\n    branches:\n      - main\n    tags-ignore:\n      - '**'\n    paths:\n      - 'packages/info/**'\n      - .github/workflows/info_test.yml\n\n  pull_request:\n    branches:\n      - main\n    paths:\n      - 'packages/info/**'\n      - .github/workflows/info_test.yml\n\njobs:\n  test:\n    runs-on: ${{ matrix.os }}\n\n    strategy:\n      matrix:\n        node: [20.x]\n        os: [windows-latest, macos-latest]\n      fail-fast: false\n\n    steps:\n      - uses: actions/checkout@v4\n\n      - name: Install pnpm\n        uses: pnpm/action-setup@v2\n\n      - name: Set node ${{ matrix.node }}\n        uses: actions/setup-node@v4\n        with:\n          node-version: ${{ matrix.node }}\n          cache: pnpm\n\n      - name: Setup\n        run: npm i -g @antfu/ni\n\n      - name: Install\n        run: nci\n\n      - name: Build\n        run: nr build:info\n\n      - name: Test\n        run: node ./packages/info/dist/outfile.cjs all\n"
  },
  {
    "path": ".github/workflows/lint.yml",
    "content": "name: Lint\n\non:\n  push:\n    branches:\n      - main\n    tags-ignore:\n      - '**'\n  pull_request:\n    branches:\n      - main\n\njobs:\n  lint:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n\n      - name: Install pnpm\n        uses: pnpm/action-setup@v2\n\n      - name: Set node\n        uses: actions/setup-node@v4\n        with:\n          node-version: 20.x\n          cache: pnpm\n\n      - name: Setup\n        run: npm i -g @antfu/ni\n\n      - name: Install\n        run: nci\n\n      - name: ESLint\n        run: pnpm lint\n\n      - name: cargo fmt\n        run: cd packages/gui && cargo fmt --check\n"
  },
  {
    "path": ".github/workflows/mcp_release.yml",
    "content": "name: create-uni/mcp release CI\n\non:\n  push:\n    tags:\n      - 'mcp-v*'\n\njobs:\n  release:\n    name: Release\n    runs-on: ubuntu-latest\n\n    permissions:\n      contents: write\n      id-token: write\n\n    steps:\n      - name: Setup JS\n        uses: sxzz/workflows/setup-js@v1\n        with:\n          fetch-all: true\n\n      - name: Generate GitHub Changelog\n        run: pnpx changelogithub\n        continue-on-error: true\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n\n      - name: Publish to NPM\n        working-directory: packages/mcp\n        run: pnpm publish --access public --no-git-checks\n"
  },
  {
    "path": ".github/workflows/uni-app_update.yml",
    "content": "name: update\n\non:\n  schedule:\n    - cron: '0 1 * * 1'\n\njobs:\n  update-dependencies:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n\n      - name: Install pnpm\n        uses: pnpm/action-setup@v4\n\n      - name: Set node\n        uses: actions/setup-node@v4\n        with:\n          node-version: 20.x\n          cache: pnpm\n\n      - name: update script\n        run: pnpm run up\n\n      - name: Commit and push if changes are made\n        run: |\n          git config --global user.email \"734243792@qq.com\"\n          git config --global user.name \"FliPPeDround\"\n          git add -A\n          git commit -m \"chore: update deps\" || echo \"No changes to commit\"\n\n      - name: Create Pull Request\n        uses: peter-evans/create-pull-request@v5\n        with:\n          token: ${{ secrets.MY_GITHUB_TOKEN }}\n          commit-message: 'chore: update deps'\n          title: 'chore: update deps'\n          body: Update dependencies\n          branch: chore/update-deps\n          delete-branch: true\n          base: main\n"
  },
  {
    "path": ".gitignore",
    "content": "# Created by .ignore support plugin (hsz.mobi)\n### Node template\n# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n\n# Runtime data\npids\n*.pid\n*.seed\n*.pid.lock\n\n# Directory for instrumented libs generated by jscoverage/JSCover\nlib-cov\n\n# Coverage directory used by tools like istanbul\ncoverage\n\n# nyc test coverage\n.nyc_output\n\n# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)\n.grunt\n\n# Bower dependency directory (https://bower.io/)\nbower_components\n\n# node-waf configuration\n.lock-wscript\n\n# Compiled binary addons (https://nodejs.org/api/addons.html)\nbuild/Release\n\n# Dependency directories\nnode_modules/\njspm_packages/\n\n# TypeScript v1 declaration files\ntypings/\n\n# Optional npm cache directory\n.npm\n\n# Optional eslint cache\n.eslintcache\n\n# Optional REPL history\n.node_repl_history\n\n# Output of 'npm pack'\n*.tgz\n\n# Yarn Integrity file\n.yarn-integrity\n\n# dotenv environment variables file\n.env\n\n# parcel-bundler cache (https://parceljs.org/)\n.cache\n\n# next.js build output\n.next\n\n# nuxt.js build output\n.nuxt\n\n# Nuxt generate\ndist\n\n# vuepress build output\n.vuepress/dist\n\n# Serverless directories\n.serverless\n\n# IDE\n.idea\n\n# turborepo\n.turbo\n.DS_Store\n"
  },
  {
    "path": ".vscode/settings.json",
    "content": "{\n  \"cSpell.words\": [\n    \"bumpp\",\n    \"dcloudio\",\n    \"esno\",\n    \"execa\",\n    \"gitee\",\n    \"kolorist\",\n    \"outro\",\n    \"Pinia\",\n    \"taze\",\n    \"Unocss\"\n  ],\n\n  \"prettier.enable\": false,\n  \"editor.formatOnSave\": false,\n\n  \"editor.codeActionsOnSave\": {\n    \"source.fixAll.eslint\": \"explicit\",\n    \"source.organizeImports\": \"never\"\n  },\n\n  \"eslint.validate\": [\n    \"javascript\",\n    \"javascriptreact\",\n    \"typescript\",\n    \"typescriptreact\",\n    \"vue\",\n    \"html\",\n    \"markdown\",\n    \"json\",\n    \"jsonc\",\n    \"yaml\"\n  ],\n  \"rust-analyzer.linkedProjects\": [\n    \"packages/gui/Cargo.toml\"\n  ]\n}\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2022 FliPPeDround <https://github.com/FliPPeDround>\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\n> create-vue is released under the MIT license:\n\n> MIT License\n\n> Copyright (c) 2021-present vuejs\n\n> Permission is hereby granted, free of charge, to any person obtaining a copy\n> of this software and associated documentation files (the \"Software\"), to deal\n> in the Software without restriction, including without limitation the rights\n> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n> copies of the Software, and to permit persons to whom the Software is\n> furnished to do so, subject to the following conditions:\n\n> The above copyright notice and this permission notice shall be included in all\n> copies or substantial portions of the Software.\n\n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n> SOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "<img src='./blink.svg' />\n<a href=\"https://github.com/uni-helper/create-uni/stargazers\"><img src=\"https://img.shields.io/github/stars/uni-helper/create-uni?colorA=09090b&colorB=fafafa&style=for-the-badge\"></a>\n<a href=\"https://npmx.dev/package/create-uni\"><img src=\"https://img.shields.io/npm/dm/create-uni?colorA=09090b&colorB=fafafa&style=for-the-badge\"></a>\n<a href=\"https://npmx.dev/package/create-uni\"><img src=\"https://img.shields.io/npm/v/create-uni?colorA=09090b&colorB=fafafa&style=for-the-badge\"></a>\n\n<br />\n\n# 📦 使用\n\n```shell\n# npm\n    npm create uni@latest\n\n# yarn\n    yarn create uni\n\n# pnpm\n    pnpm create uni\n```\n\n> [!IMPORTANT]\n> 建议添加上标记名（@latest），否则 npm 可能会解析到缓存的过时软件包版本。\n>\n<!-- <img src='./Terminal.svg' /> -->\n\n## 📖 介绍\n\n`create-uni` 是一个用于快速创建 uni-app 项目的轻量脚手架工具，它可以帮助你快速创建一个基于`vite`和`vue3`的`uni-app`项目，同时提供了一些模板供你选择。\n\n<p align=\"center\"><img  src=\".github/image/demo.png\"></p>\n\n## 🚤 快速使用\n\n```shell\npnpm create uni --gui\n```\n\n```shell\npnpm create uni <项目名称> --ts -m pinia -m uniUse -u ano -e\n```\n\n```shell\nnpx @create-uni/info@latest\n# --info  获取当前项目环境信息\n```\n\n### 参数说明\n\n| 配置项 | 参数 | 别名 | 可选值 |\n|  :---: | :---: | :---: | :---: |\n| Template | —— | t | 见[模板列表](#模板列表) |\n| TypeScript | ts | —— | —— |\n| Plugin | pluginList | p | 见[插件列表](#插件列表) |\n| Module | moduleList | m | 见[模块列表](#模块列表) |\n| UI | ui | u | 见[组件列表](#组件列表) |\n| Eslint | eslint | e | —— |\n| gui | gui | —— | —— |\n| info | info | —— | —— |\n\n#### 📦模板列表\n\n| 模板名 | 描述 | 参数名 |\n| :---: | :---: | :---: |\n| [vitesse-uni-app](https://github.com/uni-helper/vitesse-uni-app) | 由 Vite & uni-app 驱动的跨端快速启动模板 | vitesse |\n| [wot-starter](https://github.com/wot-ui/wot-starter) | 基于 vitesse-uni-app 的 wot-ui 快速起手模板 (集成 wot-ui v1) | wot-starter |\n| [wot-starter-v2](https://github.com/wot-ui/wot-starter/tree/v2) | 基于 vitesse-uni-app 的 wot-ui 快速起手模板 (集成 @wot-ui/ui@2) | wot-starter-v2 |\n| [wot-starter-retail](https://github.com/wot-ui/wot-starter-retail) | 基于 wot-ui 的 uni-app 零售行业模板 | wot-starter-retail |\n| [uview-pro-starter](https://github.com/anyup/uView-Pro-Starter) | 基于 vitesse-uni-app 的 uView Pro 快速启动模板 | uview-pro-starter |\n| [uview-pro-demo](https://github.com/anyup/uView-Pro) | 基于 uView Pro 的完整组件演示模板 | uview-pro-demo |\n| [unisave](https://github.com/sunpm/unisave) | 拥抱 web 开发，拯救 uniapp。适配所有 (app、mp、web) 平台 | unisave |\n| [tmui 3.2](https://tmui.design) | 优质 Vue3 TS Pinia Vite 跨端组件库 | tmui32 |\n\n#### 📦插件列表\n\n| 插件名 | 描述 | 参数名 |\n| :---: | :---: | :---: |\n| [vite-plugin-uni-components](https://github.com/uni-helper/vite-plugin-uni-components) | 按需自动引入组件 | import |\n| [vite-plugin-uni-pages](https://github.com/uni-helper/vite-plugin-uni-pages) | 提供基于文件系统的路由 | pages |\n| [vite-plugin-uni-layouts](https://github.com/uni-helper/vite-plugin-uni-layouts) | 提供类 nuxt 的 layouts 系统 | layouts |\n| [vite-plugin-uni-manifest](https://github.com/uni-helper/vite-plugin-uni-manifest) | 自动生成 manifest.json 文件 | manifest |\n| [vite-plugin-uni-platform](https://github.com/uni-helper/vite-plugin-uni-platform) | 基于文件名 (*.<h5\\|mp-weixin\\|app>.*) 的按平台编译插件 | filePlatform |\n| [uni-ku-root](https://github.com/uni-ku/root) | 模拟虚拟根组件 (支持 SFC 的 App.vue) | root |\n| [vite-plugin-component-placeholder](https://github.com/chouchouji/vite-plugin-component-placeholder) | 占位组件的原生实现 | componentPlaceholder |\n\n#### 📦模块列表\n\n| 模块名 | 描述 | 参数名 |\n| :---: | :---: | :---: |\n| [pinia](https://github.com/vuejs/pinia) | 符合直觉的 Vue.js 状态管理库 | pinia |\n| [unocss](https://github.com/antfu/unocss) | 即时按需的原子级 CSS 引擎 | unocss |\n| [vitest](https://github.com/uni-helper/vitest-environment-uniapp) | 基于 Vite 的测试框架 | vitest |\n| [uni-network](https://github.com/uni-helper/uni-network) | 为 uni-app 打造的基于 Promise 的网络请求库 | uniNetwork |\n| [uni-use](https://github.com/uni-helper/uni-use) | uni-app 组合式工具集 | uniUse |\n| [uni-promises](https://github.com/uni-helper/uni-promises) | 为 uni-app 提供的 Promise 包装器 | uniPromises |\n| [uni-echarts](https://uni-echarts.xiaohe.ink) | 适用于 uni-app 的 Apache ECharts 组件 | uniEcharts |\n| [z-paging](https://github.com/SmileZXLee/uni-z-paging) | 高性能、全平台兼容的 uni-app 分页组件 | zPaging |\n\n#### 📦组件列表\n\n| 组件名 | 描述 | 参数名 |\n| :---: | :---: | :---: |\n| [uni-ui](https://uniapp.dcloud.net.cn/component/uniui/uni-ui.html) | UniApp 官方组件库 | uni |\n| [wot-ui](https://v1.wot-ui.cn/) | 高颜值、轻量化的 uni-app 组件库(v1) | wot |\n| [wot-ui v2](https://wot-ui.cn/) | 轻量、美观、AI友好的 uni-app 组件库 | wot2 |\n| [TDesign](https://tdesign.tencent.com/uniapp/) | TDesign 组件库 uni-app 版 | tdesign |\n| [uView-Pro](https://uviewpro.cn/) | 全面支持 Vue3.0、TypeScript 的 uni-app 生态框架 | uview-pro |\n| [nutui-uniapp](https://uniapp-nutui.tech/) | 京东风格的轻量级移动端组件库 | nut |\n| [uv-ui](https://www.uvui.cn/components/intro.html) | 多平台快速开发的 UI 框架 | uv |\n| [ano-ui](https://ano-ui.netlify.app/) | 轻量级、漂亮、快速的 UnoCSS 组件库 | ano |\n\n## 🤝 参与贡献\n\n- 提交新功能\n- 反馈/解决[`issues`](https://github.com/uni-helper/create-uni/issues)\n- 提交新[`模板`](./packages/config/src/template.data.ts)/[`插件`](./packages/config/src/plugin.data.ts)/[`模块`](./packages/config/src/module.data.ts)/[`组件库`](./packages/config/src/ui.data.ts)\n\n## 🛠️ 开发\n- Node.js 版本 20+\n- Rust 版本 1.64+\n- 必须使用`pnpm`作为包管理工具\n- `Clone`此仓库\n- `pnpm i`安装依赖\n- `pnpm dev`运行\n- 可本地执行`pnpm create-uni`测试\n\n## 🌸 感谢\n\n项目灵感及部分代码来自 [create-vue](https://github.com/vuejs/create-vue)\n\n## 📄 License\n\n[MIT LICENSE](./LICENSE)\n\n## 🙇🏻‍♂️[赞助](https://afdian.com/a/flippedround)\n\n<p align=\"center\">\n  <a href=\"https://afdian.com/a/flippedround\">\n    <img alt=\"sponsors\" src=\"https://cdn.jsdelivr.net/gh/FliPPeDround/sponsors/sponsorkit/sponsors.svg\"/>\n  </a>\n</p>\n"
  },
  {
    "path": "eslint.config.js",
    "content": "import uni from '@uni-helper/eslint-config'\n\nexport default uni({\n  rules: {\n    'no-console': 'warn',\n  },\n  ignores: [\n    'dist/outfile.cjs',\n    'packages/gui',\n    'packages/core/template/**/*.test.js',\n  ],\n})\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"@create-uni/monorepo\",\n  \"type\": \"module\",\n  \"private\": true,\n  \"packageManager\": \"pnpm@9.9.0\",\n  \"description\": \"轻松创建你的 uni-app 项目\",\n  \"author\": \"FliPPeDround <flippedround@qq.com>\",\n  \"license\": \"MIT\",\n  \"funding\": \"https://afdian.com/a/flippedround\",\n  \"homepage\": \"https://github.com/uni-helper/create-uni#readme\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/uni-helper/create-uni.git\"\n  },\n  \"bugs\": \"https://github.com/uni-helper/create-uni/issues\",\n  \"keywords\": [\n    \"uni\",\n    \"uni-app\",\n    \"create-uni\",\n    \"cli\",\n    \"vue\",\n    \"miniapp\",\n    \"create\"\n  ],\n  \"scripts\": {\n    \"dev:shared\": \"turbo dev --filter=./packages/shared\",\n    \"dev:core\": \"turbo dev --filter=./packages/core\",\n    \"dev:gui\": \"turbo dev --filter=./packages/gui\",\n    \"dev:info\": \"turbo dev --filter=./packages/info\",\n    \"dev:mcp\": \"turbo dev --filter=./packages/mcp\",\n    \"build:core\": \"cd ./packages/core && pnpm build\",\n    \"build:info\": \"cd ./packages/info && pnpm build\",\n    \"build:ui\": \"cd ./packages/ui && pnpm build\",\n    \"build:mcp\": \"cd ./packages/mcp && pnpm build\",\n    \"release:core\": \"cd ./packages/core && pnpm release\",\n    \"release:info\": \"cd ./packages/info && pnpm release\",\n    \"release:mcp\": \"cd ./packages/mcp && pnpm release\",\n    \"release:gui\": \"cd ./packages/gui && pnpm release\",\n    \"dev\": \"turbo run dev\",\n    \"build\": \"turbo build\",\n    \"lint\": \"eslint .\",\n    \"lint:fix\": \"eslint . --fix && cd ./packages/gui && cargo fmt\",\n    \"typecheck\": \"tsc --noEmit\",\n    \"postinstall\": \"node scripts/link.cjs\",\n    \"up\": \"cd ./packages/core && pnpm run up\"\n  },\n  \"devDependencies\": {\n    \"@antfu/ni\": \"^0.23.0\",\n    \"@types/node\": \"^18.19.50\",\n    \"@uni-helper/eslint-config\": \"^0.2.0\",\n    \"bumpp\": \"^9.5.2\",\n    \"consola\": \"^3.3.3\",\n    \"cross-env\": \"^7.0.3\",\n    \"eslint\": \"^9.10.0\",\n    \"lint-staged\": \"^15.2.10\",\n    \"nodemon\": \"^3.1.9\",\n    \"simple-git-hooks\": \"^2.11.1\",\n    \"terser\": \"^5.31.6\",\n    \"tsup\": \"^8.2.4\",\n    \"turbo\": \"^2.3.3\",\n    \"typescript\": \"^5.5.4\",\n    \"unplugin-preprocessor-directives\": \"^1.0.3\",\n    \"vitest\": \"^3.2.4\"\n  },\n  \"simple-git-hooks\": {\n    \"pre-commit\": \"pnpm lint-staged\"\n  },\n  \"lint-staged\": {\n    \"*\": \"eslint --fix\"\n  }\n}\n"
  },
  {
    "path": "packages/config/package.json",
    "content": "{\n  \"name\": \"@create-uni/config\",\n  \"type\": \"module\",\n  \"version\": \"0.0.1\",\n  \"private\": true,\n  \"packageManager\": \"pnpm@9.9.0\",\n  \"description\": \"create-uni 模块配置\",\n  \"author\": \"FliPPeDround <flippedround@qq.com>\",\n  \"license\": \"MIT\",\n  \"funding\": \"https://afdian.com/a/flippedround\",\n  \"homepage\": \"https://github.com/uni-helper/create-uni#readme\",\n  \"repository\": {\n    \"directory\": \"packages/config\",\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/uni-helper/create-uni.git\"\n  },\n  \"bugs\": \"https://github.com/uni-helper/create-uni/issues\",\n  \"exports\": {\n    \".\": \"./src/index.ts\",\n    \"./*\": \"./*\"\n  },\n  \"main\": \"./src/index.ts\",\n  \"typesVersions\": {\n    \"*\": {\n      \"*\": [\n        \"./*\"\n      ]\n    }\n  },\n  \"files\": [\n    \"src\"\n  ],\n  \"dependencies\": {\n    \"kolorist\": \"^1.8.0\"\n  }\n}\n"
  },
  {
    "path": "packages/config/src/index.ts",
    "content": "import type { BaseTemplateListWithList, Options, TemplateList, TemplateValue } from './type'\nimport MODULES from './module.data'\nimport PLUGINS from './plugin.data'\nimport TEMPLATES from './template.data'\nimport UI from './ui.data'\n\nexport {\n  MODULES,\n  PLUGINS,\n  TEMPLATES,\n  UI,\n}\n\nexport type {\n  BaseTemplateListWithList,\n  Options,\n  TemplateList,\n  TemplateValue,\n}\n"
  },
  {
    "path": "packages/config/src/module.data.ts",
    "content": "import type { Options } from './type'\nimport { trueColor as rgb } from 'kolorist'\n\nexport default [\n  {\n    label: rgb(235, 186, 43)('Pinia'),\n    value: 'pinia',\n    name: 'pinia',\n    website: 'https://pinia.vuejs.org/zh/',\n    github: 'https://github.com/vuejs/pinia',\n    hint: '符合直觉的 Vue.js 状态管理库',\n  },\n  {\n    label: rgb(204, 204, 204)('Unocss'),\n    value: 'unocss',\n    name: 'unocss',\n    github: 'https://github.com/unocss/unocss',\n    website: 'https://unocss.dev/',\n    hint: '即时按需的原子级 CSS 引擎',\n  },\n  {\n    label: rgb(56, 204, 110)('Vitest'),\n    value: 'vitest',\n    name: 'vitest',\n    github: 'https://github.com/uni-helper/vitest-environment-uniapp',\n    website: 'https://vitest.dev/',\n    hint: 'Vitest 是一个基于 Vite 的测试框架',\n  },\n  {\n    label: rgb(108, 92, 231)('uni-network'),\n    value: 'uniNetwork',\n    name: 'uni-network',\n    github: 'https://github.com/uni-helper/uni-network',\n    website: 'https://uni-network.netlify.app/',\n    hint: '为 uni-app 打造的基于 Promise 的网络请求库',\n  },\n  {\n    label: rgb(63, 168, 125)('uni-use'),\n    value: 'uniUse',\n    name: 'uni-use',\n    github: 'https://github.com/uni-helper/uni-use',\n    website: 'https://uni-helper.github.io/uni-use/',\n    hint: 'uni-app 组合式工具集',\n  },\n  {\n    label: rgb(52, 152, 219)('uni-promises'),\n    value: 'uniPromises',\n    name: 'uni-promises',\n    github: 'https://github.com/uni-helper/uni-promises',\n    hint: 'uni-app promise 化的 API',\n  },\n  {\n    label: rgb(24, 121, 78)('uni-echarts'),\n    value: 'uniEcharts',\n    name: 'uni-echarts',\n    github: 'https://github.com/xiaohe0601/uni-echarts',\n    hint: '适用于 uni-app 的 Apache ECharts 组件',\n  },\n  {\n    label: rgb(0, 122, 255)('z-paging'),\n    value: 'zPaging',\n    name: 'z-paging',\n    github: 'https://github.com/SmileZXLee/uni-z-paging',\n    hint: '高性能、全平台兼容的 uni-app 分页组件',\n  },\n] as const satisfies readonly Options[]\n"
  },
  {
    "path": "packages/config/src/plugin.data.ts",
    "content": "import type { Options } from './type'\nimport { trueColor as rgb } from 'kolorist'\n\nexport default [\n  {\n    label: rgb(236, 112, 99)('vite-plugin-uni-components'),\n    value: 'import',\n    name: 'vite-plugin-uni-components',\n    hint: '按需自动引入组件',\n    github: 'https://github.com/uni-helper/vite-plugin-uni-components',\n  },\n  {\n    label: rgb(243, 156, 18)('vite-plugin-uni-pages'),\n    value: 'pages',\n    name: 'vite-plugin-uni-pages',\n    hint: '提供基于文件系统的路由',\n    github: 'https://github.com/uni-helper/vite-plugin-uni-pages',\n  },\n  {\n    label: rgb(241, 196, 15)('vite-plugin-uni-layouts'),\n    value: 'layouts',\n    name: 'vite-plugin-uni-layouts',\n    hint: '提供类 nuxt 的 layouts 系统',\n    github: 'https://github.com/uni-helper/vite-plugin-uni-layouts',\n  },\n  {\n    label: rgb(46, 204, 113)('vite-plugin-uni-manifest'),\n    value: 'manifest',\n    name: 'vite-plugin-uni-manifest',\n    hint: '自动生成 manifest.json 文件',\n    github: 'https://github.com/uni-helper/vite-plugin-uni-manifest',\n  },\n  {\n    label: rgb(52, 152, 219)('vite-plugin-uni-platform'),\n    value: 'filePlatform',\n    name: 'vite-plugin-uni-platform',\n    hint: '基于文件名 (*.<h5|mp-weixin|app>.*) 的按平台编译插件',\n    github: 'https://github.com/uni-helper/vite-plugin-uni-platform',\n  },\n  {\n    label: rgb(146, 220, 210)('uni-ku-root'),\n    value: 'root',\n    name: 'uni-ku-root',\n    hint: '模拟虚拟根组件(支持SFC的App.vue)',\n    github: 'https://github.com/uni-ku/root',\n  },\n  {\n    label: rgb(102, 153, 51)('vite-plugin-component-placeholder'),\n    value: 'componentPlaceholder',\n    name: 'vite-plugin-component-placeholder',\n    hint: '占位组件的原生实现',\n    github: 'https://github.com/chouchouji/vite-plugin-component-placeholder',\n  },\n] as const satisfies readonly Options[]\n"
  },
  {
    "path": "packages/config/src/template.data.ts",
    "content": "import type { TemplateList } from './type'\nimport { green, lightMagenta, trueColor as rgb } from 'kolorist'\n\nexport default [\n  {\n    label: `vitesse-uni-app`,\n    description: `由${green('Uni Helper')}维护的快速启动模板`,\n    value: 'vitesse',\n    url: {\n      github: 'https://github.com/uni-helper/vitesse-uni-app.git',\n    },\n    website: 'https://vitesse-docs.netlify.app/',\n    playground: 'https://vitesse-uni-app.netlify.app/',\n  },\n  {\n    label: `wot`,\n    description: `由${green('Wot UI')}提供的基于 vitesse-uni-app 的快速启动模板`,\n    value: 'wot',\n    list: [\n      {\n        label: `wot-starter`,\n        description: `由${rgb(77, 128, 240)('Wot UI')}提供的基于 vitesse-uni-app 的快速启动模板(集成 wot-ui v1)`,\n        value: 'wot-starter',\n        url: {\n          github: '-b v1 https://github.com/wot-ui/wot-starter.git',\n        },\n        website: 'https://starter-v1.wot-ui.cn/',\n        playground: 'https://starter-v1.wot-ui.cn/demo/#/',\n      },\n      {\n        label: `wot-starter-v2`,\n        description: `由${rgb(77, 128, 240)('Wot UI')}提供的基于 vitesse-uni-app 的快速启动模板(集成 @wot-ui/ui@2)`,\n        value: 'wot-starter-v2',\n        url: {\n          github: '-b v2 https://github.com/wot-ui/wot-starter.git',\n        },\n        website: 'https://starter.wot-ui.cn/',\n        playground: 'https://starter.wot-ui.cn/demo/#/',\n      },\n      {\n        label: 'wot-starter-retail',\n        description: `基于${rgb(77, 128, 240)('Wot UI')}的 uni-app 零售行业模板`,\n        value: 'wot-starter-retail',\n        url: {\n          github: 'https://github.com/wot-ui/wot-starter-retail.git',\n        },\n        playground: 'https://starter-retail.wot-ui.cn/',\n      },\n    ],\n  },\n  {\n    label: `uView Pro`,\n    description: `由 ${green('uView Pro')} 提供的快速开发模板`,\n    value: 'uview-pro',\n    list: [\n      {\n        label: `uView-Pro-Starter`,\n        description: `由 ${green('uView Pro')} 提供的基于 vitesse-uni-app 的快速启动模板`,\n        value: 'uview-pro-starter',\n        url: {\n          github: 'https://github.com/anyup/uView-Pro-Starter.git',\n        },\n        website: 'https://uviewpro.cn/',\n        playground: 'https://h5.uviewpro.cn/',\n      },\n      {\n        label: `uView-Pro-Demo`,\n        description: `由 ${green('uView Pro')} 提供的完整组件演示模板`,\n        value: 'uview-pro-demo',\n        url: {\n          github: 'https://github.com/anyup/uView-Pro.git',\n        },\n        website: 'https://uviewpro.cn/',\n        playground: 'https://h5.uviewpro.cn/',\n      },\n    ],\n  },\n  {\n    label: `unisave`,\n    description: `拥抱 web 开发，${lightMagenta('拯救')}uniapp。适配所有 (app、mp、web) 平台`,\n    value: 'unisave',\n    url: {\n      github: 'https://github.com/sunpm/unisave.git',\n    },\n    website: 'https://unisave-docs.netlify.app/',\n    playground: 'https://uni-save.netlify.app/',\n  },\n  {\n    label: `tmui3.2`,\n    description: `优质 Vue3 TS Pinia Vite 跨端组件库模板`,\n    value: 'tmui32',\n    url: {\n      gitee: 'https://gitee.com/LYTB/tmui-design.git',\n    },\n    website: 'https://tmui.design/',\n    playground: 'https://tmui.design/h5by32/',\n  },\n] as TemplateList[]\n"
  },
  {
    "path": "packages/config/src/type.d.ts",
    "content": "export interface Options {\n  label: string\n  hint: string\n  value: string | null\n  name: string\n  github?: string\n  website?: string\n}\n\ninterface GithubGitee {\n  github: string\n  gitee: string\n}\n\ntype AtLeastOne<T, U = { [K in keyof T]: Pick<T, K> }> = Partial<T> & U[keyof U]\n\ninterface BaseTemplateListCommon {\n  /**\n   * 模板名称\n   */\n  label: string\n  /**\n   * 模板类型 不能为custom\n   * @property {string} type - 模板类型\n   */\n  value: string\n  /**\n   * 模板描述\n   */\n  description?: string\n  /**\n   * 官方网站\n   */\n  website?: string\n  /**\n   * 演练场\n   */\n  playground?: string\n  /**\n   * 模板下载完成后的回调函数\n   * @param {string} root - 模板下载的根目录\n   */\n  callBack?: (root: string) => void\n}\n\ninterface BaseTemplateListWithUrl extends BaseTemplateListCommon {\n  /**\n   * 模板地址 github和gitee地址至少存在一个\n   * @property {string} github - github地址\n   * @property {string} gitee - gitee地址\n   */\n  url: AtLeastOne<GithubGitee>\n  list?: never // 确保list不会出现在这个类型中\n}\n\nexport interface BaseTemplateListWithList extends BaseTemplateListCommon {\n  url?: never // 确保url不会出现在这个类型中\n  /**\n   * 模板列表\n   * @type {BaseTemplateListWithUrl[]} - 模板列表\n   */\n  list: BaseTemplateListWithUrl[]\n}\n\ntype BaseTemplateList = BaseTemplateListWithUrl | BaseTemplateListWithList\n\nexport type TemplateList = BaseTemplateList\n\ninterface CustomTempValue {\n  type: 'custom'\n}\n\nexport interface UnCustomTempValue {\n  type: string\n  url: AtLeastOne<GithubGitee>\n  callBack?: (root: string) => void\n}\n\nexport type TemplateValue = UnCustomTempValue | CustomTempValue\n"
  },
  {
    "path": "packages/config/src/ui.data.ts",
    "content": "import type { Options } from './type'\nimport { green, trueColor as rgb } from 'kolorist'\n\nexport default [\n  {\n    label: '不需要组件库',\n    name: '不需要组件库',\n    hint: '',\n    value: null,\n  },\n  {\n    label: green('Uni Ui'),\n    hint: 'UniApp官方组件库',\n    name: 'uni-ui',\n    value: 'uni',\n    website: 'https://uniapp.dcloud.net.cn/component/uniui/uni-ui.html',\n  },\n  {\n    label: rgb(77, 128, 240)('Wot Ui'),\n    hint: '高颜值、轻量化的uni-app组件库',\n    name: 'wot-design-uni',\n    value: 'wot',\n    github: 'https://github.com/Moonofweisheng/wot-design-uni',\n    website: 'https://v1.wot-ui.cn/',\n  },\n  {\n    label: rgb(28, 100, 253)('Wot Ui V2'),\n    hint: '轻量、美观、AI友好的 uni-app 组件库',\n    name: 'wot-ui',\n    value: 'wot2',\n    github: 'https://github.com/wot-ui/wot-ui',\n    website: 'https://wot-ui.cn/',\n  },\n  {\n    label: rgb(0, 82, 217)('TDesign Uni'),\n    hint: 'TDesign 组件库 uni-app 版',\n    name: 'TDesign',\n    value: 'tdesign',\n    github: 'https://github.com/Tencent/tdesign-miniprogram',\n    website: 'https://tdesign.tencent.com/uniapp/',\n  },\n  {\n    label: rgb(41, 121, 255)('uView Pro'),\n    hint: '全面支持 Vue3.0、TypeScript 的 uni-app 生态框架',\n    name: 'uView Pro',\n    value: 'uview-pro',\n    github: 'https://github.com/anyup/uView-Pro',\n    website: 'https://uviewpro.cn/',\n  },\n  {\n    label: rgb(250, 44, 25)('Nut Ui'),\n    hint: '京东风格的轻量级移动端组件库',\n    name: 'nutui-uniapp',\n    value: 'nut',\n    github: 'https://github.com/nutui-uniapp/nutui-uniapp',\n    website: 'https://nutui-uniapp.pages.dev/',\n  },\n  {\n    label: rgb(60, 156, 255)('Uv Ui'),\n    hint: '多平台快速开发的UI框架',\n    name: 'uv-ui',\n    value: 'uv',\n    github: 'https://github.com/climblee/uv-ui',\n    website: 'https://www.uvui.cn/',\n  },\n  {\n    label: rgb(147, 85, 224)('Ano UI'),\n    hint: '轻量级、漂亮、快速的 UnoCSS 组件库',\n    name: 'ano-ui',\n    value: 'ano',\n    github: 'https://github.com/ano-ui/ano-ui',\n    website: 'https://ano-ui.netlify.app/',\n  },\n] as const satisfies readonly Options[]\n"
  },
  {
    "path": "packages/core/.gitignore",
    "content": "# Created by .ignore support plugin (hsz.mobi)\n### Node template\n# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n\n# Runtime data\npids\n*.pid\n*.seed\n*.pid.lock\n\n# Directory for instrumented libs generated by jscoverage/JSCover\nlib-cov\n\n# Coverage directory used by tools like istanbul\ncoverage\n\n# nyc test coverage\n.nyc_output\n\n# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)\n.grunt\n\n# Bower dependency directory (https://bower.io/)\nbower_components\n\n# node-waf configuration\n.lock-wscript\n\n# Compiled binary addons (https://nodejs.org/api/addons.html)\nbuild/Release\n\n# Dependency directories\nnode_modules/\njspm_packages/\n\n# TypeScript v1 declaration files\ntypings/\n\n# Optional npm cache directory\n.npm\n\n# Optional eslint cache\n.eslintcache\n\n# Optional REPL history\n.node_repl_history\n\n# Output of 'npm pack'\n*.tgz\n\n# Yarn Integrity file\n.yarn-integrity\n\n# dotenv environment variables file\n.env\n\n# parcel-bundler cache (https://parceljs.org/)\n.cache\n\n# next.js build output\n.next\n\n# nuxt.js build output\n.nuxt\n\n# Nuxt generate\ndist\n\n# vuepress build output\n.vuepress/dist\n\n# Serverless directories\n.serverless\n\n# IDE\n.idea\n\n# turborepo\n.turbo\n"
  },
  {
    "path": "packages/core/bump.config.ts",
    "content": "// bump.config.ts\nimport { defineConfig } from 'bumpp'\n\nexport default defineConfig({\n  tag: 'core-v%s',\n})\n"
  },
  {
    "path": "packages/core/package.json",
    "content": "{\n  \"name\": \"create-uni\",\n  \"type\": \"module\",\n  \"version\": \"2.15.0\",\n  \"packageManager\": \"pnpm@9.9.0\",\n  \"description\": \"轻松创建你的 uni-app 项目\",\n  \"author\": \"FliPPeDround <flippedround@qq.com>\",\n  \"license\": \"MIT\",\n  \"funding\": \"https://afdian.com/a/flippedround\",\n  \"homepage\": \"https://github.com/uni-helper/create-uni#readme\",\n  \"repository\": {\n    \"directory\": \"packages/core\",\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/uni-helper/create-uni.git\"\n  },\n  \"bugs\": \"https://github.com/uni-helper/create-uni/issues\",\n  \"keywords\": [\n    \"uni\",\n    \"uni-app\",\n    \"create-uni\",\n    \"cli\",\n    \"vue\",\n    \"miniapp\",\n    \"create\"\n  ],\n  \"sideEffects\": false,\n  \"bin\": {\n    \"create-uni\": \"dist/outfile.cjs\"\n  },\n  \"files\": [\n    \"dist/outfile.cjs\",\n    \"template\"\n  ],\n  \"scripts\": {\n    \"build\": \"tsup\",\n    \"dev\": \"cross-env CREATE_UNI_DEV=true tsup --watch\",\n    \"prepublishOnly\": \"nr build\",\n    \"release\": \"bumpp\",\n    \"up\": \"cd ./template && pnpx taze@latest major -w -r && cd ./base && pnpx @dcloudio/uvm@latest --manager pnpm\"\n  },\n  \"devDependencies\": {\n    \"@clack/prompts\": \"^0.9.0\",\n    \"@create-uni/config\": \"workspace:*\",\n    \"@create-uni/shared\": \"workspace:*\",\n    \"@types/cross-spawn\": \"^6.0.6\",\n    \"@types/ejs\": \"^3.1.5\",\n    \"@types/minimist\": \"^1.2.5\",\n    \"cross-spawn\": \"^7.0.6\",\n    \"ejs\": \"^3.1.10\",\n    \"kolorist\": \"^1.8.0\",\n    \"minimist\": \"^1.2.8\"\n  }\n}\n"
  },
  {
    "path": "packages/core/src/command/actions/gui.ts",
    "content": "import process from 'node:process'\nimport { MODULES, PLUGINS, TEMPLATES, UI } from '@create-uni/config'\nimport { sync } from 'cross-spawn'\nimport { composeCommand } from '../composeCommand'\n\nexport function actionGuiCLI() {\n  // #if CREATE_UNI_DEV\n  // @ts-expect-error compile\n  const fullCustomCommand = 'pnpm create-uni-gui'\n  // #endif\n\n  // #if !CREATE_UNI_DEV\n  // @ts-expect-error compile\n  // eslint-disable-next-line ts/no-redeclare\n  const fullCustomCommand = composeCommand('@create-uni/gui')\n  // #endif\n\n  const input = JSON.stringify({\n    templateList: TEMPLATES,\n    plugin: PLUGINS,\n    module: MODULES,\n    ui: UI,\n  })\n\n  const [command, ..._args] = fullCustomCommand.split(' ')\n\n  process.env.CREATE_UNI_GUI_INPUT = input\n  const { error, stdout } = sync(command, [..._args], {\n    stdio: 'pipe',\n  })\n\n  if (error)\n    throw new Error(`Error executing command: ${error.message}`)\n\n  let data: any\n  if (stdout.length > 0) {\n    const data_string = stdout.toString()\n    try {\n      const _data = JSON.parse(data_string)\n      if (_data.useTemplate) {\n        if (_data.projectName === '') {\n          _data.projectName = 'uni-app'\n        }\n        if (_data.useTemplate === 'custom') {\n          _data.useTemplate = null\n        }\n        data = _data\n      }\n    }\n    catch {\n      process.exit(0)\n    }\n  }\n\n  if (!data?.projectName) {\n    process.exit(0)\n  }\n  return data\n}\n"
  },
  {
    "path": "packages/core/src/command/actions/info.ts",
    "content": "import { sync } from 'cross-spawn'\nimport { composeCommand } from '../composeCommand'\n\nexport function actionInfoCLI() {\n  // #if CREATE_UNI_DEV\n  // @ts-expect-error compile\n  const fullCustomCommand = 'pnpm create-uni-info'\n  // #endif\n\n  // #if !CREATE_UNI_DEV\n  // @ts-expect-error compile\n  // eslint-disable-next-line ts/no-redeclare\n  const fullCustomCommand = composeCommand('@create-uni/info')\n  // #endif\n\n  const [command, ..._args] = fullCustomCommand.split(' ')\n  const { error } = sync(command, [..._args], {\n    stdio: 'inherit',\n  })\n\n  if (error)\n    throw new Error(`Error executing command: ${error.message}`)\n}\n"
  },
  {
    "path": "packages/core/src/command/composeCommand.ts",
    "content": "import process from 'node:process'\nimport { pkgFromUserAgent } from '@/utils'\n\nexport function composeCommand(\n  command: string,\n) {\n  const { name, version } = pkgFromUserAgent(process.env.npm_config_user_agent)!\n  const isYarn1 = name === 'yarn' && version.startsWith('1.')\n\n  let pkgManager = 'npx'\n  if (name === 'pnpm')\n    pkgManager = 'pnpm dlx'\n  if (name === 'yarn')\n    pkgManager = 'yarn dlx'\n  if (name === 'bun')\n    pkgManager = 'bun x'\n\n  return `${pkgManager} ${command}${isYarn1 ? '' : '@latest'}`\n}\n"
  },
  {
    "path": "packages/core/src/command/index.ts",
    "content": "import process from 'node:process'\nimport { helpMessage } from '@/constants'\nimport { actionGuiCLI } from './actions/gui'\nimport { actionInfoCLI } from './actions/info'\n\nconst actions = {\n  help: () => {\n    console.log(helpMessage)\n    process.exit(0)\n  },\n  info: () => {\n    actionInfoCLI()\n    process.exit(0)\n  },\n  gui: () => {\n    return actionGuiCLI()\n  },\n}\n\nexport function commandAction(argv: any) {\n  if (argv.help) {\n    actions.help()\n  }\n  else if (argv.info) {\n    actions.info()\n  }\n  else if (argv.gui) {\n    return actions.gui()\n  }\n}\n"
  },
  {
    "path": "packages/core/src/command/runCommand.ts",
    "content": "import type { StdioOptions } from 'node:child_process'\nimport { sync } from 'cross-spawn'\n\nexport function runCommand(\n  fullCustomCommand: string,\n  stdio: StdioOptions,\n  argv?: any,\n) {\n  const [command, ..._args] = fullCustomCommand.split(' ')\n  const { error, stdout } = sync(command, [..._args, argv ?? ''], {\n    stdio,\n  })\n  if (error) {\n    throw new Error(`Error executing command: ${error.message}`)\n  }\n  if (stdout.length > 0) {\n    console.log(stdout.toString())\n  }\n}\n"
  },
  {
    "path": "packages/core/src/constants/index.ts",
    "content": "export const helpMessage = `\\\n使用: create-uni [PROJECT_NAME] [OPTION]...\n\\n\n使用CLI创建uni-app项目。\n如果没有参数，则进入交互模式。\n\\n\n选项:\n  -t              使用特定模板\n  --ts            使用TypeScript\n  -p              使用特定插件\n  -m              使用特定模块\n  -ui             使用特定UI库\n  -e              使用eslint\n  -h,   --help    显示帮助信息\n  -i,   --info    显示版本信息\n  -g,   --gui     显示图形界面\n`\n"
  },
  {
    "path": "packages/core/src/index.ts",
    "content": "#!/usr/bin/env node\n\nimport type { UnCustomTempValue } from '@create-uni/config/src/type'\nimport type { Answers } from './question'\nimport {\n  existsSync,\n  mkdirSync,\n  readFileSync,\n  renameSync,\n  rmdirSync,\n  unlinkSync,\n  writeFileSync,\n} from 'node:fs'\nimport { resolve } from 'node:path'\nimport process from 'node:process'\nimport { intro, outro, spinner } from '@clack/prompts'\nimport { generateBanner } from '@create-uni/shared'\nimport ejs from 'ejs'\nimport { green } from 'kolorist'\nimport minimist from 'minimist'\nimport { commandAction } from './command'\nimport { question } from './question'\nimport askForceOverwrite from './question/file'\nimport { cancelMesssage } from './question/onCancel'\nimport {\n  dowloadTemplate,\n  getPkgManager,\n  jsonStringifyWithoutKeysQuotes,\n  preOrderDirectoryTraverse,\n  printFinish,\n  renderTemplate,\n  replaceProjectName,\n} from './utils'\nimport { postOrderDirectoryTraverse } from './utils/directoryTraverse'\nimport {\n  validateModules,\n  validatePlugins,\n  validateTemplateType,\n  validateUIName,\n} from './utils/validateArgv'\n\nasync function init() {\n  const argv = minimist(process.argv.slice(2), {\n    alias: {\n      templateType: ['t'],\n      needsTypeScript: ['ts'],\n      pluginList: ['p'],\n      moduleList: ['m'],\n      UIName: ['ui', 'u'],\n      needsEslint: ['eslint', 'e'],\n      help: ['h', 'help'],\n      info: ['info', 'i'],\n      gui: ['gui', 'g'],\n      force: ['force', 'f'],\n    },\n    string: ['_'],\n  })\n\n  let result: Answers = {}\n\n  const guiData = commandAction(argv)\n\n  const projectName = argv._[0] || guiData?.projectName\n\n  intro(generateBanner('Uni-creator - 快速创建 uni-app 项目'))\n  const s = spinner()\n\n  if (!projectName) {\n    try {\n      result = await question()\n    }\n    catch (cancelled) {\n    // eslint-disable-next-line no-console\n      console.log((<{ message: string }>cancelled).message)\n      process.exit(1)\n    }\n  }\n  else if (argv._[0]) {\n    const templateType = validateTemplateType(argv.templateType)\n    const UIName = validateUIName(argv.UIName)\n    const pluginList = validatePlugins(argv.pluginList)\n    const moduleList = validateModules(argv.moduleList)\n\n    const shouldOverwrite = argv.force ? true : await askForceOverwrite(projectName)\n\n    result = {\n      projectName,\n      shouldOverwrite,\n      templateType,\n      needsTypeScript: argv['needsTypeScript'!],\n      pluginList,\n      moduleList,\n      UIName,\n      needsEslint: argv['needsEslint'!],\n    }\n  }\n  else if (guiData.projectName) {\n    const templateType = validateTemplateType(guiData.useTemplate)\n    const UIName = validateUIName(guiData.requireUI)\n    const pluginList = validatePlugins(guiData.requiredPlugins)\n    const moduleList = validateModules(guiData.requiredModules)\n    result = {\n      projectName: guiData.projectName,\n      shouldOverwrite: true,\n      templateType,\n      needsTypeScript: guiData.requireTypeScript,\n      pluginList,\n      moduleList,\n      UIName,\n      needsEslint: guiData.requireESLint,\n    }\n  }\n\n  s.start('正在创建模板...')\n  const cwd = process.cwd()\n  const root = resolve(guiData?.installationPath ?? cwd, result.projectName!)\n  const packageManager = getPkgManager()\n\n  function emptyDir(dir: string) {\n    if (!existsSync(dir))\n      return\n\n    postOrderDirectoryTraverse(\n      dir,\n      dir => rmdirSync(dir),\n      file => unlinkSync(file),\n    )\n  }\n\n  if (existsSync(root) && result.shouldOverwrite)\n    emptyDir(root)\n\n  else if (!existsSync(root))\n    mkdirSync(root)\n\n  if (result.templateType!.type !== 'custom') {\n    const { templateType, projectName } = result\n    await dowloadTemplate(templateType as UnCustomTempValue, projectName!, root, s)\n    printFinish(root, cwd, packageManager, s)\n    return\n  }\n\n  const templateRoot = resolve(__dirname, './../template')\n\n  type Callback = (dataStore: Record<string, any>) => void\n  const callbacks: Callback[] = []\n  function render(templateName: string) {\n    const templateDir = resolve(templateRoot, templateName)\n    renderTemplate(templateDir, root, callbacks)\n  }\n\n  // Render templates\n  render('base')\n\n  const needUnocss = result.moduleList?.includes('unocss') || ['ano'].includes(result.UIName!)\n  const needUI = Boolean(result.UIName)\n\n  // Render Config\n  const config = {\n    typescript: result.needsTypeScript,\n    lint: result.needsEslint,\n  }\n\n  for (const [key, needs] of Object.entries(config)) {\n    if (needs)\n      render(`config/${key}`)\n  }\n\n  // Render Plugins\n  result.pluginList?.forEach(plugin => render(`plugin/${plugin}`))\n  if (needUI && !result.pluginList?.includes('import'))\n    render('plugin/import')\n\n  // Render modules\n  result.moduleList?.forEach(module => render(`module/${module}`))\n  if (needUnocss && !result.moduleList?.includes('unocss'))\n    render('module/unocss')\n\n  // Render UI\n  const UI = {\n    unocss: needUnocss,\n    [result.UIName!]: needUI,\n  }\n\n  for (const [key, needs] of Object.entries(UI)) {\n    if (needs)\n      render(`UI/${key}`)\n  }\n\n  const dataStore: Record<string, any> = {}\n  // Process callbacks\n  for (const cb of callbacks)\n    await cb(dataStore)\n\n  preOrderDirectoryTraverse(\n    root,\n    () => {},\n    (filepath) => {\n      if (filepath.endsWith('.ejs')) {\n        const template = readFileSync(filepath, 'utf-8')\n        const dest = filepath.replace(/\\.ejs$/, '')\n\n        if (dest.includes('vite.config') && dataStore[dest].extraConfig)\n          dataStore[dest].extraConfig = jsonStringifyWithoutKeysQuotes(dataStore[dest].extraConfig)\n\n        const content = ejs.render(template, dataStore[dest])\n\n        writeFileSync(dest, content)\n        unlinkSync(filepath)\n      }\n    },\n  )\n\n  if (result.needsTypeScript) {\n    preOrderDirectoryTraverse(\n      root,\n      () => {},\n      (filepath) => {\n        // Rename `.js` to `.ts`\n        if (filepath.endsWith('.js') && !filepath.endsWith('eslint.config.js')) {\n          const tsFilePath = filepath.replace(/\\.js$/, '.ts')\n          if (existsSync(tsFilePath))\n            unlinkSync(filepath)\n\n          else\n            renameSync(filepath, tsFilePath)\n        }\n        // Rename 'jsconfig.json' to 'tsconfig.json\n        else if (filepath.endsWith('jsconfig.json')) {\n          const tsFilePath = filepath.replace('jsconfig.json', 'tsconfig.json')\n          if (existsSync(tsFilePath))\n            unlinkSync(filepath)\n\n          else\n            renameSync(filepath, tsFilePath)\n        }\n      },\n    )\n\n    // Rename entry in `index.html`\n    const indexHtmlPath = resolve(root, 'index.html')\n    const indexHtmlContent = readFileSync(indexHtmlPath, 'utf8')\n    writeFileSync(indexHtmlPath, indexHtmlContent.replace('src/main.js', 'src/main.ts'))\n\n    // Rename <script setup> To <script setup lang=\"ts\">\n    preOrderDirectoryTraverse(\n      resolve(root, 'src'),\n      () => {},\n      (filepath) => {\n        if (filepath.endsWith('.vue')) {\n          const vueContent = readFileSync(filepath, 'utf8')\n          const vueContentWithTs = vueContent.replace('<script setup>', '<script setup lang=\"ts\">')\n          writeFileSync(filepath, vueContentWithTs)\n        }\n      },\n    )\n  }\n  replaceProjectName(root, result.projectName!)\n\n  printFinish(root, cwd, packageManager, s)\n}\n\ninit()\n  .catch((error) => {\n    outro(cancelMesssage)\n    console.log(error.message.includes('操作已取消') ? '' : error)\n    console.log(`🚀 遇到问题? 快速反馈：${green('https://github.com/uni-helper/create-uni/issues/new/choose')}`)\n    process.exit(0)\n  })\n"
  },
  {
    "path": "packages/core/src/question/choices.ts",
    "content": "import { confirm } from '@clack/prompts'\n\nexport function needsTypeScript() {\n  return confirm({\n    message: '是否使用 TypeScript 语法?',\n    active: '是',\n    inactive: '否',\n    initialValue: false,\n  })\n}\n\nexport function needsEslint() {\n  return confirm({\n    message: '是否使用 ESLint?',\n    active: '是',\n    inactive: '否',\n    initialValue: true,\n  })\n}\n"
  },
  {
    "path": "packages/core/src/question/file.ts",
    "content": "import { confirm, isCancel } from '@clack/prompts'\nimport { canSkipEmptying } from '@create-uni/shared'\nimport { printCancel } from './onCancel'\n\nexport default async (targetDir: string): Promise<boolean | undefined> => {\n  if (canSkipEmptying(targetDir))\n    return true\n  const message = `${targetDir === '.' ? '当前文件' : `目标文件\"${targetDir}\"`}非空，是否覆盖？`\n  const shouldOverwrite = await confirm({\n    message,\n    active: '是',\n    inactive: '否',\n  })\n  if (shouldOverwrite === false || isCancel(shouldOverwrite)) {\n    printCancel()\n  }\n  else {\n    return shouldOverwrite\n  }\n}\n"
  },
  {
    "path": "packages/core/src/question/index.ts",
    "content": "import type { TemplateValue } from './template/type'\nimport { group } from '@clack/prompts'\nimport { needsEslint, needsTypeScript } from './choices'\nimport askForceOverwrite from './file'\nimport moduleList from './module'\nimport projectName from './name'\nimport { printCancel } from './onCancel'\nimport pluginList from './plugin'\nimport templateType from './template'\nimport UIName from './ui'\n\nexport interface Answers {\n  projectName?: string\n  shouldOverwrite?: boolean\n  templateType?: TemplateValue\n  needsTypeScript?: boolean\n  pluginList?: string[]\n  moduleList?: string[]\n  UIName?: string | null\n  needsEslint?: boolean\n}\n\nexport async function question(): Promise<Answers> {\n  const answersName = await group(\n    {\n      projectName,\n      shouldOverwrite: ({ results }) => {\n        return askForceOverwrite(results.projectName!)\n      },\n    },\n    {\n      onCancel() {\n        printCancel()\n      },\n    },\n  ) as Answers\n\n  const template = await templateType()\n  if (template.type !== 'custom') {\n    return {\n      ...answersName,\n      templateType: template,\n    }\n  }\n\n  const answerOptions = await group(\n    {\n\n      needsTypeScript,\n      pluginList,\n      moduleList,\n      UIName,\n      needsEslint,\n    },\n    {\n      onCancel() {\n        printCancel()\n      },\n    },\n  ) as Answers\n\n  return {\n    ...answersName,\n    ...answerOptions,\n    templateType: template,\n  }\n}\n"
  },
  {
    "path": "packages/core/src/question/module/index.ts",
    "content": "import type { MultiSelectOptions } from '@clack/prompts'\nimport { multiselect } from '@clack/prompts'\nimport { MODULES } from '@create-uni/config'\n\nexport default () => (\n  multiselect({\n    message: '选择需要的库:',\n    options: MODULES as unknown as MultiSelectOptions<string>['options'],\n    required: false,\n  })\n)\n"
  },
  {
    "path": "packages/core/src/question/name.ts",
    "content": "import { text } from '@clack/prompts'\n\nexport default () => (\n  text({\n    message: '请输入项目名称:',\n    placeholder: 'uni-app',\n    validate: (value) => {\n      if (!value)\n        return '项目名称不能为空'\n    },\n  })\n)\n"
  },
  {
    "path": "packages/core/src/question/onCancel.ts",
    "content": "import process from 'node:process'\nimport { cancel } from '@clack/prompts'\n\nexport const cancelMesssage = '操作已取消'\n\nexport function printCancel() {\n  cancel(cancelMesssage)\n  process.exit(0)\n}\n"
  },
  {
    "path": "packages/core/src/question/plugin/index.ts",
    "content": "import type { MultiSelectOptions } from '@clack/prompts'\nimport { multiselect } from '@clack/prompts'\nimport { PLUGINS } from '@create-uni/config'\n\nexport default () => (\n  multiselect({\n    message: '选择需要的vite插件:',\n    options: PLUGINS as unknown as MultiSelectOptions<string>['options'],\n    required: false,\n  })\n)\n"
  },
  {
    "path": "packages/core/src/question/template/index.ts",
    "content": "import type { BaseTemplateListWithList, TemplateValue } from '@create-uni/config'\nimport process from 'node:process'\nimport { cancel, isCancel, select } from '@clack/prompts'\nimport { TEMPLATES } from '@create-uni/config'\nimport { cancelMesssage } from '../onCancel'\n\nexport default async (): Promise<TemplateValue> => {\n  const templateType = await select({\n    message: '请选择 uni-app 模板：',\n    options: [\n      {\n        label: '自定义模板',\n        value: 'custom',\n      },\n      ...TEMPLATES.map(item => ({\n        label: `${item.label}${item.list ? ' ▼' : ''}`,\n        value: item.value,\n        hint: item.description,\n      })),\n    ],\n    initialValue: 'custom',\n  })\n  if (isCancel(templateType)) {\n    cancel(cancelMesssage)\n    process.exit(0)\n  }\n\n  if (templateType === 'custom') {\n    return { type: 'custom' }\n  }\n\n  const group = TEMPLATES.find((item) => {\n    if (item.value === templateType && item.list) {\n      return true\n    }\n    return false\n  }) as BaseTemplateListWithList | undefined\n  if (group) {\n    const template = await select({\n      message: `请选择 ${templateType} 模板`,\n      options: group.list.map(item => ({\n        label: item.label,\n        value: item.value,\n        hint: item.description,\n      })),\n    })\n    if (isCancel(template)) {\n      cancel(cancelMesssage)\n      process.exit(0)\n    }\n    else {\n      const temp = group.list.find(item => item.value === template)!\n      return {\n        type: template,\n        url: temp.url,\n        callBack: temp?.callBack,\n      }\n    }\n  }\n  else {\n    const temp = TEMPLATES.find(item => item.value === templateType)!\n    return {\n      type: templateType,\n      url: temp.url!,\n      callBack: temp?.callBack,\n    }\n  }\n}\n"
  },
  {
    "path": "packages/core/src/question/type.d.ts",
    "content": "export interface Options {\n  label: string\n  hint: string\n  value: string | null\n  name: string\n  github?: string\n  website?: string\n}\n"
  },
  {
    "path": "packages/core/src/question/ui/index.ts",
    "content": "import type { SelectOptions } from '@clack/prompts'\nimport { select } from '@clack/prompts'\nimport { UI } from '@create-uni/config'\n\nexport default () => (\n  select({\n    message: '选择需要的组件库:',\n    options: UI as unknown as SelectOptions<string>['options'],\n  })\n)\n"
  },
  {
    "path": "packages/core/src/utils/clearFile.ts",
    "content": "import * as fs from 'node:fs'\nimport * as path from 'node:path'\n\nexport function clearDirectory(directoryPath: string): void {\n  // 获取目录下的所有文件和子目录\n  const files = fs.readdirSync(directoryPath)\n\n  // 遍历所有文件和子目录\n  for (const file of files) {\n    const filePath = path.join(directoryPath, file)\n\n    // 如果是子目录，则递归清空子目录\n    if (fs.statSync(filePath).isDirectory()) {\n      clearDirectory(filePath)\n    }\n    else {\n      // 如果是文件，则删除文件\n      fs.unlinkSync(filePath)\n    }\n  }\n}\n"
  },
  {
    "path": "packages/core/src/utils/cloneRepo.ts",
    "content": "import type { spinner } from '@clack/prompts'\nimport type { UnCustomTempValue } from '@create-uni/config/src/type'\nimport { exec } from 'node:child_process'\nimport { promises as fs } from 'node:fs'\nimport { join } from 'node:path'\nimport process from 'node:process'\nimport { bold } from 'kolorist'\nimport { replaceProjectName } from './setPackageName'\n\nasync function removeGitFolder(localPath: string): Promise<void> {\n  const gitFolderPath = join(localPath, '.git')\n  await fs.rm(gitFolderPath, { recursive: true, force: true })\n}\n\nasync function cloneRepo(gitUrls: string[], localPath: string): Promise<void> {\n  let lastError = null\n\n  for (const gitUrl of gitUrls) {\n    try {\n      await new Promise<void>((resolve, reject) => {\n        exec(`git clone ${gitUrl} ${localPath}`, async (error) => {\n          if (error) {\n            reject(error)\n            return\n          }\n\n          try {\n            await removeGitFolder(localPath)\n            resolve()\n          }\n          catch (error) {\n            reject(error)\n          }\n        })\n      })\n      return\n    }\n    catch (error) {\n      lastError = error\n    }\n  }\n\n  if (lastError) {\n    // @ts-expect-error 类型断言\n    throw new Error(lastError)\n  }\n}\n\nfunction getRepoUrlList(url: UnCustomTempValue['url']) {\n  const { github, gitee } = url\n  // 返回一个数组优先使用 gitee，没有则使用 github的镜像地址githubfast.com，最后使用 github\n  return [gitee, github?.replace('github.com', 'githubfast.com'), github].filter(Boolean) as string[]\n}\n\nexport async function dowloadTemplate(data: UnCustomTempValue, name: string, root: string, loading: ReturnType<typeof spinner>) {\n  const repoUrlList = getRepoUrlList(data.url)\n  try {\n    await cloneRepo(repoUrlList, root)\n  }\n  catch (error) {\n    loading.stop(`${bold('模板创建失败！')}`, 2)\n    console.log(error)\n    process.exit(1)\n  }\n\n  replaceProjectName(root, name)\n  data.callBack?.(root)\n}\n"
  },
  {
    "path": "packages/core/src/utils/deepMerge.ts",
    "content": "const isObject = (val: any) => val && typeof val === 'object'\nconst mergeArrayWithDedupe = (a: any, b: any) => Array.from(new Set([...a, ...b]))\n\n/**\n * Recursively merge the content of the new object to the existing one\n * @param {object} target the existing object\n * @param {object} obj the new object\n */\nexport function deepMerge(target: any, obj: any) {\n  for (const key of Object.keys(obj)) {\n    const oldVal = target[key]\n    const newVal = obj[key]\n\n    if (Array.isArray(oldVal) && Array.isArray(newVal))\n      target[key] = mergeArrayWithDedupe(oldVal, newVal)\n\n    else if (isObject(oldVal) && isObject(newVal))\n      target[key] = deepMerge(oldVal, newVal)\n\n    else\n      target[key] = newVal\n  }\n\n  return target\n}\n"
  },
  {
    "path": "packages/core/src/utils/directoryTraverse.ts",
    "content": "import * as fs from 'node:fs'\nimport * as path from 'node:path'\n\ntype DirectoryTraverse = (dir: string, dirCallback: (dir: string) => void, fileCallback: (file: string) => void) => void\n\nexport const preOrderDirectoryTraverse: DirectoryTraverse = (dir, dirCallback, fileCallback) => {\n  for (const filename of fs.readdirSync(dir)) {\n    if (filename === '.git')\n      continue\n\n    const fullpath = path.resolve(dir, filename)\n    if (fs.lstatSync(fullpath).isDirectory()) {\n      dirCallback(fullpath)\n      if (fs.existsSync(fullpath))\n        preOrderDirectoryTraverse(fullpath, dirCallback, fileCallback)\n\n      continue\n    }\n    fileCallback(fullpath)\n  }\n}\n\nexport const postOrderDirectoryTraverse: DirectoryTraverse = (dir, dirCallback, fileCallback) => {\n  for (const filename of fs.readdirSync(dir)) {\n    const fullpath = path.resolve(dir, filename)\n    if (fs.lstatSync(fullpath).isDirectory()) {\n      postOrderDirectoryTraverse(fullpath, dirCallback, fileCallback)\n      dirCallback(fullpath)\n      continue\n    }\n    fileCallback(fullpath)\n  }\n}\n"
  },
  {
    "path": "packages/core/src/utils/getCommand.ts",
    "content": "export function getCommand(packageManager: string, scriptName: string, args?: string) {\n  if (scriptName === 'install')\n    return packageManager === 'yarn' ? 'yarn' : `${packageManager} install`\n\n  if (args) {\n    return packageManager === 'npm'\n      ? `npm run ${scriptName} -- ${args}`\n      : `${packageManager} ${scriptName} ${args}`\n  }\n  else {\n    return packageManager === 'npm' ? `npm run ${scriptName}` : `${packageManager} ${scriptName}`\n  }\n}\n"
  },
  {
    "path": "packages/core/src/utils/getPkgManager.ts",
    "content": "import process from 'node:process'\n\nexport function getPkgManager() {\n  const pkgInfo = pkgFromUserAgent(process.env.npm_config_user_agent)\n  return pkgInfo ? pkgInfo.name : 'npm'\n}\n\nexport function pkgFromUserAgent(userAgent: string | undefined) {\n  if (!userAgent)\n    return undefined\n  const pkgSpec = userAgent.split(' ')[0]\n  const pkgSpecArr = pkgSpec.split('/')\n\n  return {\n    name: pkgSpecArr[0] || 'npm',\n    version: pkgSpecArr[1],\n  }\n}\n"
  },
  {
    "path": "packages/core/src/utils/index.ts",
    "content": "export * from './clearFile'\nexport * from './cloneRepo'\nexport * from './directoryTraverse'\nexport * from './getPkgManager'\nexport * from './jsonStringifyWithoutKeysQuotes'\nexport * from './printFinish'\nexport * from './renderTemplate'\nexport * from './setPackageName'\n"
  },
  {
    "path": "packages/core/src/utils/injectUtils.ts",
    "content": "import type { PluginData } from './types'\nimport { deepMerge } from './deepMerge'\n\nfunction addResolver(plugin: PluginData, resolver: string) {\n  if (plugin.initializer == null || plugin.initializer.includes(resolver)) {\n    return plugin\n  }\n\n  return {\n    ...plugin,\n    initializer: plugin.initializer.replace(\n      /(resolvers\\s*:\\s*\\[)([\\s\\S]*?)(\\])/,\n      (_, prefix, content, suffix) => {\n        const cont = content.trim()\n\n        return `${prefix}${cont}${cont ? ', ' : ''}${resolver}${suffix}`\n      },\n    ),\n  }\n}\n\nfunction mergeExtraConfig(oldConfig: Record<string, any> | null, config: Record<string, any>) {\n  return deepMerge(oldConfig || {}, config)\n}\n\nexport const injectUtils = {\n  deepMerge,\n  addResolver,\n  mergeExtraConfig,\n}\n"
  },
  {
    "path": "packages/core/src/utils/jsonStringifyWithoutKeysQuotes.ts",
    "content": "export function jsonStringifyWithoutKeysQuotes(obj: object) {\n  const jsonString = JSON.stringify(obj, null, 2).slice(1, -1).trim()\n\n  return jsonString.replace(/\"(\\w+)\":/g, '$1:')\n}\n"
  },
  {
    "path": "packages/core/src/utils/printFinish.ts",
    "content": "import type { spinner } from '@clack/prompts'\nimport type { getPkgManager } from './getPkgManager'\nimport { relative } from 'node:path'\nimport { note } from '@clack/prompts'\nimport { dim, lightGreen } from 'kolorist'\nimport { getCommand } from './getCommand'\n\nexport function printFinish(\n  root: string,\n  cwd: string,\n  packageManager: ReturnType<typeof getPkgManager>,\n  loading: ReturnType<typeof spinner>,\n) {\n  loading.stop('🎉 恭喜！您的项目已准备就绪。')\n  const cdProjectName = () => {\n    if (root !== cwd) {\n      const cdProjectName = relative(cwd, root)\n      return cdProjectName.includes(' ') ? `\"${cdProjectName}\"` : cdProjectName\n    }\n  }\n\n  const gettingStarted = `\n${dim('$')} ${lightGreen(`cd ${cdProjectName()}`)}\n${dim('$')} ${lightGreen(getCommand(packageManager, 'install'))}\n${dim('$')} ${lightGreen(getCommand(packageManager, 'dev'))}\n  `\n  note(gettingStarted.trim().replace(/^\\t\\t\\t/gm, ''), dim('Getting Started'))\n  console.log()\n}\n"
  },
  {
    "path": "packages/core/src/utils/renderTemplate.ts",
    "content": "import * as fs from 'node:fs'\nimport * as path from 'node:path'\nimport { pathToFileURL } from 'node:url'\n\nimport { deepMerge } from './deepMerge'\nimport { injectUtils } from './injectUtils'\nimport { sortDependencies } from './sortDependencies'\n\n/**\n * Renders a template folder/file to the file system,\n * by recursively copying all files under the `src` directory,\n * with the following exception:\n *   - `_filename` should be renamed to `.filename`\n *   - Fields in `package.json` should be recursively merged\n * @param {string} src source filename to copy\n * @param {string} dest destination filename of the copy operation\n */\ntype Callback = (dataStore: Record<string, any>) => void\n\nexport function renderTemplate(src: string, dest: string, callbacks: Callback[]) {\n  const stats = fs.statSync(src)\n\n  if (stats.isDirectory()) {\n    // skip node_module\n    if (path.basename(src) === 'node_modules')\n      return\n\n    // if it's a directory, render its subdirectories and files recursively\n    fs.mkdirSync(dest, { recursive: true })\n    for (const file of fs.readdirSync(src))\n      renderTemplate(path.resolve(src, file), path.resolve(dest, file), callbacks)\n\n    return\n  }\n\n  const filename = path.basename(src)\n\n  if (fs.existsSync(dest)) {\n    const isPackageJson = filename === 'package.json'\n    const isExtensionsJson = filename === 'extensions.json' || filename === 'settings.json'\n    const isJsConfigJson = filename === 'jsconfig.json'\n\n    if (isPackageJson || isExtensionsJson || isJsConfigJson) {\n      const existing = JSON.parse(fs.readFileSync(dest, 'utf8'))\n      const newContent = JSON.parse(fs.readFileSync(src, 'utf8'))\n      const merged = deepMerge(existing, newContent)\n      const result = isPackageJson ? sortDependencies(merged) : merged\n      fs.writeFileSync(dest, `${JSON.stringify(result, null, 2)}\\n`)\n      return\n    }\n  }\n\n  if (filename.startsWith('_')) {\n    // rename `_file` to `.file`\n    dest = path.resolve(path.dirname(dest), filename.replace(/^_/, '.'))\n  }\n\n  if ((filename === '_gitignore' || filename === '_npmrc') && fs.existsSync(dest)) {\n    // append to existing .gitignore\n    const existing = fs.readFileSync(dest, 'utf8')\n    const newGitignore = fs.readFileSync(src, 'utf8')\n    fs.writeFileSync(dest, `${existing}\\n${newGitignore}`)\n    return\n  }\n\n  // data file for EJS templates\n  if (filename.endsWith('.data.mjs')) {\n    // use dest path as key for the data store\n    dest = dest.replace(/\\.data\\.mjs$/, '')\n\n    // Add a callback to the array for late usage when template files are being processed\n    callbacks.push(async (dataStore: Record<string, any>) => {\n      const getData = (await import(pathToFileURL(src).toString())).default\n\n      // Though current `getData` are all sync, we still retain the possibility of async\n      dataStore[dest] = await getData({\n        oldData: dataStore[dest] || {},\n        utils: injectUtils,\n      })\n    })\n\n    return // skip copying the data file\n  }\n\n  fs.copyFileSync(src, dest)\n}\n"
  },
  {
    "path": "packages/core/src/utils/setPackageName.ts",
    "content": "import { existsSync, readFileSync, writeFileSync } from 'node:fs'\nimport { join } from 'node:path'\n\nfunction replaceNameContent(filePath: string, projectName: string) {\n  if (!existsSync(filePath))\n    return\n  const fileContent = JSON.parse(readFileSync(filePath, 'utf8'))\n  fileContent.name = projectName\n  writeFileSync(filePath, JSON.stringify(fileContent, null, 2))\n}\n\nexport function replaceProjectName(root: string, name: string) {\n  const projectName = name.toLocaleLowerCase().replace(/\\s/g, '-')\n  const pkgPath = join(root, 'package.json')\n\n  replaceNameContent(pkgPath, projectName)\n}\n"
  },
  {
    "path": "packages/core/src/utils/sortDependencies.ts",
    "content": "interface PackageJson {\n  dependencies?: Record<string, string>\n  devDependencies?: Record<string, string>\n  peerDependencies?: Record<string, string>\n  optionalDependencies?: Record<string, string>\n  [key: string]: any\n}\n\nexport function sortDependencies(packageJson: PackageJson): PackageJson {\n  const sorted: Record<string, Record<string, string>> = {}\n\n  const depTypes = ['dependencies', 'devDependencies', 'peerDependencies', 'optionalDependencies']\n\n  for (const depType of depTypes) {\n    if (packageJson[depType]) {\n      sorted[depType] = {}\n\n      Object.keys(packageJson[depType])\n        .sort()\n        .forEach((name) => {\n          sorted[depType][name] = packageJson[depType][name]\n        })\n    }\n  }\n\n  return {\n    ...packageJson,\n    ...sorted,\n  }\n}\n"
  },
  {
    "path": "packages/core/src/utils/types.ts",
    "content": "export interface PluginData {\n  id: string\n  importer?: string\n  dynamicImporter?: string\n  initializer?: string\n}\n"
  },
  {
    "path": "packages/core/src/utils/validateArgv.ts",
    "content": "import type { TemplateValue } from './../question/template/type'\n\nimport process from 'node:process'\nimport { outro } from '@clack/prompts'\n\nimport { MODULES, PLUGINS, TEMPLATES, UI } from '@create-uni/config'\nimport { bold, gray } from 'kolorist'\n\ntype ArgvBase = string | null\ntype ArgvList = ArgvBase | string[]\n\nfunction validateTemplateType(argvTemplate: ArgvBase): TemplateValue {\n  if (!argvTemplate)\n    return { type: 'custom' }\n  const templateType = TEMPLATES.find(item => item.value === argvTemplate)\n  if (templateType) {\n    return {\n      type: templateType.value,\n      url: templateType.url!,\n    }\n  }\n  else {\n    for (const item of TEMPLATES) {\n      if (item.list) {\n        const templateType = item.list.find(subItem => subItem.value === argvTemplate)\n        if (templateType) {\n          return {\n            type: templateType.value,\n            url: templateType.url!,\n          }\n        }\n      }\n    }\n  }\n\n  outro(`${bold(`暂不支持 ${gray(argvTemplate)} 模板`)}`)\n  process.exit(1)\n}\n\nfunction validateUIName(argvUIName: ArgvBase) {\n  if (!argvUIName)\n    return null\n  const UIName = UI.find(item => item.value === argvUIName)?.value\n  if (!UIName) {\n    outro(`${bold(`暂不支持 ${gray(argvUIName)} UI库`)}`)\n    process.exit(1)\n  }\n  return UIName\n}\n\nfunction validatePlugins(argvPlugins: ArgvList): [] {\n  if (!argvPlugins)\n    return []\n  const pluginList = [argvPlugins].flat()\n  const missedPluginList = pluginList.filter(item => !PLUGINS.some(plugin => plugin.value === item))\n  if (missedPluginList.length) {\n    outro(`${bold(`暂不支持 ${gray(missedPluginList.join(', '))} 插件`)}`)\n    process.exit(1)\n  }\n  return pluginList as []\n}\n\nfunction validateModules(argvModules: ArgvList): [] {\n  if (!argvModules)\n    return []\n  const moduleList = [argvModules].flat()\n  const missedModuleList = moduleList.filter(item => !MODULES.some(module => module.value === item))\n  if (missedModuleList.length) {\n    outro(`${bold(`暂不支持 ${gray(missedModuleList.join(', '))} 模块`)}`)\n    process.exit(1)\n  }\n  return moduleList as []\n}\n\nexport {\n  validateModules,\n  validatePlugins,\n  validateTemplateType,\n  validateUIName,\n}\n"
  },
  {
    "path": "packages/core/template/UI/ano/package.json",
    "content": "{\n  \"dependencies\": {\n    \"ano-ui\": \"^0.9.2\"\n  },\n  \"devDependencies\": {\n    \"@iconify-json/tabler\": \"^1.2.33\"\n  }\n}\n"
  },
  {
    "path": "packages/core/template/UI/ano/src/components/InputEntry.vue",
    "content": "<script setup>\nimport { ref } from 'vue'\n\nconst name = ref('')\nconst notify = ref()\n\nfunction handleClick() {\n  notify.value?.show({\n    duration: 3000,\n  })\n}\n</script>\n\n<template>\n  <view m4 p2 border=\"1px solid gray\">\n    <input\n      v-model=\"name\"\n      placeholder=\"What's your name?\"\n    >\n  </view>\n  <view>\n    <AButton\n      type=\"primary\" block\n      :disabled=\"!name\"\n      @click=\"handleClick\"\n    >\n      Hello\n    </AButton>\n  </view>\n\n  <ANotify ref=\"notify\">\n    <ANoticeBar type=\"primary\">\n      Hello{{ `  ${name}` }} 👏\n    </ANoticeBar>\n  </ANotify>\n</template>\n"
  },
  {
    "path": "packages/core/template/UI/ano/uno.config.js.data.mjs",
    "content": "export default function getData({ oldData }) {\n  const anoUIConfig = {\n    id: 'ano',\n    importer: `import { presetAno } from 'ano-ui'`,\n    initializer: 'presetAno()',\n  }\n\n  return {\n    ...oldData,\n    config: oldData.config.flatMap(config =>\n      config.id === 'unocss' ? [config, anoUIConfig] : config,\n    ),\n  }\n}\n"
  },
  {
    "path": "packages/core/template/UI/ano/vite.config.js.data.mjs",
    "content": "export default function getData({ oldData, utils }) {\n  const autoImportAnoUiPlugin = {\n    id: 'ano-ui',\n    importer: `import { AnoResolver } from '@uni-helper/vite-plugin-uni-components/resolvers'`,\n  }\n\n  return {\n    ...oldData,\n    plugins: oldData.plugins.flatMap(plugin =>\n      plugin.id === 'autoImport'\n        ? [utils.addResolver(plugin, 'AnoResolver()'), autoImportAnoUiPlugin]\n        : plugin,\n    ),\n  }\n}\n"
  },
  {
    "path": "packages/core/template/UI/nut/package.json",
    "content": "{\n  \"dependencies\": {\n    \"nutui-uniapp\": \"^1.11.2\"\n  }\n}\n"
  },
  {
    "path": "packages/core/template/UI/nut/src/App.vue",
    "content": "<script setup>\nimport { onLaunch } from '@dcloudio/uni-app'\n\nonLaunch(() => {})\n</script>\n\n<style lang=\"scss\">\n@import \"nutui-uniapp/styles/index.scss\";\n</style>\n"
  },
  {
    "path": "packages/core/template/UI/nut/src/components/InputEntry.vue",
    "content": "<script setup>\nimport { ref } from 'vue'\n\nconst name = ref('')\nconst popupVisible = ref(false)\n\nfunction handleClick() {\n  popupVisible.value = true\n}\n</script>\n\n<template>\n  <view class=\"input-box\">\n    <input\n      v-model=\"name\"\n      placeholder=\"What's your name?\"\n    >\n  </view>\n  <view>\n    <nut-button :disabled=\"!name\" block @click=\"handleClick\">\n      Hello\n    </nut-button>\n  </view>\n\n  <nut-popup v-model:visible=\"popupVisible\" :custom-style=\"{ padding: '30px 50px' }\">\n    Hello{{ `  ${name}` }} 👏\n  </nut-popup>\n</template>\n\n<style scoped lang=\"scss\">\n.input-box {\n  margin: 1rem;\n  padding: 0.5rem;\n  border-bottom: 1px solid gray;\n}\n</style>\n"
  },
  {
    "path": "packages/core/template/UI/nut/vite.config.js.data.mjs",
    "content": "export default function getData({ oldData, utils }) {\n  const autoImportNutUiPlugin = {\n    id: 'nutui-uniapp',\n    importer: `import { NutResolver } from 'nutui-uniapp'`,\n  }\n\n  const nutuiExtraConfig = {\n    css: {\n      preprocessorOptions: {\n        scss: {\n          additionalData: '@import \"nutui-uniapp/styles/variables.scss\";',\n        },\n      },\n    },\n  }\n\n  return {\n    ...oldData,\n    plugins: oldData.plugins.flatMap(plugin =>\n      plugin.id === 'autoImport'\n        ? [utils.addResolver(plugin, 'NutResolver()'), autoImportNutUiPlugin]\n        : plugin,\n    ),\n    extraConfig: utils.mergeExtraConfig(oldData.extraConfig, nutuiExtraConfig),\n  }\n}\n"
  },
  {
    "path": "packages/core/template/UI/tdesign/package.json",
    "content": "{\n  \"dependencies\": {\n    \"@tdesign/uniapp\": \"^0.8.1\"\n  },\n  \"devDependencies\": {\n    \"less\": \"^4.6.4\"\n  }\n}\n"
  },
  {
    "path": "packages/core/template/UI/tdesign/src/components/InputEntry.vue",
    "content": "<script setup lang=\"ts\">\nimport { ref } from 'vue'\n\nconst name = ref('')\nconst visible = ref(false)\n\nfunction handleClick() {\n  visible.value = true\n}\n</script>\n\n<template>\n  <view class=\"input-box\">\n    <input\n      v-model=\"name\"\n      placeholder=\"What's your name?\"\n    >\n  </view>\n  <view>\n    <t-button\n      block\n      size=\"large\"\n      variant=\"outline\"\n      theme=\"primary\"\n      :disabled=\"!name\"\n      @click=\"handleClick\"\n    >\n      Hello\n    </t-button>\n  </view>\n\n  <t-popup\n    :visible=\"visible\"\n    placement=\"bottom\"\n    @update:visible=\"visible = $event\"\n  >\n    <view class=\"block block--bottom\">\n      Hello{{ `  ${name}` }} 👏\n    </view>\n  </t-popup>\n</template>\n\n<style scoped lang=\"scss\">\n.input-box {\n  margin: 1rem;\n  padding: 0.5rem;\n  border-bottom: 1px solid gray;\n}\n\n.block {\n  color: var(--td-text-color-secondary);\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  width: 100vw;\n  height: 240px;\n}\n</style>\n"
  },
  {
    "path": "packages/core/template/UI/tdesign/vite.config.js.data.mjs",
    "content": "export default function getData({ oldData, utils }) {\n  const autoImportTDesignUniPlugin = {\n    id: 'tdesign-uni',\n    importer: `import { TDesignUniappResolver } from '@uni-helper/vite-plugin-uni-components/resolvers'`,\n  }\n\n  return {\n    ...oldData,\n    plugins: oldData.plugins.flatMap(plugin =>\n      plugin.id === 'autoImport'\n        ? [utils.addResolver(plugin, 'TDesignUniappResolver()'), autoImportTDesignUniPlugin]\n        : plugin,\n    ),\n  }\n}\n"
  },
  {
    "path": "packages/core/template/UI/uni/package.json",
    "content": "{\n  \"dependencies\": {\n    \"@dcloudio/uni-ui\": \"^1.5.12\"\n  }\n}\n"
  },
  {
    "path": "packages/core/template/UI/uni/src/components/InputEntry.vue",
    "content": "<script setup>\nimport { ref } from 'vue'\n\nconst name = ref('')\nconst popup = ref()\n\nfunction handleClick() {\n  popup.value.open('top')\n}\n</script>\n\n<template>\n  <view class=\"input-box\">\n    <input\n      v-model=\"name\"\n      placeholder=\"What's your name?\"\n    >\n  </view>\n  <view>\n    <button :disabled=\"!name\" @click=\"handleClick\">\n      Hello\n    </button>\n  </view>\n\n  <uni-popup ref=\"popup\" type=\"bottom\">\n    <text class=\"popup_label\">\n      Hello{{ `  ${name}` }} 👏\n    </text>\n  </uni-popup>\n</template>\n\n<style scoped lang=\"scss\">\n.input-box {\n  margin: 1rem;\n  padding: 0.5rem;\n  border-bottom: 1px solid gray;\n}\n.popup_label {\n  padding: 0.5rem 2rem;\n  background: gray;\n  border-radius: 8px;\n}\n</style>\n"
  },
  {
    "path": "packages/core/template/UI/uni/vite.config.js.data.mjs",
    "content": "export default function getData({ oldData, utils }) {\n  const excludeMap = {\n    'root': 'UniKuAppRoot',\n    'uni-echarts': 'UniEcharts',\n  }\n\n  const excludes = oldData.plugins\n    .map(plugin => excludeMap[plugin.id])\n    .filter(Boolean)\n\n  const resolverOptions = excludes.length > 0\n    ? `{ exclude: /^(?:${excludes.join('|')})$/ }`\n    : ''\n\n  const autoImportUniUiPlugin = {\n    id: 'uni-ui',\n    importer: `import { UniUIResolver } from '@uni-helper/vite-plugin-uni-components/resolvers'`,\n  }\n\n  return {\n    ...oldData,\n    plugins: oldData.plugins.flatMap(plugin =>\n      plugin.id === 'autoImport'\n        ? [utils.addResolver(plugin, `UniUIResolver(${resolverOptions})`), autoImportUniUiPlugin]\n        : plugin,\n    ),\n  }\n}\n"
  },
  {
    "path": "packages/core/template/UI/unocss/src/components/AppFooter.vue",
    "content": "<script setup>\nfunction handleClickGithub() {\n  if (window?.open) {\n    window.open('https://github.com/uni-helper/create-uni')\n  }\n  else {\n    uni.showToast({\n      icon: 'none',\n      title: '请使用浏览器打开',\n    })\n  }\n}\n</script>\n\n<template>\n  <view\n    i-carbon:logo-github\n    absolute\n    bottom-1rem left=\"50%\"\n    translate-x=\"-50%\"\n    color=\"#888\"\n    @click=\"handleClickGithub\"\n  />\n</template>\n"
  },
  {
    "path": "packages/core/template/UI/unocss/src/components/AppLogos.vue",
    "content": "<template>\n  <view inline-flex cursor-default text-2xl font-300>\n    <view\n      flex\n      flex-col\n      items-center\n      hover-class=\"drop-shadow-md drop-shadow-color-green5\"\n    >\n      <image inline-block h-18 w-18 src=\"/static/logo.svg\" />\n      <text mt--2 text-green5 class=\"uni-helper-logo__label\">\n        uni-helper\n      </text>\n    </view>\n    <view\n      text=\"3xl gray4\"\n      m=\"x-4 y-auto\"\n      i-carbon-add transform transition-all-500 hover:rotate-135\n    />\n    <view flex flex-col hover-class=\"drop-shadow-md drop-shadow-color-purple5\">\n      <image inline-block h-18 w-18 src=\"/static/vite.png\" />\n      <text mt--2 text-purple5>\n        Vite\n      </text>\n    </view>\n  </view>\n</template>\n"
  },
  {
    "path": "packages/core/template/UI/unocss/src/components/InputEntry.vue",
    "content": "<script setup>\nimport { ref } from 'vue'\n\nconst name = ref('')\nconst show = ref(false)\n\nfunction handleClick() {\n  show.value = true\n  setTimeout(() => {\n    show.value = false\n  }, 3000)\n}\n</script>\n\n<template>\n  <view m4 p2 border=\"1px solid gray\">\n    <input\n      v-model=\"name\"\n      placeholder=\"What's your name?\"\n    >\n  </view>\n  <view>\n    <button :disabled=\"!name\" @click=\"handleClick\">\n      Hello\n    </button>\n  </view>\n\n  <view v-show=\"show\" fixed top-8 left-0 right-0>\n    <text px8 py2 bg-gray rounded-1>\n      Hello{{ `  ${name}` }} 👏\n    </text>\n  </view>\n</template>\n"
  },
  {
    "path": "packages/core/template/UI/unocss/src/pages/index.vue",
    "content": "<script setup>\nimport AppFooter from '@/components/AppFooter.vue'\nimport AppLogos from '@/components/AppLogos.vue'\nimport InputEntry from '@/components/InputEntry.vue'\n</script>\n\n<template>\n  <view px-10 py-20 text-center>\n    <AppLogos />\n    <InputEntry />\n    <AppFooter />\n  </view>\n</template>\n"
  },
  {
    "path": "packages/core/template/UI/uv/package.json",
    "content": "{\n  \"dependencies\": {\n    \"@climblee/uv-ui\": \"^1.1.20\"\n  }\n}\n"
  },
  {
    "path": "packages/core/template/UI/uv/src/App.vue",
    "content": "<script setup>\nimport { onLaunch } from '@dcloudio/uni-app'\n\nonLaunch(() => {})\n</script>\n\n<style lang=\"scss\">\n@import '@climblee/uv-ui/index.scss';\n</style>\n"
  },
  {
    "path": "packages/core/template/UI/uv/src/components/InputEntry.vue",
    "content": "<script setup>\nimport { ref } from 'vue'\n\nconst name = ref('')\n\nconst popup = ref()\nfunction handleClick() {\n  popup.value.open('bottom')\n}\n</script>\n\n<template>\n  <view class=\"input-box\">\n    <uv-input\n      v-model=\"name\"\n      placeholder=\"What's your name?\"\n    />\n  </view>\n  <view>\n    <uv-button\n      type=\"primary\"\n      :disabled=\"!name\"\n      @click=\"handleClick\"\n    >\n      Hello\n    </uv-button>\n  </view>\n\n  <uv-popup ref=\"popup\" round=\"25\">\n    <div class=\"popup-box\">\n      Hello{{ `  ${name}` }} 👏\n    </div>\n  </uv-popup>\n</template>\n\n<style scoped lang=\"scss\">\n.input-box {\n  margin: 1rem;\n  padding: 0.5rem;\n  border-bottom: 1px solid gray;\n}\n.popup-box {\n  color: black;\n  height: 100px;\n}\n</style>\n"
  },
  {
    "path": "packages/core/template/UI/uv/vite.config.js.data.mjs",
    "content": "export default function getData({ oldData, utils }) {\n  const autoImportUvUiPlugin = {\n    id: 'uv-ui',\n    importer: `import { UvResolver } from '@uni-helper/vite-plugin-uni-components/resolvers'`,\n  }\n\n  return {\n    ...oldData,\n    plugins: oldData.plugins.flatMap(plugin =>\n      plugin.id === 'autoImport'\n        ? [utils.addResolver(plugin, 'UvResolver()'), autoImportUvUiPlugin]\n        : plugin,\n    ),\n  }\n}\n"
  },
  {
    "path": "packages/core/template/UI/uview-pro/jsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"types\": [\n      \"uview-pro/types\"\n    ]\n  }\n}\n"
  },
  {
    "path": "packages/core/template/UI/uview-pro/package.json",
    "content": "{\n  \"dependencies\": {\n    \"uview-pro\": \"^0.5.18\"\n  }\n}\n"
  },
  {
    "path": "packages/core/template/UI/uview-pro/src/App.vue",
    "content": "<script setup>\nimport { onLaunch } from '@dcloudio/uni-app'\n\nonLaunch(() => {})\n</script>\n\n<style lang=\"scss\">\n@import \"uview-pro/index.scss\";\n</style>\n"
  },
  {
    "path": "packages/core/template/UI/uview-pro/src/components/InputEntry.vue",
    "content": "<script setup>\nimport { ref } from 'vue'\n\nconst name = ref('')\nconst popupShow = ref(false)\n\nfunction handleClick() {\n  popupShow.value = true\n}\n</script>\n\n<template>\n  <view class=\"input-box\">\n    <input\n      v-model=\"name\"\n      placeholder=\"What's your name?\"\n    >\n  </view>\n  <view>\n    <u-button :disabled=\"!name\" type=\"primary\" @click=\"handleClick\">\n      Hello\n    </u-button>\n  </view>\n\n  <u-popup v-model=\"popupShow\" mode=\"bottom\" border-radius=\"14\" height=\"300px\">\n    <view class=\"popup-box\">\n      Hello{{ `  ${name}` }} 👏\n    </view>\n  </u-popup>\n</template>\n\n<style scoped lang=\"scss\">\n.input-box {\n  margin: 1rem;\n  padding: 0.5rem;\n  border-bottom: 1px solid gray;\n}\n.popup-box {\n  display: flex;\n  justify-content: center;\n  align-items: center;\n  height: 100%;\n  font-size: 1.5rem;\n}\n</style>\n"
  },
  {
    "path": "packages/core/template/UI/uview-pro/src/main.js.data.mjs",
    "content": "export default function getData({ oldData }) {\n  const uViewProEntries = {\n    id: 'uview-pro',\n    importer: 'import uViewPro from \\'uview-pro\\'',\n    use: 'app.use(uViewPro)',\n  }\n  return {\n    ...oldData,\n    entries: oldData.entries.flatMap(entry =>\n      entry.id === 'vue' ? [entry, uViewProEntries] : entry,\n    ),\n  }\n}\n"
  },
  {
    "path": "packages/core/template/UI/uview-pro/vite.config.js.data.mjs",
    "content": "export default function getData({ oldData, utils }) {\n  const autoImportUviewProPlugin = {\n    id: 'uview-pro',\n    importer: `import { uViewProResolver } from '@uni-helper/vite-plugin-uni-components/resolvers'`,\n  }\n\n  const uviewProExtraConfig = {\n    css: {\n      preprocessorOptions: {\n        scss: {\n          additionalData: '@import \"uview-pro/theme.scss\";',\n        },\n      },\n    },\n  }\n\n  return {\n    ...oldData,\n    plugins: oldData.plugins.flatMap(plugin =>\n      plugin.id === 'autoImport'\n        ? [utils.addResolver(plugin, 'uViewProResolver()'), autoImportUviewProPlugin]\n        : plugin,\n    ),\n    extraConfig: utils.mergeExtraConfig(oldData.extraConfig, uviewProExtraConfig),\n  }\n}\n"
  },
  {
    "path": "packages/core/template/UI/wot/.vscode/extensions.json",
    "content": "{\n  \"recommendations\": [\n    \"wot-ui.wot-ui-intellisense\"\n  ]\n}\n"
  },
  {
    "path": "packages/core/template/UI/wot/jsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"types\": [\n      \"wot-design-uni/global.d.ts\"\n    ]\n  }\n}\n"
  },
  {
    "path": "packages/core/template/UI/wot/package.json",
    "content": "{\n  \"dependencies\": {\n    \"wot-design-uni\": \"^1.14.0\"\n  }\n}\n"
  },
  {
    "path": "packages/core/template/UI/wot/src/components/InputEntry.vue",
    "content": "<script setup>\nimport { ref } from 'vue'\n\nconst name = ref('')\nconst popupShow = ref(false)\n\nfunction handleClick() {\n  popupShow.value = true\n}\n</script>\n\n<template>\n  <view class=\"input-box\">\n    <input\n      v-model=\"name\"\n      placeholder=\"What's your name?\"\n    >\n  </view>\n  <view>\n    <wd-button :disabled=\"!name\" @click=\"handleClick\">\n      Hello\n    </wd-button>\n  </view>\n\n  <wd-popup v-model=\"popupShow\" custom-style=\"padding: 30px 40px;\">\n    Hello{{ `  ${name}` }} 👏\n  </wd-popup>\n</template>\n\n<style scoped lang=\"scss\">\n.input-box {\n  margin: 1rem;\n  padding: 0.5rem;\n  border-bottom: 1px solid gray;\n}\n</style>\n"
  },
  {
    "path": "packages/core/template/UI/wot/vite.config.js.data.mjs",
    "content": "export default function getData({ oldData, utils }) {\n  const autoImportWotDesignUiPlugin = {\n    id: 'wot-design-ui',\n    importer: `import { WotResolver } from '@uni-helper/vite-plugin-uni-components/resolvers'`,\n  }\n\n  return {\n    ...oldData,\n    plugins: oldData.plugins.flatMap(plugin =>\n      plugin.id === 'autoImport'\n        ? [utils.addResolver(plugin, 'WotResolver()'), autoImportWotDesignUiPlugin]\n        : plugin,\n    ),\n  }\n}\n"
  },
  {
    "path": "packages/core/template/UI/wot2/.vscode/extensions.json",
    "content": "{\n  \"recommendations\": [\n    \"wot-ui.wot-ui-intellisense\"\n  ]\n}\n"
  },
  {
    "path": "packages/core/template/UI/wot2/jsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"types\": [\n      \"@wot-ui/ui/global.d.ts\"\n    ]\n  }\n}\n"
  },
  {
    "path": "packages/core/template/UI/wot2/package.json",
    "content": "{\n  \"dependencies\": {\n    \"@wot-ui/ui\": \"^2.0.4\"\n  },\n  \"devDependencies\": {\n    \"sass\": \"^1.99.0\"\n  }\n}\n"
  },
  {
    "path": "packages/core/template/UI/wot2/src/components/InputEntry.vue",
    "content": "<script setup>\nimport { ref } from 'vue'\n\nconst name = ref('')\nconst popupShow = ref(false)\n\nfunction handleClick() {\n  popupShow.value = true\n}\n</script>\n\n<template>\n  <view class=\"input-box\">\n    <input\n      v-model=\"name\"\n      placeholder=\"What's your name?\"\n    >\n  </view>\n  <view>\n    <wd-button :disabled=\"!name\" @click=\"handleClick\">\n      Hello\n    </wd-button>\n  </view>\n\n  <wd-popup v-model=\"popupShow\" custom-style=\"padding: 30px 40px;\">\n    Hello{{ `  ${name}` }} 👏\n  </wd-popup>\n</template>\n\n<style scoped lang=\"scss\">\n.input-box {\n  margin: 1rem;\n  padding: 0.5rem;\n  border-bottom: 1px solid gray;\n}\n</style>\n"
  },
  {
    "path": "packages/core/template/UI/wot2/vite.config.js.data.mjs",
    "content": "export default function getData({ oldData, utils }) {\n  const autoImportWotUiPlugin = {\n    id: 'wot-ui',\n    importer: `import { WotV2Resolver } from '@uni-helper/vite-plugin-uni-components/resolvers'`,\n  }\n\n  return {\n    ...oldData,\n    plugins: oldData.plugins.flatMap(plugin =>\n      plugin.id === 'autoImport'\n        ? [utils.addResolver(plugin, 'WotV2Resolver()'), autoImportWotUiPlugin]\n        : plugin,\n    ),\n  }\n}\n"
  },
  {
    "path": "packages/core/template/base/.vscode/extensions.json",
    "content": "{\n  \"recommendations\": [\n    \"vue.volar\",\n    \"mrmaoddxxaa.create-uniapp-view\",\n    \"uni-helper.uni-helper-vscode\",\n    \"uni-helper.uni-app-schemas-vscode\",\n    \"uni-helper.uni-highlight-vscode\",\n    \"uni-helper.uni-ui-snippets-vscode\",\n    \"uni-helper.uni-app-snippets-vscode\",\n    \"uni-helper.uni-cloud-snippets-vscode\"\n  ]\n}\n"
  },
  {
    "path": "packages/core/template/base/.vscode/settings.json",
    "content": "{\n  \"files.associations\": {\n    \"pages.json\": \"jsonc\",\n    \"manifest.json\": \"jsonc\"\n  }\n}\n"
  },
  {
    "path": "packages/core/template/base/_gitignore",
    "content": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\npnpm-debug.log*\nlerna-debug.log*\n\nnode_modules\n.DS_Store\ndist\n*.local\n\n# Editor directories and files\n.idea\n*.suo\n*.ntvs*\n*.njsproj\n*.sln\n*.sw?\n"
  },
  {
    "path": "packages/core/template/base/_npmrc",
    "content": "strict-peer-dependencies=false\nauto-install-peers=true\nshamefully-hoist=true\n"
  },
  {
    "path": "packages/core/template/base/index.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"UTF-8\" />\n    <link rel=\"icon\" href=\"static/logo.svg\">\n    <script>\n      const coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)')\n  || CSS.supports('top: constant(a)'))\n      document.write(\n        `<meta name=\"viewport\" content=\"width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0${\n  coverSupport ? ', viewport-fit=cover' : ''}\" />`)\n    </script>\n    <title></title>\n    <!--preload-links-->\n    <!--app-context-->\n  </head>\n  <body>\n    <div id=\"app\"><!--app-html--></div>\n    <script type=\"module\" src=\"/src/main.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "packages/core/template/base/jsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"baseUrl\": \".\",\n    \"paths\": {\n      \"@/*\": [\"./src/*\"]\n    },\n    \"types\": [\n      \"vite/client\",\n      \"@dcloudio/types\",\n      \"@mini-types/alipay\",\n      \"miniprogram-api-typings\",\n      \"@uni-helper/uni-types\"\n    ]\n  },\n  \"vueCompilerOptions\": {\n    \"plugins\": [\"@uni-helper/uni-types/volar-plugin\"]\n  }\n}\n"
  },
  {
    "path": "packages/core/template/base/package.json",
    "content": "{\n  \"name\": \"uni-app\",\n  \"type\": \"module\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"scripts\": {\n    \"dev\": \"unh dev\",\n    \"build\": \"unh build\",\n    \"about\": \"unh info\"\n  },\n  \"dependencies\": {\n    \"@dcloudio/uni-app\": \"3.0.0-5000720260410001\",\n    \"@dcloudio/uni-app-harmony\": \"3.0.0-5000720260410001\",\n    \"@dcloudio/uni-app-plus\": \"3.0.0-5000720260410001\",\n    \"@dcloudio/uni-components\": \"3.0.0-5000720260410001\",\n    \"@dcloudio/uni-h5\": \"3.0.0-5000720260410001\",\n    \"@dcloudio/uni-mp-alipay\": \"3.0.0-5000720260410001\",\n    \"@dcloudio/uni-mp-baidu\": \"3.0.0-5000720260410001\",\n    \"@dcloudio/uni-mp-harmony\": \"3.0.0-5000720260410001\",\n    \"@dcloudio/uni-mp-jd\": \"3.0.0-5000720260410001\",\n    \"@dcloudio/uni-mp-kuaishou\": \"3.0.0-5000720260410001\",\n    \"@dcloudio/uni-mp-lark\": \"3.0.0-5000720260410001\",\n    \"@dcloudio/uni-mp-qq\": \"3.0.0-5000720260410001\",\n    \"@dcloudio/uni-mp-toutiao\": \"3.0.0-5000720260410001\",\n    \"@dcloudio/uni-mp-weixin\": \"3.0.0-5000720260410001\",\n    \"@dcloudio/uni-mp-xhs\": \"3.0.0-5000720260410001\",\n    \"@dcloudio/uni-quickapp-webview\": \"3.0.0-5000720260410001\",\n    \"vue\": \"3.4.21\",\n    \"vue-i18n\": \"9.6.2\",\n    \"vue-router\": \"4.5.1\"\n  },\n  \"devDependencies\": {\n    \"@dcloudio/types\": \"3.4.28\",\n    \"@dcloudio/uni-automator\": \"3.0.0-5000720260410001\",\n    \"@dcloudio/uni-cli-shared\": \"3.0.0-5000720260410001\",\n    \"@dcloudio/uni-stacktracey\": \"3.0.0-5000720260410001\",\n    \"@dcloudio/vite-plugin-uni\": \"3.0.0-5000720260410001\",\n    \"@mini-types/alipay\": \"^3.0.14\",\n    \"@uni-helper/plugin-uni\": \"0.1.0\",\n    \"@uni-helper/unh\": \"^0.3.1\",\n    \"@uni-helper/uni-types\": \"^1.0.0-alpha.8\",\n    \"@vue/runtime-core\": \"3.4.21\",\n    \"miniprogram-api-typings\": \"^5.1.3\",\n    \"sass\": \"1.64.2\",\n    \"vite\": \"5.2.8\"\n  }\n}\n"
  },
  {
    "path": "packages/core/template/base/src/App.vue",
    "content": "<script setup>\nimport { onLaunch } from '@dcloudio/uni-app'\n\nonLaunch(() => {})\n</script>\n\n<style></style>\n"
  },
  {
    "path": "packages/core/template/base/src/components/AppFooter.vue",
    "content": "<script setup>\nfunction handleClickGithub() {\n  if (window?.open) {\n    window.open('https://github.com/uni-helper/create-uni')\n  }\n  else {\n    uni.showToast({\n      icon: 'none',\n      title: '请使用浏览器打开',\n    })\n  }\n}\n</script>\n\n<template>\n  <view class=\"footer\" @click=\"handleClickGithub\">\n    <image class=\"uni-helper-github__image\" src=\"/static/github.svg\" />\n  </view>\n</template>\n\n<style>\n.footer{\n  position: absolute;\n  bottom: 1rem;\n  left: 50%;\n  transform: translateX(-50%);\n  color: #888;\n}\n.uni-helper-github__image {\n  display: inline-block;\n  height: 1em;\n  width: 1em;\n}\n</style>\n"
  },
  {
    "path": "packages/core/template/base/src/components/AppLogos.vue",
    "content": "<script setup>\n</script>\n\n<template>\n  <view class=\"container\">\n    <view class=\"uni-helper-logo\">\n      <image class=\"uni-helper-logo__image\" src=\"/static/logo.svg\" />\n      <text class=\"uni-helper-logo__label green\">\n        uni-helper\n      </text>\n    </view>\n    <text class=\"link-bar\">\n      +\n    </text>\n    <view class=\"uni-helper-logo\">\n      <image class=\"uni-helper-logo__image\" src=\"/static/vite.png\" />\n      <text class=\"uni-helper-logo__label purple\">\n        Vite\n      </text>\n    </view>\n  </view>\n</template>\n\n<style scoped lang=\"scss\">\n.container {\n  display: inline-flex;\n  font-size: 1.5rem;\n  font-weight: 300;\n  &:hover {\n    .link-bar {\n      transform: rotate(135deg);\n    }\n  }\n}\n.uni-helper-logo {\n  display: flex;\n  flex-direction: column;\n  align-items: center;\n  .uni-helper-logo__image {\n    display: inline-block;\n    height: 4.5rem;\n    width: 4.5rem;\n  }\n  .uni-helper-logo__label {\n    margin-top: -0.5rem;\n  }\n  .green {\n    color: #22c55e;\n  };\n  .purple {\n    color: #a855f7;\n  }\n}\n.link-bar {\n  color: #9ca3af;\n  margin: auto 1em;\n  transition: all 500ms cubic-bezier(0.4, 0, 0.2, 1);\n}\n</style>\n"
  },
  {
    "path": "packages/core/template/base/src/components/InputEntry.vue",
    "content": "<script setup>\nimport { ref } from 'vue'\n\nconst name = ref('')\nconst show = ref(false)\n\nfunction handleClick() {\n  show.value = true\n  setTimeout(() => {\n    show.value = false\n  }, 3000)\n}\n</script>\n\n<template>\n  <view class=\"input-box\">\n    <input\n      v-model=\"name\"\n      placeholder=\"What's your name?\"\n    >\n  </view>\n  <view>\n    <button :disabled=\"!name\" @click=\"handleClick\">\n      Hello\n    </button>\n  </view>\n\n  <view v-show=\"show\" class=\"popup\">\n    <text class=\"popup_label\">\n      Hello{{ `  ${name}` }} 👏\n    </text>\n  </view>\n</template>\n\n<style scoped lang=\"scss\">\n.input-box {\n  margin: 1rem;\n  padding: 0.5rem;\n  border-bottom: 1px solid gray;\n}\n.popup {\n  position: fixed;\n  top: 2rem;\n  left: 0px;\n  right: 0px;\n  .popup_label {\n    padding: 0.5rem 2rem;\n    background: gray;\n    border-radius: 8px;\n  }\n}\n</style>\n"
  },
  {
    "path": "packages/core/template/base/src/main.js.data.mjs",
    "content": "export default function getData() {\n  return {\n    entries: [{\n      id: 'vue',\n      importer: `import { createSSRApp } from 'vue'`,\n      use: 'const app = createSSRApp(App)',\n      returner: 'app,',\n    }],\n  }\n}\n"
  },
  {
    "path": "packages/core/template/base/src/main.js.ejs",
    "content": "<%_ for (const { importer } of entries) { _%>\n<%- importer %>\n<%_ } _%>\nimport App from './App.vue'\n\nexport function createApp() {\n  <%_ for (const { use } of entries) { _%>\n  <%_ if (use) { _%>\n  <%- use %>\n  <%_ } _%>\n  <%_ } _%>\n  return {\n    <%_ for (const { returner } of entries) { _%>\n    <%_ if (returner) { _%>\n    <%- returner %>\n    <%_ } _%>\n    <%_ } _%>\n  }\n}\n"
  },
  {
    "path": "packages/core/template/base/src/manifest.json",
    "content": "{\n  \"name\": \"\",\n  \"appid\": \"\",\n  \"description\": \"\",\n  \"versionName\": \"1.0.0\",\n  \"versionCode\": \"100\",\n  \"transformPx\": false,\n  \"uniStatistics\": {\n    \"enable\": false\n  },\n  \"app-plus\": {\n    \"usingComponents\": true,\n    \"nvueStyleCompiler\": \"uni-app\",\n    \"compilerVersion\": 3,\n    \"splashscreen\": {\n      \"alwaysShowBeforeRender\": true,\n      \"waiting\": true,\n      \"autoclose\": true,\n      \"delay\": 0\n    },\n    \"modules\": {},\n    \"distribute\": {\n      \"android\": {\n        \"permissions\": [\n          \"<uses-permission android:name=\\\"android.permission.CHANGE_NETWORK_STATE\\\"/>\",\n          \"<uses-permission android:name=\\\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\\\"/>\",\n          \"<uses-permission android:name=\\\"android.permission.VIBRATE\\\"/>\",\n          \"<uses-permission android:name=\\\"android.permission.READ_LOGS\\\"/>\",\n          \"<uses-permission android:name=\\\"android.permission.ACCESS_WIFI_STATE\\\"/>\",\n          \"<uses-feature android:name=\\\"android.hardware.camera.autofocus\\\"/>\",\n          \"<uses-permission android:name=\\\"android.permission.ACCESS_NETWORK_STATE\\\"/>\",\n          \"<uses-permission android:name=\\\"android.permission.CAMERA\\\"/>\",\n          \"<uses-permission android:name=\\\"android.permission.GET_ACCOUNTS\\\"/>\",\n          \"<uses-permission android:name=\\\"android.permission.READ_PHONE_STATE\\\"/>\",\n          \"<uses-permission android:name=\\\"android.permission.CHANGE_WIFI_STATE\\\"/>\",\n          \"<uses-permission android:name=\\\"android.permission.WAKE_LOCK\\\"/>\",\n          \"<uses-permission android:name=\\\"android.permission.FLASHLIGHT\\\"/>\",\n          \"<uses-feature android:name=\\\"android.hardware.camera\\\"/>\",\n          \"<uses-permission android:name=\\\"android.permission.WRITE_SETTINGS\\\"/>\"\n        ]\n      },\n      \"ios\": {},\n      \"sdkConfigs\": {}\n    }\n  },\n  \"h5\": {\n    \"darkmode\": true,\n    \"themeLocation\": \"theme.json\"\n  },\n  \"quickapp\": {},\n  \"mp-weixin\": {\n    \"appid\": \"\",\n    \"setting\": {\n      \"urlCheck\": false\n    },\n    \"usingComponents\": true,\n    \"darkmode\": true,\n    \"themeLocation\": \"theme.json\"\n  },\n  \"mp-alipay\": {\n    \"usingComponents\": true\n  },\n  \"mp-baidu\": {\n    \"usingComponents\": true\n  },\n  \"mp-toutiao\": {\n    \"usingComponents\": true\n  },\n  \"vueVersion\": \"3\"\n}\n"
  },
  {
    "path": "packages/core/template/base/src/pages/index.vue",
    "content": "<script setup>\nimport AppFooter from '@/components/AppFooter.vue'\nimport AppLogos from '@/components/AppLogos.vue'\nimport InputEntry from '@/components/InputEntry.vue'\n</script>\n\n<template>\n  <view class=\"root-container\">\n    <AppLogos />\n    <InputEntry />\n    <AppFooter />\n  </view>\n</template>\n\n<style scoped>\n.root-container {\n  padding: 5rem 2.5rem;\n  text-align: center;\n}\n</style>\n"
  },
  {
    "path": "packages/core/template/base/src/pages.json",
    "content": "{\n  \"pages\": [\n    {\n      \"path\": \"pages/index\",\n      \"type\": \"home\"\n    }\n  ],\n  \"globalStyle\": {\n    \"backgroundColor\": \"@bgColor\",\n    \"backgroundColorBottom\": \"@bgColorBottom\",\n    \"backgroundColorTop\": \"@bgColorTop\",\n    \"backgroundTextStyle\": \"@bgTxtStyle\",\n    \"navigationBarBackgroundColor\": \"#000000\",\n    \"navigationBarTextStyle\": \"@navTxtStyle\",\n    \"navigationBarTitleText\": \"Uni Creator\",\n    \"navigationStyle\": \"custom\"\n  },\n  \"subPackages\": []\n}\n"
  },
  {
    "path": "packages/core/template/base/src/theme.json",
    "content": "{\n  \"light\": {\n    \"bgColor\": \"#fcfcfc\",\n    \"bgColorBottom\": \"#fcfcfc\",\n    \"bgColorTop\": \"#ff6b00\",\n    \"bgTxtStyle\": \"dark\",\n    \"navBgColor\": \"#ff6b00\",\n    \"navTxtStyle\": \"white\",\n    \"tabBgColor\": \"#fcfcfc\",\n    \"tabBorderStyle\": \"black\",\n    \"tabFontColor\": \"#1f2937\",\n    \"tabSelectedColor\": \"#ff6b00\"\n  },\n  \"dark\": {\n    \"bgColor\": \"#181818\",\n    \"bgColorBottom\": \"#181818\",\n    \"bgColorTop\": \"#ff6b00\",\n    \"bgTxtStyle\": \"light\",\n    \"navBgColor\": \"#ff6b00\",\n    \"navTxtStyle\": \"white\",\n    \"tabBgColor\": \"#181818\",\n    \"tabBorderStyle\": \"white\",\n    \"tabFontColor\": \"#f3f4f6\",\n    \"tabSelectedColor\": \"#ff6b00\"\n  }\n}\n"
  },
  {
    "path": "packages/core/template/base/src/uni.scss",
    "content": "/**\n * 这里是uni-app内置的常用样式变量\n *\n * uni-app 官方扩展插件及插件市场（https://ext.dcloud.net.cn）上很多三方插件均使用了这些样式变量\n * 如果你是插件开发者，建议你使用scss预处理，并在插件代码中直接使用这些变量（无需 import 这个文件），方便用户通过搭积木的方式开发整体风格一致的App\n *\n */\n\n/**\n * 如果你是App开发者（插件使用者），你可以通过修改这些变量来定制自己的插件主题，实现自定义主题功能\n *\n * 如果你的项目同样使用了scss预处理，你也可以直接在你的 scss 代码中使用如下变量，同时无需 import 这个文件\n */\n\n/* 颜色变量 */\n\n/* 行为相关颜色 */\n$uni-color-primary: #007aff;\n$uni-color-success: #4cd964;\n$uni-color-warning: #f0ad4e;\n$uni-color-error: #dd524d;\n\n/* 文字基本颜色 */\n$uni-text-color: #333; // 基本色\n$uni-text-color-inverse: #fff; // 反色\n$uni-text-color-grey: #999; // 辅助灰色，如加载更多的提示信息\n$uni-text-color-placeholder: #808080;\n$uni-text-color-disable: #c0c0c0;\n\n/* 背景颜色 */\n$uni-bg-color: #fff;\n$uni-bg-color-grey: #f8f8f8;\n$uni-bg-color-hover: #f1f1f1; // 点击状态颜色\n$uni-bg-color-mask: rgba(0, 0, 0, 0.4); // 遮罩颜色\n\n/* 边框颜色 */\n$uni-border-color: #c8c7cc;\n\n/* 尺寸变量 */\n\n/* 文字尺寸 */\n$uni-font-size-sm: 12px;\n$uni-font-size-base: 14px;\n$uni-font-size-lg: 16px;\n\n/* 图片尺寸 */\n$uni-img-size-sm: 20px;\n$uni-img-size-base: 26px;\n$uni-img-size-lg: 40px;\n\n/* Border Radius */\n$uni-border-radius-sm: 2px;\n$uni-border-radius-base: 3px;\n$uni-border-radius-lg: 6px;\n$uni-border-radius-circle: 50%;\n\n/* 水平间距 */\n$uni-spacing-row-sm: 5px;\n$uni-spacing-row-base: 10px;\n$uni-spacing-row-lg: 15px;\n\n/* 垂直间距 */\n$uni-spacing-col-sm: 4px;\n$uni-spacing-col-base: 8px;\n$uni-spacing-col-lg: 12px;\n\n/* 透明度 */\n$uni-opacity-disabled: 0.3; // 组件禁用态的透明度\n\n/* 文章场景相关 */\n$uni-color-title: #2c405a; // 文章标题颜色\n$uni-font-size-title: 20px;\n$uni-color-subtitle: #555; // 二级标题颜色\n$uni-font-size-subtitle: 18px;\n$uni-color-paragraph: #3f536e; // 文章段落颜色\n$uni-font-size-paragraph: 15px;\n"
  },
  {
    "path": "packages/core/template/base/unh.config.js.data.mjs",
    "content": "export default function getData() {\n  return {\n    autoGenerate: {\n      pages: false,\n      manifest: false,\n    },\n  }\n}\n"
  },
  {
    "path": "packages/core/template/base/unh.config.js.ejs",
    "content": "import { defineConfig } from '@uni-helper/unh'\n\n/**\n * unh 配置文件\n * 更多配置请参考：https://uni-helper.js.org/unh/\n */\nexport default defineConfig({\n  platform: {\n    // 默认平台\n    default: 'h5',\n    // 平台别名\n    alias: {\n      'h5': ['w', 'h'],\n      'mp-weixin': 'wx',\n    },\n  },\n<%_ if (autoGenerate.pages || autoGenerate.manifest) { _%>\n  autoGenerate: {\n<%_ if (autoGenerate.pages) { _%>\n    pages: <%= autoGenerate.pages %>,\n<%_ } _%>\n<%_ if (autoGenerate.manifest) { _%>\n    manifest: <%= autoGenerate.manifest %>,\n<%_ } _%>\n  },\n<%_ } _%>\n})\n"
  },
  {
    "path": "packages/core/template/base/vite.config.js.data.mjs",
    "content": "export default function getData() {\n  return {\n    plugins: [{\n      id: 'uni',\n      importer: `import Uni from '@uni-helper/plugin-uni'`,\n      initializer: `// https://uni-helper.js.org/plugin-uni\n    Uni()`,\n    }],\n    extraConfig: null,\n    dynamic: false,\n  }\n}\n"
  },
  {
    "path": "packages/core/template/base/vite.config.js.ejs",
    "content": "import { fileURLToPath, URL } from 'node:url'\n\nimport { defineConfig } from 'vite'\n<%_ for (const { importer } of plugins) { _%>\n<%_ if (importer) { _%>\n<%- importer %>\n<%_ } _%>\n<%_ } _%>\n\n<%_ if (dynamic) { _%>\nexport default defineConfig(async () => {\n  <%_ for (const { dynamicImporter } of plugins) { _%>\n  <%_ if (dynamicImporter) { _%>\n  <%- dynamicImporter %>\n  <%_ } _%>\n  <%_ } _%>\n\n  return {\n    resolve: {\n      alias: {\n        '@': fileURLToPath(new URL('./src', import.meta.url))\n      }\n    },\n    plugins: [\n    <%_ for (const { initializer } of plugins) { _%>\n    <%_ if (initializer) { _%>\n      <%- initializer _%>,\n    <%_ } _%>\n    <%_ } _%>\n    ],\n    <%_ if (extraConfig) { _%>\n    <%- extraConfig _%>\n    <%_ } _%>\n  }\n})\n\n<%_ } else { _%>\nexport default defineConfig({\n  resolve: {\n    alias: {\n      '@': fileURLToPath(new URL('./src', import.meta.url))\n    }\n  },\n  plugins: [\n  <%_ for (const { initializer } of plugins) { _%>\n  <%_ if (initializer) { _%>\n    <%- initializer _%>,\n  <%_ } _%>\n  <%_ } _%>\n  ],\n  <%_ if (extraConfig) { _%>\n  <%- extraConfig _%>\n  <%_ } _%>\n  \n})\n<%_ } _%>\n\n\n"
  },
  {
    "path": "packages/core/template/config/lint/.vscode/extensions.json",
    "content": "{\n  \"recommendations\": [\n    \"dbaeumer.vscode-eslint\"\n  ]\n}\n"
  },
  {
    "path": "packages/core/template/config/lint/.vscode/settings.json",
    "content": "{\n  \"editor.codeActionsOnSave\": {\n    \"source.fixAll.eslint\": \"explicit\",\n    \"source.organizeImports\": \"never\"\n  },\n  \"prettier.enable\": false,\n  \"editor.formatOnSave\": false,\n  \"eslint.validate\": [\n    \"javascript\",\n    \"javascriptreact\",\n    \"typescript\",\n    \"typescriptreact\",\n    \"vue\",\n    \"nvue\",\n    \"uvue\",\n    \"html\",\n    \"markdown\",\n    \"json\",\n    \"jsonc\",\n    \"yaml\",\n    \"toml\",\n    \"xml\",\n    \"gql\",\n    \"graphql\",\n    \"astro\",\n    \"svelte\",\n    \"css\",\n    \"less\",\n    \"scss\",\n    \"pcss\",\n    \"postcss\"\n  ]\n}\n"
  },
  {
    "path": "packages/core/template/config/lint/eslint.config.js",
    "content": "import uniHelper from '@uni-helper/eslint-config'\n\nexport default uniHelper()\n"
  },
  {
    "path": "packages/core/template/config/lint/package.json",
    "content": "{\n  \"scripts\": {\n    \"lint\": \"eslint .\",\n    \"lint:fix\": \"eslint . --fix\"\n  },\n  \"devDependencies\": {\n    \"@uni-helper/eslint-config\": \"^0.7.1\",\n    \"eslint\": \"^10.2.1\"\n  }\n}\n"
  },
  {
    "path": "packages/core/template/config/typescript/.vscode/extensions.json",
    "content": "{\n  \"recommendations\": [\n    \"yoavbls.pretty-ts-errors\",\n    \"johnsoncodehk.vscode-tsconfig-helper\"\n  ]\n}\n"
  },
  {
    "path": "packages/core/template/config/typescript/jsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"lib\": [\"DOM\", \"DOM.Iterable\", \"ESNext\"],\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"resolveJsonModule\": true,\n    \"jsx\": \"preserve\",\n    \"jsxImportSource\": \"vue\",\n    \"noImplicitThis\": true,\n    \"strict\": true,\n    \"verbatimModuleSyntax\": true,\n    \"target\": \"ESNext\",\n    \"useDefineForClassFields\": true,\n    \"esModuleInterop\": true,\n    \"forceConsistentCasingInFileNames\": true,\n    \"skipLibCheck\": true\n  },\n  \"includes\": [\"src/**/*.ts\", \"src/**/*.tsx\"]\n}\n"
  },
  {
    "path": "packages/core/template/config/typescript/package.json",
    "content": "{\n  \"scripts\": {\n    \"type-check\": \"vue-tsc --noEmit\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^25.6.0\",\n    \"@vue/tsconfig\": \"^0.9.1\",\n    \"typescript\": \"5.9.3\",\n    \"vue-tsc\": \"^3.2.7\"\n  }\n}\n"
  },
  {
    "path": "packages/core/template/module/pinia/package.json",
    "content": "{\n  \"dependencies\": {\n    \"pinia\": \"2.2.4\"\n  }\n}\n"
  },
  {
    "path": "packages/core/template/module/pinia/src/main.js.data.mjs",
    "content": "export default function getData({ oldData }) {\n  const piniaEntries = {\n    id: 'pinia',\n    importer: 'import * as Pinia from \\'pinia\\'',\n    use: 'app.use(Pinia.createPinia())',\n    returner: 'Pinia,',\n  }\n  return {\n    ...oldData,\n    entries: oldData.entries.flatMap(entry =>\n      entry.id === 'vue' ? [entry, piniaEntries] : entry,\n    ),\n  }\n}\n"
  },
  {
    "path": "packages/core/template/module/pinia/src/stores/counter.js",
    "content": "import { defineStore } from 'pinia'\nimport { ref } from 'vue'\n\nexport const useCounterStore = defineStore('counter', () => {\n  const count = ref(0)\n  function increment() {\n    count.value++\n  }\n  return { count, increment }\n})\n"
  },
  {
    "path": "packages/core/template/module/uniEcharts/jsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"types\": [\n      \"uni-echarts/global\"\n    ]\n  }\n}\n"
  },
  {
    "path": "packages/core/template/module/uniEcharts/package.json",
    "content": "{\n  \"dependencies\": {\n    \"echarts\": \"^6.0.0\",\n    \"uni-echarts\": \"^2.5.1\"\n  }\n}\n"
  },
  {
    "path": "packages/core/template/module/uniEcharts/vite.config.js.data.mjs",
    "content": "export default function getData({ oldData, utils }) {\n  const uniEchartsPlugin = {\n    id: 'uni-echarts',\n    importer: `import { UniEcharts } from 'uni-echarts/vite'`,\n    initializer: `// https://uni-echarts.xiaohe.ink\n    UniEcharts()`,\n  }\n\n  const autoImportUniEchartsPlugin = {\n    id: 'uni-echarts-auto-import',\n    importer: `import { UniEchartsResolver } from 'uni-echarts/resolver'`,\n  }\n\n  const uniEchartsExtraConfig = {\n    optimizeDeps: {\n      exclude: ['uni-echarts'],\n    },\n  }\n\n  return {\n    ...oldData,\n    plugins: oldData.plugins.flatMap((plugin) => {\n      if (plugin.id === 'uni') {\n        return [uniEchartsPlugin, plugin]\n      }\n\n      if (plugin.id === 'autoImport') {\n        return [utils.addResolver(plugin, 'UniEchartsResolver()'), autoImportUniEchartsPlugin]\n      }\n\n      return plugin\n    }),\n    extraConfig: utils.mergeExtraConfig(oldData.extraConfig, uniEchartsExtraConfig),\n  }\n}\n"
  },
  {
    "path": "packages/core/template/module/uniNetwork/package.json",
    "content": "{\n  \"dependencies\": {\n    \"@uni-helper/uni-network\": \"^0.23.1\"\n  }\n}\n"
  },
  {
    "path": "packages/core/template/module/uniPromises/package.json",
    "content": "{\n  \"dependencies\": {\n    \"@uni-helper/uni-promises\": \"^0.2.1\"\n  }\n}\n"
  },
  {
    "path": "packages/core/template/module/uniPromises/src/main.js.data.mjs",
    "content": "export default function getData({ oldData }) {\n  const uniPromisesEntry = {\n    id: 'uniPromises',\n  }\n  return {\n    ...oldData,\n    entries: oldData.entries.some(item => item.id === 'uniUse')\n      ? oldData.entries\n      : oldData.entries.flatMap(entry =>\n          entry.id === 'vue' ? [entry, uniPromisesEntry] : entry,\n        ),\n  }\n}\n"
  },
  {
    "path": "packages/core/template/module/uniPromises/vite.config.js.data.mjs",
    "content": "export default function getData({ oldData, utils }) {\n  const promisesExtraConfig = {\n    build: {\n      target: 'es6',\n      cssTarget: 'chrome61',\n    },\n    optimizeDeps: {\n      exclude: ['vue-demi'],\n    },\n  }\n\n  return {\n    ...oldData,\n    extraConfig: utils.mergeExtraConfig(oldData.extraConfig, promisesExtraConfig),\n  }\n}\n"
  },
  {
    "path": "packages/core/template/module/uniUse/package.json",
    "content": "{\n  \"dependencies\": {\n    \"@uni-helper/uni-use\": \"^0.19.17\",\n    \"@vueuse/core\": \"9.13.0\"\n  }\n}\n"
  },
  {
    "path": "packages/core/template/module/uniUse/src/main.js.data.mjs",
    "content": "export default function getData({ oldData }) {\n  const uniUseEntry = {\n    id: 'uniUse',\n  }\n  return {\n    ...oldData,\n    entries: oldData.entries.some(item => item.id === 'uniPromises')\n      ? oldData.entries\n      : oldData.entries.flatMap(entry =>\n          entry.id === 'vue' ? [entry, uniUseEntry] : entry,\n        ),\n  }\n}\n"
  },
  {
    "path": "packages/core/template/module/uniUse/vite.config.js.data.mjs",
    "content": "export default function getData({ oldData, utils }) {\n  const uniUseExtraConfig = {\n    build: {\n      target: 'es6',\n      cssTarget: 'chrome61', // https://cn.vitejs.dev/config/build-options.html#build-csstarget\n    },\n    optimizeDeps: {\n      exclude: ['vue-demi'],\n    },\n  }\n\n  return {\n    ...oldData,\n    extraConfig: utils.mergeExtraConfig(oldData.extraConfig, uniUseExtraConfig),\n  }\n}\n"
  },
  {
    "path": "packages/core/template/module/unocss/.vscode/extensions.json",
    "content": "{\n  \"recommendations\": [\n    \"antfu.unocss\"\n  ]\n}\n"
  },
  {
    "path": "packages/core/template/module/unocss/package.json",
    "content": "{\n  \"devDependencies\": {\n    \"@iconify-json/carbon\": \"^1.2.20\",\n    \"@uni-helper/unocss-preset-uni\": \"^0.2.11\",\n    \"unocss\": \"66.0.0\"\n  },\n  \"pnpm\": {\n    \"overrides\": {\n      \"unconfig\": \"7.3.2\"\n    }\n  },\n  \"overrides\": {\n    \"unconfig\": \"7.3.2\"\n  },\n  \"resolutions\": {\n    \"unconfig\": \"7.3.2\"\n  }\n}\n"
  },
  {
    "path": "packages/core/template/module/unocss/src/main.js.data.mjs",
    "content": "export default function getData({ oldData }) {\n  const unocssEntry = {\n    id: 'unocss',\n    importer: 'import \\'uno.css\\'',\n  }\n  return {\n    ...oldData,\n    entries: oldData.entries.flatMap(entry =>\n      entry.id === 'vue' ? [entry, unocssEntry] : entry,\n    ),\n  }\n}\n"
  },
  {
    "path": "packages/core/template/module/unocss/uno.config.js.data.mjs",
    "content": "export default function getData() {\n  return {\n    config: [{\n      id: 'unocss',\n      importer: `import { presetUni } from '@uni-helper/unocss-preset-uni'`,\n      initializer: 'presetUni()',\n    }],\n  }\n}\n"
  },
  {
    "path": "packages/core/template/module/unocss/uno.config.js.ejs",
    "content": "import {\n  defineConfig,\n  presetIcons,\n  transformerDirectives,\n  transformerVariantGroup,\n} from 'unocss'\n\n<%_ for (const { importer } of config) { _%>\n<%_ if (importer) { _%>\n<%- importer %>\n<%_ } _%>\n<%_ } _%>\n\nexport default defineConfig({\n  presets: [\n    <%_ for (const { initializer } of config) { _%>\n    <%_ if (initializer) { _%>\n    <%- initializer _%>,\n    <%_ } _%>\n    <%_ } _%>\n    presetIcons({\n      scale: 1.2,\n      warn: true,\n      extraProperties: {\n        'display': 'inline-block',\n        'vertical-align': 'middle',\n      },\n    }),\n  ],\n  transformers: [\n    transformerDirectives(),\n    transformerVariantGroup(),\n  ],\n})\n"
  },
  {
    "path": "packages/core/template/module/unocss/vite.config.js.data.mjs",
    "content": "export default function getData({ oldData }) {\n  const UnoCSSPlugin = {\n    id: 'UnoCSS',\n    importer: `import UnoCSS from 'unocss/vite'`,\n    initializer: 'UnoCSS()',\n  }\n\n  return {\n    ...oldData,\n    plugins: oldData.plugins.flatMap(plugin =>\n      plugin.id === 'uni' ? [plugin, UnoCSSPlugin] : plugin,\n    ),\n  }\n}\n"
  },
  {
    "path": "packages/core/template/module/vitest/jsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"types\": [\n      \"vitest-environment-uniapp/types\"\n    ]\n  }\n}\n"
  },
  {
    "path": "packages/core/template/module/vitest/package.json",
    "content": "{\n  \"scripts\": {\n    \"test\": \"vitest\"\n  },\n  \"devDependencies\": {\n    \"vitest\": \"^4.1.5\",\n    \"vitest-environment-uniapp\": \"^0.0.5\"\n  }\n}\n"
  },
  {
    "path": "packages/core/template/module/vitest/test/index.test.js",
    "content": "import { beforeAll, describe, expect, it } from 'vitest'\n\ndescribe('test title', () => {\n  let page: Page\n  beforeAll(async () => {\n    page = await program.currentPage()\n    await page.waitFor(3000)\n  })\n\n  it('check uni-helper logo label', async () => {\n    const el = await page.$('.uni-helper-logo__label')\n    const titleText = await el.text()\n    expect(titleText).toEqual('uni-helper')\n  })\n})\n"
  },
  {
    "path": "packages/core/template/module/vitest/vitest.config.js",
    "content": "import { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  test: {\n    environment: 'uniapp',\n    environmentOptions: {\n      uniapp: {\n        platform: 'mp-weixin',\n        projectPath: './src',\n        port: 5121,\n      },\n    },\n  },\n})\n"
  },
  {
    "path": "packages/core/template/module/zPaging/jsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"types\": [\n      \"z-paging/types\"\n    ]\n  }\n}\n"
  },
  {
    "path": "packages/core/template/module/zPaging/package.json",
    "content": "{\n  \"dependencies\": {\n    \"z-paging\": \"^2.8.8\"\n  }\n}\n"
  },
  {
    "path": "packages/core/template/module/zPaging/vite.config.js.data.mjs",
    "content": "export default function getData({ oldData, utils }) {\n  const autoImportZPagingPlugin = {\n    id: 'z-paging-auto-import',\n    importer: `import { ZPagingResolver } from '@uni-helper/vite-plugin-uni-components/resolvers'`,\n  }\n\n  return {\n    ...oldData,\n    plugins: oldData.plugins.flatMap(plugin =>\n      plugin.id === 'autoImport'\n        ? [utils.addResolver(plugin, 'ZPagingResolver()'), autoImportZPagingPlugin]\n        : plugin,\n    ),\n  }\n}\n"
  },
  {
    "path": "packages/core/template/plugin/componentPlaceholder/package.json",
    "content": "{\n  \"devDependencies\": {\n    \"@binbinji/vite-plugin-component-placeholder\": \"^0.0.15\"\n  }\n}\n"
  },
  {
    "path": "packages/core/template/plugin/componentPlaceholder/vite.config.js.data.mjs",
    "content": "export default function getData({ oldData }) {\n  const componentPlaceholderPlugin = {\n    id: 'componentPlaceholder',\n    importer: `import ComponentPlaceholder from '@binbinji/vite-plugin-component-placeholder'`,\n    initializer: `// https://github.com/chouchouji/vite-plugin-component-placeholder\n    ComponentPlaceholder()`,\n  }\n\n  return {\n    ...oldData,\n    plugins: oldData.plugins.flatMap(plugin =>\n      plugin.id === 'uni' ? [componentPlaceholderPlugin, plugin] : plugin,\n    ),\n  }\n}\n"
  },
  {
    "path": "packages/core/template/plugin/filePlatform/package.json",
    "content": "{\n  \"devDependencies\": {\n    \"@uni-helper/vite-plugin-uni-platform\": \"^0.0.5\"\n  }\n}\n"
  },
  {
    "path": "packages/core/template/plugin/filePlatform/vite.config.js.data.mjs",
    "content": "export default function getData({ oldData }) {\n  const platformPlugin = {\n    id: 'platform',\n    importer: `import UniPlatform from '@uni-helper/vite-plugin-uni-platform'`,\n    initializer: `// https://uni-helper.js.org/vite-plugin-uni-platform\n    UniPlatform()`,\n  }\n\n  return {\n    ...oldData,\n    plugins: oldData.plugins.flatMap(plugin =>\n      plugin.id === 'uni' ? [platformPlugin, plugin] : plugin,\n    ),\n  }\n}\n"
  },
  {
    "path": "packages/core/template/plugin/import/package.json",
    "content": "{\n  \"devDependencies\": {\n    \"@uni-helper/vite-plugin-uni-components\": \"^0.2.10\"\n  }\n}\n"
  },
  {
    "path": "packages/core/template/plugin/import/vite.config.js.data.mjs",
    "content": "export default function getData({ oldData }) {\n  const autoImportPlugin = {\n    id: 'autoImport',\n    importer: `import Components from '@uni-helper/vite-plugin-uni-components'`,\n    initializer: `// https://uni-helper.js.org/vite-plugin-uni-components\n    Components({\n      dts: true,\n      resolvers: []\n    })`,\n  }\n\n  return {\n    ...oldData,\n    plugins: oldData.plugins.flatMap(plugin =>\n      plugin.id === 'uni' ? [autoImportPlugin, plugin] : plugin,\n    ),\n  }\n}\n"
  },
  {
    "path": "packages/core/template/plugin/layouts/package.json",
    "content": "{\n  \"devDependencies\": {\n    \"@uni-helper/vite-plugin-uni-layouts\": \"^0.1.11\"\n  }\n}\n"
  },
  {
    "path": "packages/core/template/plugin/layouts/vite.config.js.data.mjs",
    "content": "export default function getData({ oldData }) {\n  const layoutsPlugin = {\n    id: 'layouts',\n    importer: `import UniLayouts from '@uni-helper/vite-plugin-uni-layouts'`,\n    initializer: `// https://uni-helper.js.org/vite-plugin-uni-layouts\n    UniLayouts()`,\n  }\n\n  return {\n    ...oldData,\n    plugins: oldData.plugins.flatMap(plugin =>\n      plugin.id === 'uni' ? [layoutsPlugin, plugin] : plugin,\n    ),\n  }\n}\n"
  },
  {
    "path": "packages/core/template/plugin/manifest/manifest.config.js",
    "content": "import { defineManifestConfig } from '@uni-helper/vite-plugin-uni-manifest'\n\nexport default defineManifestConfig({\n  'name': '',\n  'appid': '',\n  'description': '',\n  'versionName': '1.0.0',\n  'versionCode': '100',\n  'transformPx': false,\n  /* 5+App特有相关 */\n  'app-plus': {\n    usingComponents: true,\n    nvueStyleCompiler: 'uni-app',\n    compilerVersion: 3,\n    splashscreen: {\n      alwaysShowBeforeRender: true,\n      waiting: true,\n      autoclose: true,\n      delay: 0,\n    },\n    /* 模块配置 */\n    modules: {},\n    /* 应用发布信息 */\n    distribute: {\n      /* android打包配置 */\n      android: {\n        permissions: [\n          '<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>',\n          '<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>',\n          '<uses-permission android:name=\"android.permission.VIBRATE\"/>',\n          '<uses-permission android:name=\"android.permission.READ_LOGS\"/>',\n          '<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>',\n          '<uses-feature android:name=\"android.hardware.camera.autofocus\"/>',\n          '<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>',\n          '<uses-permission android:name=\"android.permission.CAMERA\"/>',\n          '<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>',\n          '<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>',\n          '<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>',\n          '<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>',\n          '<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>',\n          '<uses-feature android:name=\"android.hardware.camera\"/>',\n          '<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>',\n        ],\n      },\n      /* ios打包配置 */\n      ios: {},\n      /* SDK配置 */\n      sdkConfigs: {},\n    },\n  },\n  /* 快应用特有相关 */\n  'quickapp': {},\n  /* 小程序特有相关 */\n  'mp-weixin': {\n    appid: '',\n    setting: {\n      urlCheck: false,\n    },\n    usingComponents: true,\n    darkmode: true,\n    themeLocation: 'theme.json',\n  },\n  'mp-alipay': {\n    usingComponents: true,\n  },\n  'mp-baidu': {\n    usingComponents: true,\n  },\n  'mp-toutiao': {\n    usingComponents: true,\n  },\n  'h5': {\n    darkmode: true,\n    themeLocation: 'theme.json',\n  },\n  'uniStatistics': {\n    enable: false,\n  },\n  'vueVersion': '3',\n})\n"
  },
  {
    "path": "packages/core/template/plugin/manifest/package.json",
    "content": "{\n  \"devDependencies\": {\n    \"@uni-helper/vite-plugin-uni-manifest\": \"^0.2.12\"\n  }\n}\n"
  },
  {
    "path": "packages/core/template/plugin/manifest/unh.config.js.data.mjs",
    "content": "export default function getData({ oldData }) {\n  return {\n    autoGenerate: {\n      ...oldData.autoGenerate,\n      manifest: true,\n    },\n  }\n}\n"
  },
  {
    "path": "packages/core/template/plugin/manifest/vite.config.js.data.mjs",
    "content": "export default function getData({ oldData }) {\n  const manifestPlugin = {\n    id: 'manifest',\n    importer: `import UniManifest from '@uni-helper/vite-plugin-uni-manifest'`,\n    initializer: `// https://uni-helper.js.org/vite-plugin-uni-manifest\n    UniManifest()`,\n  }\n\n  return {\n    ...oldData,\n    plugins: oldData.plugins.flatMap(plugin =>\n      plugin.id === 'uni' ? [manifestPlugin, plugin] : plugin,\n    ),\n  }\n}\n"
  },
  {
    "path": "packages/core/template/plugin/pages/jsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"types\": [\n      \"@uni-helper/vite-plugin-uni-pages\"\n    ]\n  }\n}\n"
  },
  {
    "path": "packages/core/template/plugin/pages/package.json",
    "content": "{\n  \"devDependencies\": {\n    \"@uni-helper/vite-plugin-uni-pages\": \"^0.3.24\"\n  }\n}\n"
  },
  {
    "path": "packages/core/template/plugin/pages/pages.config.js",
    "content": "import { defineUniPages } from '@uni-helper/vite-plugin-uni-pages'\n\nexport default defineUniPages({\n  pages: [],\n  globalStyle: {\n    backgroundColor: '@bgColor',\n    backgroundColorBottom: '@bgColorBottom',\n    backgroundColorTop: '@bgColorTop',\n    backgroundTextStyle: '@bgTxtStyle',\n    navigationBarBackgroundColor: '#000000',\n    navigationBarTextStyle: '@navTxtStyle',\n    navigationBarTitleText: 'Uni Creator',\n    navigationStyle: 'custom',\n  },\n  subPackages: [],\n})\n"
  },
  {
    "path": "packages/core/template/plugin/pages/unh.config.js.data.mjs",
    "content": "export default function getData({ oldData }) {\n  return {\n    autoGenerate: {\n      ...oldData.autoGenerate,\n      pages: true,\n    },\n  }\n}\n"
  },
  {
    "path": "packages/core/template/plugin/pages/vite.config.js.data.mjs",
    "content": "export default function getData({ oldData }) {\n  const pagesPlugin = {\n    id: 'pages',\n    importer: `import UniPages from '@uni-helper/vite-plugin-uni-pages'`,\n    initializer: `// https://uni-helper.js.org/vite-plugin-uni-pages\n    UniPages()`,\n  }\n\n  return {\n    ...oldData,\n    plugins: oldData.plugins.flatMap(plugin =>\n      plugin.id === 'uni' ? [pagesPlugin, plugin] : plugin,\n    ),\n  }\n}\n"
  },
  {
    "path": "packages/core/template/plugin/root/package.json",
    "content": "{\n  \"devDependencies\": {\n    \"@uni-ku/root\": \"^1.4.1\"\n  }\n}\n"
  },
  {
    "path": "packages/core/template/plugin/root/src/App.ku.vue",
    "content": "<script setup>\nfunction handleClickGithub() {\n  if (window?.open) {\n    window.open('https://github.com/uni-ku/root')\n  }\n  else {\n    uni.showToast({\n      icon: 'none',\n      title: '请使用浏览器打开',\n    })\n  }\n}\n</script>\n\n<template>\n  <div>\n    <KuRootView />\n    <div class=\"root-bar\">\n      Root component By\n      <span class=\"color-blue\" @click=\"handleClickGithub\">uni-ku/root</span>\n    </div>\n  </div>\n</template>\n\n<style>\n.root-bar {\n  position: fixed;\n  bottom: 0;\n  left: 0;\n  width: 100%;\n  height: 40px;\n  background-color: #f5f5f5;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  color: #999;\n  font-size: 14px;\n  line-height: 40px;\n  text-align: center;\n  box-sizing: border-box;\n  padding: 0 20px;\n}\n.color-blue {\n  color: #409eff;\n  cursor: pointer;\n}\n</style>\n"
  },
  {
    "path": "packages/core/template/plugin/root/vite.config.js.data.mjs",
    "content": "export default function getData({ oldData }) {\n  const rootPlugin = {\n    id: 'root',\n    importer: `import UniRoot from '@uni-ku/root'`,\n    initializer: `// https://github.com/uni-ku/root\n    UniRoot()`,\n  }\n\n  return {\n    ...oldData,\n    plugins: oldData.plugins.flatMap(plugin =>\n      plugin.id === 'uni' ? [rootPlugin, plugin] : plugin,\n    ),\n  }\n}\n"
  },
  {
    "path": "packages/core/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"es2018\",\n    \"lib\": [\"esnext\"],\n    \"baseUrl\": \".\",\n    \"module\": \"esnext\",\n    \"moduleResolution\": \"node\",\n    \"paths\": {\n      \"@/*\": [\"src/*\"]\n    },\n    \"resolveJsonModule\": true,\n    \"strict\": true,\n    \"strictNullChecks\": true,\n    \"esModuleInterop\": true,\n    \"skipDefaultLibCheck\": true,\n    \"skipLibCheck\": true\n  },\n  \"include\": [\"src\"]\n}\n"
  },
  {
    "path": "packages/core/tsup.config.ts",
    "content": "import { defineConfig } from 'tsup'\nimport PreprocessorDirectives from 'unplugin-preprocessor-directives/esbuild'\n\nexport default ({ watch }: { watch: boolean }) => (\n  defineConfig({\n    entry: {\n      outfile: 'src/index.ts',\n    },\n    format: 'cjs',\n    platform: 'node',\n    target: 'node14',\n    minify: watch ? false : 'terser',\n    clean: true,\n    esbuildPlugins: [\n      PreprocessorDirectives(),\n    ],\n  })\n)\n"
  },
  {
    "path": "packages/gui/.cargo/config.toml",
    "content": "[target.x86_64-pc-windows-msvc]\nrustflags = [\n  \"-C\",\n  \"target-feature=+crt-static\"\n]\n"
  },
  {
    "path": "packages/gui/.github/workflows/CI.yml",
    "content": "name: CI\nenv:\n  DEBUG: napi:*\n  APP_NAME: gui\n  MACOSX_DEPLOYMENT_TARGET: '10.13'\npermissions:\n  contents: write\n  id-token: write\non:\n  push:\n    branches:\n      - main\n    tags-ignore:\n      - '**'\n    paths-ignore:\n      - '**/*.md'\n      - LICENSE\n      - '**/*.gitignore'\n      - .editorconfig\n      - docs/**\n  pull_request: null\njobs:\n  build:\n    strategy:\n      fail-fast: false\n      matrix:\n        settings:\n          - host: macos-latest\n            target: x86_64-apple-darwin\n            build: yarn build --target x86_64-apple-darwin\n          - host: windows-latest\n            build: yarn build --target x86_64-pc-windows-msvc\n            target: x86_64-pc-windows-msvc\n          - host: windows-latest\n            build: |\n              yarn build --target i686-pc-windows-msvc\n              yarn test\n            target: i686-pc-windows-msvc\n          - host: macos-latest\n            target: aarch64-apple-darwin\n            build: yarn build --target aarch64-apple-darwin\n          - host: windows-latest\n            target: aarch64-pc-windows-msvc\n            build: yarn build --target aarch64-pc-windows-msvc\n    name: stable - ${{ matrix.settings.target }} - node@20\n    runs-on: ${{ matrix.settings.host }}\n    steps:\n      - uses: actions/checkout@v4\n      - name: Setup node\n        uses: actions/setup-node@v4\n        if: ${{ !matrix.settings.docker }}\n        with:\n          node-version: 20\n          cache: yarn\n      - name: Install\n        uses: dtolnay/rust-toolchain@stable\n        if: ${{ !matrix.settings.docker }}\n        with:\n          toolchain: stable\n          targets: ${{ matrix.settings.target }}\n      - name: Cache cargo\n        uses: actions/cache@v4\n        with:\n          path: |\n            ~/.cargo/registry/index/\n            ~/.cargo/registry/cache/\n            ~/.cargo/git/db/\n            .cargo-cache\n            target/\n          key: ${{ matrix.settings.target }}-cargo-${{ matrix.settings.host }}\n      - uses: goto-bus-stop/setup-zig@v2\n        if: ${{ matrix.settings.target == 'armv7-unknown-linux-gnueabihf' || matrix.settings.target == 'armv7-unknown-linux-musleabihf' }}\n        with:\n          version: 0.13.0\n      - name: Setup toolchain\n        run: ${{ matrix.settings.setup }}\n        if: ${{ matrix.settings.setup }}\n        shell: bash\n      - name: Setup node x86\n        if: matrix.settings.target == 'i686-pc-windows-msvc'\n        run: yarn config set supportedArchitectures.cpu \"ia32\"\n        shell: bash\n      - name: Install dependencies\n        run: yarn install\n      - name: Setup node x86\n        uses: actions/setup-node@v4\n        if: matrix.settings.target == 'i686-pc-windows-msvc'\n        with:\n          node-version: 20\n          cache: yarn\n          architecture: x86\n      - name: Build in docker\n        uses: addnab/docker-run-action@v3\n        if: ${{ matrix.settings.docker }}\n        with:\n          image: ${{ matrix.settings.docker }}\n          options: '--user 0:0 -v ${{ github.workspace }}/.cargo-cache/git/db:/usr/local/cargo/git/db -v ${{ github.workspace }}/.cargo/registry/cache:/usr/local/cargo/registry/cache -v ${{ github.workspace }}/.cargo/registry/index:/usr/local/cargo/registry/index -v ${{ github.workspace }}:/build -w /build'\n          run: ${{ matrix.settings.build }}\n      - name: Build\n        run: ${{ matrix.settings.build }}\n        if: ${{ !matrix.settings.docker }}\n        shell: bash\n      - name: Upload artifact\n        uses: actions/upload-artifact@v4\n        with:\n          name: bindings-${{ matrix.settings.target }}\n          path: ${{ env.APP_NAME }}.*.node\n          if-no-files-found: error\n  test-macOS-windows-binding:\n    name: Test bindings on ${{ matrix.settings.target }} - node@${{ matrix.node }}\n    needs:\n      - build\n    strategy:\n      fail-fast: false\n      matrix:\n        settings:\n          - host: macos-latest\n            target: x86_64-apple-darwin\n          - host: windows-latest\n            target: x86_64-pc-windows-msvc\n        node:\n          - '20'\n    runs-on: ${{ matrix.settings.host }}\n    steps:\n      - uses: actions/checkout@v4\n      - name: Setup node\n        uses: actions/setup-node@v4\n        with:\n          node-version: ${{ matrix.node }}\n          cache: yarn\n          architecture: x64\n      - name: Install dependencies\n        run: yarn install\n      - name: Download artifacts\n        uses: actions/download-artifact@v4\n        with:\n          name: bindings-${{ matrix.settings.target }}\n          path: .\n      - name: List packages\n        run: ls -R .\n        shell: bash\n      - name: Test bindings\n        run: yarn test\n  universal-macOS:\n    name: Build universal macOS binary\n    needs:\n      - build\n    runs-on: macos-latest\n    steps:\n      - uses: actions/checkout@v4\n      - name: Setup node\n        uses: actions/setup-node@v4\n        with:\n          node-version: 20\n          cache: yarn\n      - name: Install dependencies\n        run: yarn install\n      - name: Download macOS x64 artifact\n        uses: actions/download-artifact@v4\n        with:\n          name: bindings-x86_64-apple-darwin\n          path: artifacts\n      - name: Download macOS arm64 artifact\n        uses: actions/download-artifact@v4\n        with:\n          name: bindings-aarch64-apple-darwin\n          path: artifacts\n      - name: Combine binaries\n        run: yarn universal\n      - name: Upload artifact\n        uses: actions/upload-artifact@v4\n        with:\n          name: bindings-universal-apple-darwin\n          path: ${{ env.APP_NAME }}.*.node\n          if-no-files-found: error\n  publish:\n    name: Publish\n    runs-on: ubuntu-latest\n    needs:\n      - test-macOS-windows-binding\n      - universal-macOS\n    steps:\n      - uses: actions/checkout@v4\n      - name: Setup node\n        uses: actions/setup-node@v4\n        with:\n          node-version: 20\n          cache: yarn\n      - name: Install dependencies\n        run: yarn install\n      - name: Download all artifacts\n        uses: actions/download-artifact@v4\n        with:\n          path: artifacts\n      - name: Move artifacts\n        run: yarn artifacts\n      - name: List packages\n        run: ls -R ./npm\n        shell: bash\n      - name: Publish\n        run: |\n          npm config set provenance true\n          if git log -1 --pretty=%B | grep \"^[0-9]\\+\\.[0-9]\\+\\.[0-9]\\+$\";\n          then\n            echo \"//registry.npmjs.org/:_authToken=$NPM_TOKEN\" >> ~/.npmrc\n            npm publish --access public\n          elif git log -1 --pretty=%B | grep \"^[0-9]\\+\\.[0-9]\\+\\.[0-9]\\+\";\n          then\n            echo \"//registry.npmjs.org/:_authToken=$NPM_TOKEN\" >> ~/.npmrc\n            npm publish --tag next --access public\n          else\n            echo \"Not a release, skipping publish\"\n          fi\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n          NPM_TOKEN: ${{ secrets.NPM_TOKEN }}\n"
  },
  {
    "path": "packages/gui/.gitignore",
    "content": "# Created by https://www.toptal.com/developers/gitignore/api/node\n# Edit at https://www.toptal.com/developers/gitignore?templates=node\n\n### Node ###\n# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\nlerna-debug.log*\n\n# Diagnostic reports (https://nodejs.org/api/report.html)\nreport.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json\n\n# Runtime data\npids\n*.pid\n*.seed\n*.pid.lock\n\n# Directory for instrumented libs generated by jscoverage/JSCover\nlib-cov\n\n# Coverage directory used by tools like istanbul\ncoverage\n*.lcov\n\n# nyc test coverage\n.nyc_output\n\n# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)\n.grunt\n\n# Bower dependency directory (https://bower.io/)\nbower_components\n\n# node-waf configuration\n.lock-wscript\n\n# Compiled binary addons (https://nodejs.org/api/addons.html)\nbuild/Release\n\n# Dependency directories\nnode_modules/\njspm_packages/\n\n# TypeScript v1 declaration files\ntypings/\n\n# TypeScript cache\n*.tsbuildinfo\n\n# Optional npm cache directory\n.npm\n\n# Optional eslint cache\n.eslintcache\n\n# Microbundle cache\n.rpt2_cache/\n.rts2_cache_cjs/\n.rts2_cache_es/\n.rts2_cache_umd/\n\n# Optional REPL history\n.node_repl_history\n\n# Output of 'npm pack'\n*.tgz\n\n# Yarn Integrity file\n.yarn-integrity\n\n# dotenv environment variables file\n.env\n.env.test\n\n# parcel-bundler cache (https://parceljs.org/)\n.cache\n\n# Next.js build output\n.next\n\n# Nuxt.js build / generate output\n.nuxt\ndist\n\n# Gatsby files\n.cache/\n# Comment in the public line in if your project uses Gatsby and not Next.js\n# https://nextjs.org/blog/next-9-1#public-directory-support\n# public\n\n# vuepress build output\n.vuepress/dist\n\n# Serverless directories\n.serverless/\n\n# FuseBox cache\n.fusebox/\n\n# DynamoDB Local files\n.dynamodb/\n\n# TernJS port file\n.tern-port\n\n# Stores VSCode versions used for testing VSCode extensions\n.vscode-test\n\n# End of https://www.toptal.com/developers/gitignore/api/node\n\n# Created by https://www.toptal.com/developers/gitignore/api/macos\n# Edit at https://www.toptal.com/developers/gitignore?templates=macos\n\n### macOS ###\n# General\n.DS_Store\n.AppleDouble\n.LSOverride\n\n# Icon must end with two \nIcon\n\n\n# Thumbnails\n._*\n\n# Files that might appear in the root of a volume\n.DocumentRevisions-V100\n.fseventsd\n.Spotlight-V100\n.TemporaryItems\n.Trashes\n.VolumeIcon.icns\n.com.apple.timemachine.donotpresent\n\n# Directories potentially created on remote AFP share\n.AppleDB\n.AppleDesktop\nNetwork Trash Folder\nTemporary Items\n.apdisk\n\n### macOS Patch ###\n# iCloud generated files\n*.icloud\n\n# End of https://www.toptal.com/developers/gitignore/api/macos\n\n# Created by https://www.toptal.com/developers/gitignore/api/windows\n# Edit at https://www.toptal.com/developers/gitignore?templates=windows\n\n### Windows ###\n# Windows thumbnail cache files\nThumbs.db\nThumbs.db:encryptable\nehthumbs.db\nehthumbs_vista.db\n\n# Dump file\n*.stackdump\n\n# Folder config file\n[Dd]esktop.ini\n\n# Recycle Bin used on file shares\n$RECYCLE.BIN/\n\n# Windows Installer files\n*.cab\n*.msi\n*.msix\n*.msm\n*.msp\n\n# Windows shortcuts\n*.lnk\n\n# End of https://www.toptal.com/developers/gitignore/api/windows\n\n#Added by cargo\n\n/target\nCargo.lock\n\n.pnp.*\n.yarn/*\n!.yarn/patches\n!.yarn/plugins\n!.yarn/releases\n!.yarn/sdks\n!.yarn/versions\n\n*.node\n\n\nsrc/ui/index.html\n"
  },
  {
    "path": "packages/gui/.npmignore",
    "content": "target\nCargo.lock\n.cargo\n.github\nnpm\n.eslintrc\n.prettierignore\nrustfmt.toml\nyarn.lock\n*.node\n.yarn\n__test__\nrenovate.json\n"
  },
  {
    "path": "packages/gui/Cargo.toml",
    "content": "[package]\nedition = \"2021\"\nname = \"create-uni_gui\"\nversion = \"0.0.0\"\n\n[lib]\ncrate-type = [ \"cdylib\" ]\n\n[dependencies]\n# Default enable napi4 feature, see https://nodejs.org/api/n-api.html#node-api-version-matrix\nnapi = { version = \"2.12.2\", default-features = false, features = [ \"napi4\" ] }\nnapi-derive = \"2.12.2\"\nrfd = \"0.15.1\"\ntao = \"0.31.0\"\nwebbrowser = \"1.0.3\"\nwry = \"0.47.2\"\n\n[build-dependencies]\nnapi-build = \"2.0.1\"\n\n[profile.release]\nlto = true\nstrip = \"symbols\"\n"
  },
  {
    "path": "packages/gui/bin/index.cjs",
    "content": "#!/usr/bin/env node\n\nconst { createWebview } = require('./../index.js')\n\ncreateWebview()\n"
  },
  {
    "path": "packages/gui/build.rs",
    "content": "extern crate napi_build;\n\nfn main() {\n  napi_build::setup();\n}\n"
  },
  {
    "path": "packages/gui/bump.config.ts",
    "content": "// bump.config.ts\nimport { defineConfig } from 'bumpp'\n\nexport default defineConfig({\n  tag: false,\n  commit: 'v%s'\n})\n"
  },
  {
    "path": "packages/gui/index.d.ts",
    "content": "/* tslint:disable */\n/* eslint-disable */\n\n/* auto-generated by NAPI-RS */\n\nexport declare function createWebview(): void\n"
  },
  {
    "path": "packages/gui/index.js",
    "content": "/* tslint:disable */\n/* eslint-disable */\n/* prettier-ignore */\n\n/* auto-generated by NAPI-RS */\n\nconst { existsSync, readFileSync } = require('fs')\nconst { join } = require('path')\n\nconst { platform, arch } = process\n\nlet nativeBinding = null\nlet localFileExisted = false\nlet loadError = null\n\nfunction isMusl() {\n  // For Node 10\n  if (!process.report || typeof process.report.getReport !== 'function') {\n    try {\n      const lddPath = require('child_process').execSync('which ldd').toString().trim()\n      return readFileSync(lddPath, 'utf8').includes('musl')\n    } catch (e) {\n      return true\n    }\n  } else {\n    const { glibcVersionRuntime } = process.report.getReport().header\n    return !glibcVersionRuntime\n  }\n}\n\nswitch (platform) {\n  case 'android':\n    switch (arch) {\n      case 'arm64':\n        localFileExisted = existsSync(join(__dirname, 'gui.android-arm64.node'))\n        try {\n          if (localFileExisted) {\n            nativeBinding = require('./gui.android-arm64.node')\n          } else {\n            nativeBinding = require('@create-uni/gui-android-arm64')\n          }\n        } catch (e) {\n          loadError = e\n        }\n        break\n      case 'arm':\n        localFileExisted = existsSync(join(__dirname, 'gui.android-arm-eabi.node'))\n        try {\n          if (localFileExisted) {\n            nativeBinding = require('./gui.android-arm-eabi.node')\n          } else {\n            nativeBinding = require('@create-uni/gui-android-arm-eabi')\n          }\n        } catch (e) {\n          loadError = e\n        }\n        break\n      default:\n        throw new Error(`Unsupported architecture on Android ${arch}`)\n    }\n    break\n  case 'win32':\n    switch (arch) {\n      case 'x64':\n        localFileExisted = existsSync(\n          join(__dirname, 'gui.win32-x64-msvc.node')\n        )\n        try {\n          if (localFileExisted) {\n            nativeBinding = require('./gui.win32-x64-msvc.node')\n          } else {\n            nativeBinding = require('@create-uni/gui-win32-x64-msvc')\n          }\n        } catch (e) {\n          loadError = e\n        }\n        break\n      case 'ia32':\n        localFileExisted = existsSync(\n          join(__dirname, 'gui.win32-ia32-msvc.node')\n        )\n        try {\n          if (localFileExisted) {\n            nativeBinding = require('./gui.win32-ia32-msvc.node')\n          } else {\n            nativeBinding = require('@create-uni/gui-win32-ia32-msvc')\n          }\n        } catch (e) {\n          loadError = e\n        }\n        break\n      case 'arm64':\n        localFileExisted = existsSync(\n          join(__dirname, 'gui.win32-arm64-msvc.node')\n        )\n        try {\n          if (localFileExisted) {\n            nativeBinding = require('./gui.win32-arm64-msvc.node')\n          } else {\n            nativeBinding = require('@create-uni/gui-win32-arm64-msvc')\n          }\n        } catch (e) {\n          loadError = e\n        }\n        break\n      default:\n        throw new Error(`Unsupported architecture on Windows: ${arch}`)\n    }\n    break\n  case 'darwin':\n    localFileExisted = existsSync(join(__dirname, 'gui.darwin-universal.node'))\n    try {\n      if (localFileExisted) {\n        nativeBinding = require('./gui.darwin-universal.node')\n      } else {\n        nativeBinding = require('@create-uni/gui-darwin-universal')\n      }\n      break\n    } catch {}\n    switch (arch) {\n      case 'x64':\n        localFileExisted = existsSync(join(__dirname, 'gui.darwin-x64.node'))\n        try {\n          if (localFileExisted) {\n            nativeBinding = require('./gui.darwin-x64.node')\n          } else {\n            nativeBinding = require('@create-uni/gui-darwin-x64')\n          }\n        } catch (e) {\n          loadError = e\n        }\n        break\n      case 'arm64':\n        localFileExisted = existsSync(\n          join(__dirname, 'gui.darwin-arm64.node')\n        )\n        try {\n          if (localFileExisted) {\n            nativeBinding = require('./gui.darwin-arm64.node')\n          } else {\n            nativeBinding = require('@create-uni/gui-darwin-arm64')\n          }\n        } catch (e) {\n          loadError = e\n        }\n        break\n      default:\n        throw new Error(`Unsupported architecture on macOS: ${arch}`)\n    }\n    break\n  case 'freebsd':\n    if (arch !== 'x64') {\n      throw new Error(`Unsupported architecture on FreeBSD: ${arch}`)\n    }\n    localFileExisted = existsSync(join(__dirname, 'gui.freebsd-x64.node'))\n    try {\n      if (localFileExisted) {\n        nativeBinding = require('./gui.freebsd-x64.node')\n      } else {\n        nativeBinding = require('@create-uni/gui-freebsd-x64')\n      }\n    } catch (e) {\n      loadError = e\n    }\n    break\n  case 'linux':\n    switch (arch) {\n      case 'x64':\n        if (isMusl()) {\n          localFileExisted = existsSync(\n            join(__dirname, 'gui.linux-x64-musl.node')\n          )\n          try {\n            if (localFileExisted) {\n              nativeBinding = require('./gui.linux-x64-musl.node')\n            } else {\n              nativeBinding = require('@create-uni/gui-linux-x64-musl')\n            }\n          } catch (e) {\n            loadError = e\n          }\n        } else {\n          localFileExisted = existsSync(\n            join(__dirname, 'gui.linux-x64-gnu.node')\n          )\n          try {\n            if (localFileExisted) {\n              nativeBinding = require('./gui.linux-x64-gnu.node')\n            } else {\n              nativeBinding = require('@create-uni/gui-linux-x64-gnu')\n            }\n          } catch (e) {\n            loadError = e\n          }\n        }\n        break\n      case 'arm64':\n        if (isMusl()) {\n          localFileExisted = existsSync(\n            join(__dirname, 'gui.linux-arm64-musl.node')\n          )\n          try {\n            if (localFileExisted) {\n              nativeBinding = require('./gui.linux-arm64-musl.node')\n            } else {\n              nativeBinding = require('@create-uni/gui-linux-arm64-musl')\n            }\n          } catch (e) {\n            loadError = e\n          }\n        } else {\n          localFileExisted = existsSync(\n            join(__dirname, 'gui.linux-arm64-gnu.node')\n          )\n          try {\n            if (localFileExisted) {\n              nativeBinding = require('./gui.linux-arm64-gnu.node')\n            } else {\n              nativeBinding = require('@create-uni/gui-linux-arm64-gnu')\n            }\n          } catch (e) {\n            loadError = e\n          }\n        }\n        break\n      case 'arm':\n        if (isMusl()) {\n          localFileExisted = existsSync(\n            join(__dirname, 'gui.linux-arm-musleabihf.node')\n          )\n          try {\n            if (localFileExisted) {\n              nativeBinding = require('./gui.linux-arm-musleabihf.node')\n            } else {\n              nativeBinding = require('@create-uni/gui-linux-arm-musleabihf')\n            }\n          } catch (e) {\n            loadError = e\n          }\n        } else {\n          localFileExisted = existsSync(\n            join(__dirname, 'gui.linux-arm-gnueabihf.node')\n          )\n          try {\n            if (localFileExisted) {\n              nativeBinding = require('./gui.linux-arm-gnueabihf.node')\n            } else {\n              nativeBinding = require('@create-uni/gui-linux-arm-gnueabihf')\n            }\n          } catch (e) {\n            loadError = e\n          }\n        }\n        break\n      case 'riscv64':\n        if (isMusl()) {\n          localFileExisted = existsSync(\n            join(__dirname, 'gui.linux-riscv64-musl.node')\n          )\n          try {\n            if (localFileExisted) {\n              nativeBinding = require('./gui.linux-riscv64-musl.node')\n            } else {\n              nativeBinding = require('@create-uni/gui-linux-riscv64-musl')\n            }\n          } catch (e) {\n            loadError = e\n          }\n        } else {\n          localFileExisted = existsSync(\n            join(__dirname, 'gui.linux-riscv64-gnu.node')\n          )\n          try {\n            if (localFileExisted) {\n              nativeBinding = require('./gui.linux-riscv64-gnu.node')\n            } else {\n              nativeBinding = require('@create-uni/gui-linux-riscv64-gnu')\n            }\n          } catch (e) {\n            loadError = e\n          }\n        }\n        break\n      case 's390x':\n        localFileExisted = existsSync(\n          join(__dirname, 'gui.linux-s390x-gnu.node')\n        )\n        try {\n          if (localFileExisted) {\n            nativeBinding = require('./gui.linux-s390x-gnu.node')\n          } else {\n            nativeBinding = require('@create-uni/gui-linux-s390x-gnu')\n          }\n        } catch (e) {\n          loadError = e\n        }\n        break\n      default:\n        throw new Error(`Unsupported architecture on Linux: ${arch}`)\n    }\n    break\n  default:\n    throw new Error(`Unsupported OS: ${platform}, architecture: ${arch}`)\n}\n\nif (!nativeBinding) {\n  if (loadError) {\n    throw loadError\n  }\n  throw new Error(`Failed to load native binding`)\n}\n\nconst { createWebview } = nativeBinding\n\nmodule.exports.createWebview = createWebview\n"
  },
  {
    "path": "packages/gui/nodemon.json",
    "content": "{\n  \"watch\": [\"src\"],\n  \"ext\": \"rs\",\n  \"exec\": \"pnpm run build:debug\"\n}\n"
  },
  {
    "path": "packages/gui/npm/darwin-arm64/README.md",
    "content": "# `@create-uni/gui-darwin-arm64`\n\nThis is the **aarch64-apple-darwin** binary for `@create-uni/gui`\n"
  },
  {
    "path": "packages/gui/npm/darwin-arm64/package.json",
    "content": "{\n  \"name\": \"@create-uni/gui-darwin-arm64\",\n  \"version\": \"0.0.1-beta.1\",\n  \"os\": [\n    \"darwin\"\n  ],\n  \"cpu\": [\n    \"arm64\"\n  ],\n  \"license\": \"MIT\",\n  \"main\": \"gui.darwin-arm64.node\",\n  \"files\": [\n    \"gui.darwin-arm64.node\"\n  ],\n  \"engines\": {\n    \"node\": \">= 10\"\n  },\n  \"repository\": \"git@github.com:uni-helper/create-uni.git\"\n}\n"
  },
  {
    "path": "packages/gui/npm/darwin-x64/README.md",
    "content": "# `@create-uni/gui-darwin-x64`\n\nThis is the **x86_64-apple-darwin** binary for `@create-uni/gui`\n"
  },
  {
    "path": "packages/gui/npm/darwin-x64/package.json",
    "content": "{\n  \"name\": \"@create-uni/gui-darwin-x64\",\n  \"version\": \"0.0.1-beta.1\",\n  \"os\": [\n    \"darwin\"\n  ],\n  \"cpu\": [\n    \"x64\"\n  ],\n  \"license\": \"MIT\",\n  \"main\": \"gui.darwin-x64.node\",\n  \"files\": [\n    \"gui.darwin-x64.node\"\n  ],\n  \"engines\": {\n    \"node\": \">= 10\"\n  },\n  \"repository\": \"git@github.com:uni-helper/create-uni.git\"\n}\n"
  },
  {
    "path": "packages/gui/npm/win32-arm64-msvc/README.md",
    "content": "# `@create-uni/gui-win32-arm64-msvc`\n\nThis is the **aarch64-pc-windows-msvc** binary for `@create-uni/gui`\n"
  },
  {
    "path": "packages/gui/npm/win32-arm64-msvc/package.json",
    "content": "{\n  \"name\": \"@create-uni/gui-win32-arm64-msvc\",\n  \"version\": \"0.0.1-beta.1\",\n  \"os\": [\n    \"win32\"\n  ],\n  \"cpu\": [\n    \"arm64\"\n  ],\n  \"license\": \"MIT\",\n  \"main\": \"gui.win32-arm64-msvc.node\",\n  \"files\": [\n    \"gui.win32-arm64-msvc.node\"\n  ],\n  \"engines\": {\n    \"node\": \">= 10\"\n  },\n  \"repository\": \"git@github.com:uni-helper/create-uni.git\"\n}\n"
  },
  {
    "path": "packages/gui/npm/win32-ia32-msvc/README.md",
    "content": "# `@create-uni/gui-win32-ia32-msvc`\n\nThis is the **i686-pc-windows-msvc** binary for `@create-uni/gui`\n"
  },
  {
    "path": "packages/gui/npm/win32-ia32-msvc/package.json",
    "content": "{\n  \"name\": \"@create-uni/gui-win32-ia32-msvc\",\n  \"version\": \"0.0.1-beta.1\",\n  \"os\": [\n    \"win32\"\n  ],\n  \"cpu\": [\n    \"ia32\"\n  ],\n  \"license\": \"MIT\",\n  \"main\": \"gui.win32-ia32-msvc.node\",\n  \"files\": [\n    \"gui.win32-ia32-msvc.node\"\n  ],\n  \"engines\": {\n    \"node\": \">= 10\"\n  },\n  \"repository\": \"git@github.com:uni-helper/create-uni.git\"\n}\n"
  },
  {
    "path": "packages/gui/npm/win32-x64-msvc/README.md",
    "content": "# `@create-uni/gui-win32-x64-msvc`\n\nThis is the **x86_64-pc-windows-msvc** binary for `@create-uni/gui`\n"
  },
  {
    "path": "packages/gui/npm/win32-x64-msvc/package.json",
    "content": "{\n  \"name\": \"@create-uni/gui-win32-x64-msvc\",\n  \"version\": \"0.0.1-beta.1\",\n  \"os\": [\n    \"win32\"\n  ],\n  \"cpu\": [\n    \"x64\"\n  ],\n  \"license\": \"MIT\",\n  \"main\": \"gui.win32-x64-msvc.node\",\n  \"files\": [\n    \"gui.win32-x64-msvc.node\"\n  ],\n  \"engines\": {\n    \"node\": \">= 10\"\n  },\n  \"repository\": \"git@github.com:uni-helper/create-uni.git\"\n}\n"
  },
  {
    "path": "packages/gui/package.json",
    "content": "{\n  \"name\": \"@create-uni/gui\",\n  \"version\": \"0.0.7\",\n  \"license\": \"MIT\",\n  \"main\": \"./bin/index.cjs\",\n  \"bin\": {\n    \"create-uni-gui\": \"./bin/index.cjs\"\n  },\n  \"files\": [\n    \"bin/index.cjs\",\n    \"index.js\"\n  ],\n  \"napi\": {\n    \"name\": \"gui\",\n    \"triples\": {\n      \"defaults\": false,\n      \"additional\": [\n        \"aarch64-apple-darwin\",\n        \"aarch64-pc-windows-msvc\",\n        \"x86_64-apple-darwin\",\n        \"x86_64-pc-windows-msvc\",\n        \"i686-pc-windows-msvc\"\n      ]\n    }\n  },\n  \"engines\": {\n    \"node\": \">= 10\"\n  },\n  \"repository\": {\n    \"directory\": \"packages/gui\",\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/uni-helper/create-uni.git\"\n  },\n  \"scripts\": {\n    \"artifacts\": \"napi artifacts\",\n    \"build\": \"napi build --platform --release\",\n    \"build:debug\": \"napi build --platform\",\n    \"dev\": \"nodemon\",\n    \"prepublishOnly\": \"napi prepublish -t npm\",\n    \"test\": \"ava\",\n    \"release\": \"bumpp\",\n    \"universal\": \"napi universal\",\n    \"version\": \"napi version\"\n  },\n  \"devDependencies\": {\n    \"@napi-rs/cli\": \"^2.18.4\"\n  }\n}\n"
  },
  {
    "path": "packages/gui/rustfmt.toml",
    "content": "tab_spaces = 2\nedition = \"2021\"\n"
  },
  {
    "path": "packages/gui/src/lib.rs",
    "content": "#![deny(clippy::all)]\n\n#[macro_use]\nextern crate napi_derive;\n\nuse napi::Result;\n\nuse tao::{\n  event::{Event, WindowEvent},\n  event_loop::{ControlFlow, EventLoopBuilder},\n  window::WindowBuilder,\n};\nuse wry::{dpi::LogicalSize, http::Request, WebViewBuilder};\n\nuse rfd::FileDialog;\nuse std::env;\nuse std::path::PathBuf;\nuse webbrowser::{open_browser, Browser::Default};\n\nenum UserEvent {\n  FilePath,\n  CloseWindow,\n  DragWindow,\n}\n\n#[napi]\npub fn create_webview() -> Result<()> {\n  let current_dir: PathBuf = env::current_dir().expect(\"Unable to get current working directory\");\n  let input = match env::var(\"CREATE_UNI_GUI_INPUT\") {\n    Ok(val) => val,\n    Err(_) => String::from(\"default_value\"),\n  };\n\n  let current_dir_str = current_dir.to_str().unwrap_or(\"\");\n  let escaped_current_dir_str = current_dir_str.replace(\"\\\\\", \"\\\\\\\\\");\n\n  let final_string = format!(\n    \"window.create_uni_current_dir=\\\"{}\\\";window.create_uni_data={}\",\n    escaped_current_dir_str, input\n  );\n\n  const WINDOW_WIDTH: u32 = 375;\n  const WINDOW_HEIGHT: u32 = 667;\n\n  let event_loop = EventLoopBuilder::<UserEvent>::with_user_event().build();\n  let window = WindowBuilder::new()\n    .with_inner_size(LogicalSize {\n      width: WINDOW_WIDTH,\n      height: WINDOW_HEIGHT,\n    })\n    .with_title(\"Uni Creator\")\n    .with_resizable(false)\n    .with_decorations(false)\n    .build(&event_loop)\n    .unwrap();\n\n  let proxy = event_loop.create_proxy();\n  let handler = move |req: Request<String>| {\n    let body = req.body();\n    let mut req = body.split(['|']);\n    match req.next().unwrap() {\n      \"file_path\" => {\n        let _ = proxy.send_event(UserEvent::FilePath);\n      }\n      \"drag_window\" => {\n        let _ = proxy.send_event(UserEvent::DragWindow);\n      }\n      \"open\" => {\n        let url = req.next().unwrap();\n        open_browser(Default, url).unwrap();\n      }\n      \"close\" => {\n        let _ = proxy.send_event(UserEvent::CloseWindow);\n      }\n      \"install\" => {\n        let message = req.next().unwrap();\n        println!(\"{}\", message);\n        let _ = proxy.send_event(UserEvent::CloseWindow);\n      }\n      _ => {}\n    }\n  };\n\n  #[cfg(debug_assertions)]\n  let webview = WebViewBuilder::new()\n    .with_url(\"http://localhost:4006/\")\n    .with_ipc_handler(handler)\n    .with_initialization_script(&final_string)\n    .build(&window)\n    .unwrap();\n\n  const HTML_CONTENT: &str = include_str!(\"ui/index.html\");\n  #[cfg(not(debug_assertions))]\n  let webview = WebViewBuilder::new()\n    .with_html(HTML_CONTENT)\n    .with_ipc_handler(handler)\n    .with_initialization_script(&final_string)\n    .build(&window)\n    .expect(\"Failed to build WebView in release mode\");\n\n  event_loop.run(move |event, _, control_flow| {\n    *control_flow = ControlFlow::Wait;\n\n    match event {\n      Event::WindowEvent {\n        event: WindowEvent::CloseRequested,\n        ..\n      }\n      | Event::UserEvent(UserEvent::CloseWindow) => *control_flow = ControlFlow::Exit,\n\n      Event::UserEvent(e) => match e {\n        UserEvent::FilePath => {\n          // Show file dialog to select a directory\n          if let Some(path) = FileDialog::new()\n            .set_title(\"Select a directory\")\n            .set_directory(&current_dir)\n            .pick_folder()\n          {\n            let script = format!(\n              r#\"\n              window.dispatchEvent(\n                new CustomEvent('pathEvent', {{\n                  detail: {{ path: '{}' }} \n              }})\n              );\n              \"#,\n              path.to_str().unwrap_or(\"\").replace(\"\\\\\", \"\\\\\\\\\")\n            );\n            webview.evaluate_script(&script).unwrap();\n          }\n        }\n        UserEvent::DragWindow => window.drag_window().unwrap(),\n        UserEvent::CloseWindow => { /* handled above */ }\n      },\n      _ => (),\n    }\n  });\n}\n"
  },
  {
    "path": "packages/info/bump.config.ts",
    "content": "// bump.config.ts\nimport { defineConfig } from 'bumpp'\n\nexport default defineConfig({\n  tag: 'info-v%s',\n})\n"
  },
  {
    "path": "packages/info/package.json",
    "content": "{\n  \"name\": \"@create-uni/info\",\n  \"type\": \"module\",\n  \"version\": \"0.1.9\",\n  \"packageManager\": \"pnpm@9.9.0\",\n  \"description\": \"快速检测你的uni-app项目\",\n  \"author\": \"FliPPeDround <flippedround@qq.com>\",\n  \"license\": \"MIT\",\n  \"funding\": \"https://afdian.com/a/flippedround\",\n  \"homepage\": \"https://github.com/uni-helper/create-uni#readme\",\n  \"repository\": {\n    \"directory\": \"packages/info\",\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/uni-helper/create-uni.git\"\n  },\n  \"bugs\": \"https://github.com/uni-helper/create-uni/issues\",\n  \"keywords\": [\n    \"uni\",\n    \"uni-app\",\n    \"create-uni\",\n    \"cli\",\n    \"vue\",\n    \"miniapp\",\n    \"create\"\n  ],\n  \"sideEffects\": false,\n  \"bin\": {\n    \"create-uni-info\": \"./dist/outfile.cjs\"\n  },\n  \"files\": [\n    \"dist/outfile.cjs\"\n  ],\n  \"scripts\": {\n    \"build\": \"tsup\",\n    \"dev\": \"tsup --watch\",\n    \"prepublishOnly\": \"nr build\",\n    \"release\": \"bumpp\",\n    \"typecheck\": \"tsc --noEmit\"\n  },\n  \"devDependencies\": {\n    \"@create-uni/shared\": \"workspace:*\",\n    \"@types/envinfo\": \"^7.8.4\",\n    \"@types/minimist\": \"^1.2.5\",\n    \"envinfo\": \"^7.14.0\",\n    \"kolorist\": \"^1.8.0\",\n    \"path-exists\": \"^5.0.0\"\n  }\n}\n"
  },
  {
    "path": "packages/info/src/constants/index.ts",
    "content": "export const uniDependenciesMap = {\n  '@uni-helper/uni-use': ['@vueuse/core'],\n  '@uni-helper/axios-adapter': ['axios'],\n  '@uni-helper/unocss-preset-uni': ['unocss'],\n  '@uni-helper/eslint-config': ['eslint'],\n  '@uni-helper/vite-plugin-uni-tailwind': ['tailwindcss'],\n} as Record<string, string[]>\n"
  },
  {
    "path": "packages/info/src/index.ts",
    "content": "#!/usr/bin/env node\n\nimport type { UniPresetEnvInfo } from './types'\nimport process from 'node:process'\nimport { generateBanner, ora } from '@create-uni/shared'\nimport envinfo from 'envinfo'\nimport { gray, italic, link, red, yellow } from 'kolorist'\nimport { uniDependenciesMap } from './constants'\nimport { getBaseDependencies, getUniHelperDependencies } from './utils/dependencies'\nimport { getUniHelperExtensions, getVolarExtensions, getVSCodeExtensions, paserExtensionList } from './utils/extensions'\nimport { whichPm } from './utils/whichPm'\n\nexport async function getBaseEnvInfo() {\n  const loadingStopInfo = {\n    message: '',\n    code: 0,\n  }\n\n  const _envInfo = JSON.parse(await envinfo.run(\n    {\n      npmPackages: '**',\n      System: ['OS'],\n      Binaries: ['Node'],\n      IDEs: ['VSCode'],\n    },\n    {\n      json: true,\n      showNotFound: true,\n    },\n  )) as UniPresetEnvInfo\n  const os = _envInfo.System.OS\n  const node = _envInfo.Binaries.Node.version\n  const vscode = _envInfo.IDEs.VSCode?.version || null\n  const packageInfo = _envInfo.npmPackages\n\n  // 获取npm包信息\n  let uniHelperDependencies\n  let baseDependencies\n  if (packageInfo && Object.keys(packageInfo).includes('@dcloudio/uni-app')) {\n    uniHelperDependencies = getUniHelperDependencies(packageInfo)\n    baseDependencies = getBaseDependencies(packageInfo)\n  }\n  else {\n    loadingStopInfo.message = red('⛔ 当前目录未安装uni-app，请在uni-app项目根目录下执行, 以获取依赖信息！！！')\n    loadingStopInfo.code = 1\n  }\n\n  // 获取vscode扩展信息\n  let uniHelperExtensions\n  let volarExtensions\n  const extensions = getVSCodeExtensions()\n  if (vscode && extensions) {\n    uniHelperExtensions = paserExtensionList(getUniHelperExtensions(extensions))\n    volarExtensions = paserExtensionList(getVolarExtensions(extensions))[0] || null\n  }\n  else {\n    if (loadingStopInfo.code === 1) {\n      loadingStopInfo.message += `\\n${yellow('⚠️ 未找到vscode, 无法获取插件信息, 请自行补充vscode插件信息')}`\n    }\n    else {\n      loadingStopInfo.message += `${yellow('⚠️ 未找到vscode, 无法获取插件信息, 请自行补充vscode插件信息')}`\n      loadingStopInfo.code = 1\n    }\n  }\n\n  const pm = await whichPm()\n\n  return {\n    os,\n    node,\n    vscode,\n    uniHelperExtensions,\n    baseDependencies,\n    volarExtensions,\n    packageInfo,\n    uniHelperDependencies,\n    packageManager: pm?.name,\n    loadingStopInfo,\n  }\n}\n\nexport async function getUniAppInfo() {\n  console.log(generateBanner('@uni-create/info - 快速检测 uni-app 环境信息'))\n  console.log()\n  const loading = ora('正在获取环境信息...').start()\n\n  // 获取环境信息\n  const baseEnvInfo = await getBaseEnvInfo()\n  const errorDependencies = baseEnvInfo.uniHelperDependencies || []\n  const errorExtensions = baseEnvInfo.uniHelperExtensions || []\n  loading.succeed('获取环境信息完成')\n\n  if (baseEnvInfo.loadingStopInfo.code !== 0) {\n    console.log()\n    console.log(baseEnvInfo.loadingStopInfo.message)\n  }\n\n  const splitter = '----------------------------------------------'\n  console.log()\n  console.log(splitter)\n  console.log()\n\n  // 输出系统环境信息\n  const systemEnvInfo = {\n    os: baseEnvInfo.os,\n    node: baseEnvInfo.node,\n    packageManager: baseEnvInfo.packageManager,\n    vscode: baseEnvInfo?.vscode,\n    volar: baseEnvInfo?.volarExtensions?.version,\n  }\n  let baseEnvInfoStr = ''\n  for (const [key, value] of Object.entries(systemEnvInfo)) {\n    if (value)\n      baseEnvInfoStr += `  - ${key}: \\`${value}\\`\\n`\n  }\n  console.log(italic('基础环境信息:'))\n  console.log(baseEnvInfoStr)\n\n  // 输出基础依赖信息\n  const baseDependenciesLength = Object.keys(baseEnvInfo?.baseDependencies || {}).length\n  if (baseDependenciesLength > 0) {\n    let baseDependenciesStr = ''\n    for (const [name, version] of Object.entries(baseEnvInfo.baseDependencies!))\n      baseDependenciesStr += `  - ${name}: \\`${version}\\`\\n`\n\n    console.log(italic('基础依赖信息:'))\n    console.log(baseDependenciesStr)\n  }\n\n  // 输出uni-helper依赖信息\n  const uniHelperDependenciesLength = Object.keys(baseEnvInfo?.uniHelperDependencies || {}).length\n  if (uniHelperDependenciesLength > 0) {\n    let errorDependenciesStr = ''\n    for (const [key, value] of Object.entries(errorDependencies)) {\n      errorDependenciesStr += `  - ${key}: \\`${value}\\`\\n`\n      if (uniDependenciesMap[key]) {\n        for (const uniDependency of uniDependenciesMap[key]) {\n          const packageInfo = baseEnvInfo.packageInfo?.[uniDependency]\n          if (packageInfo?.installed) {\n            errorDependenciesStr += `    - ${uniDependency}: \\`${packageInfo.installed}\\`\\n`\n          }\n          else {\n            errorDependenciesStr += `    - ${uniDependency}: \\`未安装\\`\\n`\n          }\n        }\n      }\n    }\n\n    console.log(italic('uni-helper依赖信息:'))\n    console.log(errorDependenciesStr)\n  }\n\n  // 输出uni-helper插件信息\n  if (errorExtensions.length > 0) {\n    let errorExtensionsStr = ''\n    for (const { name, version, bugs } of errorExtensions)\n      errorExtensionsStr += `  - ${link(name, bugs)}: \\`${version}\\`\\n`\n\n    console.log(italic('uni-helper插件信息:'))\n    console.log(errorExtensionsStr)\n  }\n\n  console.log(splitter)\n  console.log()\n  console.log(\n    `${[\n      gray(italic('🎯 感谢使用uni-helper，请提供虚线内的信息以便我们排查问题')),\n      gray(italic('   若还需提供其他信息，请自行修改补充')),\n      '',\n      '👉 uni-helper 官网: https://uni-helper.js.org/',\n      '👉 改进建议: https://github.com/uni-helper/create-uni/issues/new/choose',\n    ].join('\\n')}\\n`,\n  )\n\n  process.exit(0)\n}\n\ngetUniAppInfo()\n"
  },
  {
    "path": "packages/info/src/question/index.ts",
    "content": "import process from 'node:process'\nimport { isCancel, multiselect } from '@clack/prompts'\n\nexport default async function question(choices: string[], message: string) {\n  const result = await multiselect({\n    message,\n    options: choices.map(item => ({\n      value: item,\n      label: item,\n    })),\n    required: false,\n  })\n  if (isCancel(result)) {\n    process.exit(0)\n  }\n  return result\n}\n"
  },
  {
    "path": "packages/info/src/types/index.d.ts",
    "content": "export interface UniPresetEnvInfo {\n  System: {\n    OS: string\n  }\n  Binaries: {\n    Node: {\n      version: string\n      path: string\n    }\n  }\n  IDEs: {\n    VSCode: {\n      version: string\n      path: string\n    }\n    WebStorm: {\n      version: string\n      path: string\n    }\n  }\n  npmPackages: {\n    [key: string]: {\n      installed: string\n      wanted: string\n    }\n  }\n}\n"
  },
  {
    "path": "packages/info/src/utils/dependencies.ts",
    "content": "import type { UniPresetEnvInfo } from '../types'\n\nexport function getBaseDependencies(packageInfo: UniPresetEnvInfo['npmPackages']) {\n  const baseDependenciesName = ['vue', 'vite', '@dcloudio/uni-app']\n  const baseDependencies: Record<string, string> = {}\n  for (const name of baseDependenciesName) {\n    const version = packageInfo[name]?.installed\n    if (version)\n      baseDependencies[name] = version\n  }\n  return baseDependencies\n}\n\nexport function getUniHelperDependencies(packageInfo: UniPresetEnvInfo['npmPackages']) {\n  const uniHelperDependencies: Record<string, string> = {}\n  for (const name in packageInfo) {\n    if (name.includes('@uni-helper'))\n      uniHelperDependencies[name] = packageInfo[name]?.installed || ''\n  }\n  return uniHelperDependencies\n}\n\n// export async function getErrorDependencies(\n//   argv: string,\n//   uniHelperDependencies: Record<string, string>,\n// ) {\n//   if (!uniHelperDependencies)\n//     return {}\n//   let errorDependencies: Record<string, string> = {}\n//   if (argv === 'all') {\n//     errorDependencies = uniHelperDependencies\n//   }\n//   else {\n//     const uniHelperDependenciesName = Object.keys(uniHelperDependencies)\n//     const errorIndexList = await question(uniHelperDependenciesName, '请选择需要反馈的依赖')\n\n//     errorIndexList.forEach((item) => {\n//       errorDependencies[item] = uniHelperDependencies[item]\n//     })\n//   }\n//   return errorDependencies\n// }\n"
  },
  {
    "path": "packages/info/src/utils/extensions.ts",
    "content": "import { execSync } from 'node:child_process'\n\nexport function getVSCodeExtensions() {\n  try {\n    const list = execSync(\n      `code --list-extensions --show-versions`,\n      {\n        encoding: 'utf-8',\n        stdio: [0, 'pipe', 'ignore'],\n      },\n    )\n    return list.split(/\\r?\\n/).filter(line => line.trim() !== '')\n  }\n  catch {\n    return null\n  }\n}\n\nexport function getUniHelperExtensions(extensions: string[]) {\n  return extensions.filter(item => item.toLocaleLowerCase().includes('uni-helper.') || item.toLocaleLowerCase().includes('mrmaoddxxaa.create-uniapp-view'))\n}\n\nexport function getVolarExtensions(extensions: string[]) {\n  return extensions.filter(item => item.toLocaleLowerCase().includes('vue.volar'))\n}\n\nexport function paserExtensionList(list: string[]) {\n  return list.map((item) => {\n    const [name_, version] = item.split('@')\n    const [_, name] = name_.split('.')\n    const bugs = `https://github.com/uni-helper/${name}/issues`\n    return { name, version, bugs }\n  })\n}\n\n// export async function getErrorExtensions(\n//   argv: string,\n//   uniHelperExtensions: ReturnType<typeof paserExtensionList>,\n// ) {\n//   if (!uniHelperExtensions)\n//     return []\n\n//   const choices = uniHelperExtensions.map(item => item.name)\n\n//   let errorExtensions: typeof uniHelperExtensions = []\n//   if (argv === 'all') {\n//     errorExtensions = uniHelperExtensions\n//   }\n//   else {\n//     const errorIndexList = await question(choices, '请选择需要反馈的vscode插件')\n\n//     errorIndexList.forEach((item) => {\n//       errorExtensions.push(uniHelperExtensions.find(i => i.name === item)!)\n//     })\n//   }\n//   return errorExtensions\n// }\n"
  },
  {
    "path": "packages/info/src/utils/whichPm.ts",
    "content": "import { join } from 'node:path'\nimport process from 'node:process'\nimport { pathExists } from 'path-exists'\n\nexport async function whichPm() {\n  const pkgPath = process.cwd()\n  const modulesPath = join(pkgPath, 'node_modules')\n\n  const existsYarnFlagFile = await pathExists(join(modulesPath, '.yarn-integrity'))\n  if (existsYarnFlagFile)\n    return { name: 'yarn' }\n\n  const existsPnpmFlagFile = await pathExists(join(modulesPath, '.modules.yaml'))\n  if (existsPnpmFlagFile)\n    return { name: 'pnpm' }\n\n  if (await pathExists(join(pkgPath, 'bun.lockb')))\n    return { name: 'bun' }\n\n  const modulesExists = await pathExists(modulesPath)\n  return modulesExists ? { name: 'npm' } : null\n}\n"
  },
  {
    "path": "packages/info/tsup.config.ts",
    "content": "import { defineConfig } from 'tsup'\n\nexport default ({ watch }: { watch: boolean }) => (\n  defineConfig({\n    entry: {\n      outfile: 'src/index.ts',\n    },\n    format: 'cjs',\n    platform: 'node',\n    target: 'node14',\n    minify: watch ? false : 'terser',\n    clean: true,\n  })\n)\n"
  },
  {
    "path": "packages/mcp/README.md",
    "content": "# @create-uni/mcp\n\ncreate-uni的MCP（Model Context Protocol）服务，为AI助手提供创建uni-app项目的能力。\n\n```json\n{\n  \"mcpServers\": {\n    \"create-uni\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"@create-uni/mcp\"\n      ]\n    }\n  }\n}\n```\n"
  },
  {
    "path": "packages/mcp/bump.config.ts",
    "content": "// bump.config.ts\nimport { defineConfig } from 'bumpp'\n\nexport default defineConfig({\n  tag: 'mcp-v%s',\n})\n"
  },
  {
    "path": "packages/mcp/package.json",
    "content": "{\n  \"name\": \"@create-uni/mcp\",\n  \"type\": \"module\",\n  \"version\": \"0.1.14\",\n  \"packageManager\": \"pnpm@9.9.0\",\n  \"description\": \"create-uni的mcp服务\",\n  \"author\": \"FliPPeDround <flippedround@qq.com>\",\n  \"license\": \"MIT\",\n  \"funding\": \"https://afdian.com/a/flippedround\",\n  \"homepage\": \"https://github.com/uni-helper/create-uni#readme\",\n  \"repository\": {\n    \"directory\": \"packages/mcp\",\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/uni-helper/create-uni.git\"\n  },\n  \"bugs\": \"https://github.com/uni-helper/create-uni/issues\",\n  \"keywords\": [\n    \"uni\",\n    \"uni-app\",\n    \"create-uni\",\n    \"cli\",\n    \"vue\",\n    \"miniapp\",\n    \"create\"\n  ],\n  \"sideEffects\": false,\n  \"bin\": {\n    \"create-uni-mcp\": \"./dist/outfile.cjs\"\n  },\n  \"files\": [\n    \"dist/outfile.cjs\"\n  ],\n  \"scripts\": {\n    \"build\": \"tsup\",\n    \"dev\": \"tsup --watch\",\n    \"prepublishOnly\": \"nr build\",\n    \"inspect\": \"mcp-inspector\",\n    \"release\": \"bumpp\",\n    \"typecheck\": \"tsc --noEmit\",\n    \"test\": \"vitest\"\n  },\n  \"devDependencies\": {\n    \"@create-uni/config\": \"workspace:*\",\n    \"@create-uni/shared\": \"workspace:*\",\n    \"@modelcontextprotocol/inspector\": \"^0.16.6\",\n    \"@modelcontextprotocol/sdk\": \"^1.17.5\",\n    \"@types/cross-spawn\": \"^6.0.6\",\n    \"cross-spawn\": \"^7.0.6\",\n    \"zod\": \"3.25.68\"\n  }\n}\n"
  },
  {
    "path": "packages/mcp/src/handlers.ts",
    "content": "import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js'\nimport type { CreateCustomOptions, CreateWithTemplateOptions } from './types.js'\nimport { MODULES, PLUGINS, TEMPLATES, UI } from '@create-uni/config'\nimport { canSkipEmptying } from '@create-uni/shared'\nimport { sync } from 'cross-spawn'\nimport { flattenTemplateList } from './utils.js'\n\n/**\n * 构建命令行参数\n */\nfunction buildCommandArgs(options: CreateCustomOptions & { templateType?: string }): string[] {\n  const args: string[] = []\n\n  // 项目名称\n  args.push(options.name)\n\n  // TypeScript支持\n  if (options.needsTypeScript) {\n    args.push('--ts')\n  }\n\n  // ESLint配置\n  if (options.needsEslint) {\n    args.push('-e')\n  }\n\n  // UI组件库\n  if (options.UIName) {\n    args.push('-u', options.UIName)\n  }\n\n  // 插件列表\n  if (options.pluginList?.length) {\n    options.pluginList.forEach((plugin) => {\n      args.push('-p', plugin)\n    })\n  }\n\n  // 模块列表\n  if (options.moduleList?.length) {\n    options.moduleList.forEach((module) => {\n      args.push('-m', module)\n    })\n  }\n\n  // 强制覆盖\n  if (options.force) {\n    args.push('-f')\n  }\n\n  // 模板类型（如果指定）\n  if (options.templateType) {\n    args.push('-t', options.templateType)\n  }\n\n  return args\n}\n\n/**\n * 执行创建命令\n */\nfunction executeCreateCommand(args: string[]): { success: boolean, error?: string } {\n  const [command, ...commandArgs] = ['npx', 'create-uni@latest', ...args]\n\n  const { error } = sync(command, commandArgs, { stdio: 'pipe' })\n\n  if (error) {\n    return { success: false, error: error.message }\n  }\n\n  return { success: true }\n}\n\n/**\n * 检查目录是否可以创建项目\n */\nfunction checkDirectory(name: string, force?: boolean): { canCreate: boolean, message?: string } {\n  if (!force) {\n    const canSkip = canSkipEmptying(name)\n    if (!canSkip) {\n      return {\n        canCreate: false,\n        message: `目标目录${name}非空，无法创建项目, 请使用 --force 强制覆盖`,\n      }\n    }\n  }\n\n  return { canCreate: true }\n}\n\n/**\n * 使用预设模板创建项目\n */\nexport async function createWithTemplate(options: CreateWithTemplateOptions): Promise<CallToolResult> {\n  const { canCreate, message } = checkDirectory(options.name, options.force)\n\n  if (!canCreate) {\n    return {\n      content: [{\n        type: 'text',\n        text: message!,\n      }],\n    }\n  }\n\n  const args = buildCommandArgs({\n    name: options.name,\n    templateType: options.templateType,\n    force: options.force,\n  })\n\n  const result = executeCreateCommand(args)\n\n  if (!result.success) {\n    return {\n      content: [{\n        type: 'text',\n        text: `创建项目失败: ${result.error}`,\n      }],\n    }\n  }\n\n  const flattenedTemplates = flattenTemplateList(TEMPLATES)\n  const templateInfo = flattenedTemplates.find(t => t.value === options.templateType)?.description || options.templateType\n\n  return {\n    content: [{\n      type: 'text' as const,\n      text: `✅ 使用预设模板创建uni-app项目成功！\n\n📁 项目路径: ${options.name}\n🎯 模板类型: ${options.templateType}\n📝 模板描述: ${templateInfo}\n\n🚀 项目已创建完成，接下来可以：\n1. cd ${options.name}\n2. 安装依赖: pnpm install\n3. 启动开发: pnpm dev\n4. 重要：访问 https://uni-helper.js.org/ 查看更多文档信息`,\n    }],\n  }\n}\n\n/**\n * 使用自定义模板创建项目\n */\nexport async function createCustom(options: CreateCustomOptions): Promise<CallToolResult> {\n  const { canCreate, message } = checkDirectory(options.name, options.force)\n\n  if (!canCreate) {\n    return {\n      content: [{\n        type: 'text',\n        text: message!,\n      }],\n    }\n  }\n\n  const args = buildCommandArgs(options)\n  const result = executeCreateCommand(args)\n\n  if (!result.success) {\n    return {\n      content: [{\n        type: 'text',\n        text: `创建项目失败: ${result.error}`,\n      }],\n    }\n  }\n\n  const features = []\n  if (options.needsTypeScript)\n    features.push('✅ TypeScript支持')\n  if (options.needsEslint)\n    features.push('✅ ESLint代码规范')\n  if (options.UIName) {\n    const uiInfo = UI.find(ui => ui.value === options.UIName)?.hint || options.UIName\n    features.push(`✅ UI组件库: ${uiInfo}`)\n  }\n  if (options.pluginList?.length) {\n    const pluginNames = options.pluginList.map((p) => {\n      const plugin = PLUGINS.find(plugin => plugin.value === p)\n      return plugin ? `${p} (${plugin.hint})` : p\n    })\n    features.push(`✅ 插件: ${pluginNames.join(', ')}`)\n  }\n  if (options.moduleList?.length) {\n    const moduleNames = options.moduleList.map((m) => {\n      const module = MODULES.find(mod => mod.value === m)\n      return module ? `${m} (${module.hint})` : m\n    })\n    features.push(`✅ 模块: ${moduleNames.join(', ')}`)\n  }\n\n  return {\n    content: [{\n      type: 'text',\n      text: `✅ 创建uni-app项目成功！\n\n📁 项目路径: ${options.name}\n${features.length ? `\\n🎯 已选择的功能:\\n${features.join('\\n')}` : ''}\n\n🚀 项目已创建完成，接下来可以：\n1. cd ${options.name}\n2. 安装依赖: pnpm install\n3. 启动开发: pnpm dev\n4. 重要：访问 https://uni-helper.js.org/ 查看更多文档信息`,\n    }],\n  }\n}\n"
  },
  {
    "path": "packages/mcp/src/index.ts",
    "content": "#!/usr/bin/env node\n\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'\nimport packageJson from './../package.json'\nimport { createCustom, createWithTemplate } from './handlers.js'\nimport { createCustomSchema, createWithTemplateSchema } from './schemas.js'\n\n/**\n * create-uni的MCP服务器\n * 为AI助手提供创建uni-app项目的能力\n */\nconst server = new McpServer({\n  name: packageJson.name,\n  title: packageJson.description,\n  version: packageJson.version,\n})\n\n/**\n * 使用预设模板创建uni-app项目\n * 通过选择预设模板快速创建uni-app项目，无需自定义配置\n */\nserver.registerTool(\n  'create-with-template',\n  {\n    title: '使用预设模板创建uni-app项目',\n    description: '通过选择预设模板快速创建uni-app项目，无需自定义配置。提供多种预设模板，包括vitesse、wot-starter、零售模板等，适合不同场景的快速启动。',\n    inputSchema: createWithTemplateSchema.shape,\n  },\n  async (input) => {\n    return await createWithTemplate(input)\n  },\n)\n\n/**\n * 使用自定义模板创建uni-app项目\n * 通过自定义配置创建uni-app项目，可自由选择插件、模块、UI库等\n */\nserver.registerTool(\n  'create-custom',\n  {\n    title: '使用自定义模板创建uni-app项目',\n    description: '通过自定义配置创建uni-app项目，可自由选择TypeScript、ESLint、插件、模块、UI库等。适合需要精细化配置的项目需求，提供完整的定制化能力。',\n    inputSchema: createCustomSchema.shape,\n  },\n  async (input) => {\n    return createCustom(input)\n  },\n)\n\n// 启动服务器\nconst transport = new StdioServerTransport()\nserver.connect(transport)\n"
  },
  {
    "path": "packages/mcp/src/schemas.ts",
    "content": "import { MODULES, PLUGINS, TEMPLATES, UI } from '@create-uni/config'\nimport { z } from 'zod'\nimport { getConfigValuesAsEnum, getTemplateValuesAsEnum, promptBuilder, templatePromptBuilder } from './utils'\n/**\n * 基于core包中的数据定义Zod schema\n * 为AI提供更好的理解和描述\n */\n\n// 模板类型schema\nexport const templateTypeSchema = z.enum(getTemplateValuesAsEnum(TEMPLATES))\n  .describe(templatePromptBuilder(TEMPLATES, '预设模板类型, 每个模板都有不同的特点'))\n\n// 插件类型schema\nexport const pluginListSchema = z.array(z.enum(getConfigValuesAsEnum(PLUGINS)))\n  .optional()\n  .default([])\n  .describe(promptBuilder(PLUGINS, '支持安装的插件列表, 每个插件提供特定功能'))\n\n// 模块类型schema\nexport const moduleListSchema = z.array(z.enum(getConfigValuesAsEnum(MODULES)))\n  .optional()\n  .default([])\n  .describe(promptBuilder(MODULES, '支持安装的模块列表, 每个模块提供特定功能'))\n\n// UI组件库类型schema\nexport const uiNameSchema = z.enum(getConfigValuesAsEnum(UI))\n  .optional()\n  .default(' ')\n  .describe(promptBuilder(UI, 'UI组件库名称, 选择合适的组件库加速开发'))\n\n// 基础创建参数schema\nexport const baseCreateSchema = {\n  name: z.string().describe('项目路径名称（将作为文件夹名称）').default('.'),\n  force: z.boolean().optional().describe('是否强制覆盖已存在的目录, 默认为false').default(false),\n}\n\n// 预设模板创建schema\nexport const createWithTemplateSchema = z.object({\n  ...baseCreateSchema,\n  templateType: templateTypeSchema,\n})\n\n// 自定义模板创建schema\nexport const createCustomSchema = z.object({\n  ...baseCreateSchema,\n  needsTypeScript: z.boolean().optional().describe('是否需要TypeScript支持, 提供类型安全和更好的开发体验').default(false),\n  pluginList: pluginListSchema,\n  moduleList: moduleListSchema,\n  UIName: uiNameSchema,\n  needsEslint: z.boolean().optional().describe('是否需要ESLint配置, 统一代码风格和质量').default(false),\n})\n"
  },
  {
    "path": "packages/mcp/src/types.ts",
    "content": "import type { MODULES, PLUGINS, UI } from '@create-uni/config/src'\n\n/**\n * 创建项目的基础选项\n */\nexport interface BaseCreateOptions {\n  name: string\n  force?: boolean\n}\n\n/**\n * 使用模板创建选项\n */\nexport interface CreateWithTemplateOptions extends BaseCreateOptions {\n  templateType: string\n}\n\n/**\n * 自定义创建选项\n */\nexport interface CreateCustomOptions extends BaseCreateOptions {\n  needsTypeScript?: boolean\n  pluginList?: typeof PLUGINS[number]['value'][]\n  moduleList?: typeof MODULES[number]['value'][]\n  UIName?: typeof UI[number]['value'] | ' '\n  needsEslint?: boolean\n}\n"
  },
  {
    "path": "packages/mcp/src/utils.ts",
    "content": "import type { Options } from '@create-uni/config'\nimport type { BaseTemplateListWithUrl, TemplateList } from '@create-uni/config/src/type'\n\n/**\n * 从配置里获取全部的value作为枚举列表\n * @template T - 具体的配置项类型，用于从常量中提取字面量类型\n * @returns 返回与输入数组顺序对应的值数组，包含具体的字面量类型\n */\nexport function getConfigValuesAsEnum<T extends readonly Options[]>(config: T) {\n  return config.map(item => item.value || ' ') as {\n    [K in keyof T]: T[K] extends { value: infer V }\n      ? V extends string\n        ? V\n        : ' '\n      : ' '\n  }\n}\n\n/**\n * AI提示词构建器\n * 用于组装各种配置项的AI提示词描述\n */\nexport function promptBuilder(\n  config: readonly Options[],\n  prefix: string,\n): string {\n  const descriptions = config.map((module) => {\n    const parts = module.value ? [`- ${module.value}: ${module.hint}`] : [`- \" \": 不安装`]\n\n    return parts.join(' ')\n  })\n\n  return `${prefix}: \\n${descriptions.join('\\n')}`\n}\n\n/**\n * 扁平化模板数据结构\n * 将包含分组的模板数据展开为单层数组\n */\nexport function flattenTemplateList(templates: TemplateList[]): BaseTemplateListWithUrl[] {\n  const result: BaseTemplateListWithUrl[] = []\n\n  for (const template of templates) {\n    if ('list' in template && template.list) {\n      // 处理有子列表的分组模板\n      result.push(...template.list)\n    }\n    else if ('url' in template) {\n      // 处理单个模板（没有子列表）\n      result.push(template as BaseTemplateListWithUrl)\n    }\n  }\n\n  return result\n}\n\n/**\n * 从模板配置中获取所有的value作为枚举列表\n */\nexport function getTemplateValuesAsEnum(templates: TemplateList[]): [string, ...string[]] {\n  const flattened = flattenTemplateList(templates)\n  return flattened.map(item => item.value) as [string, ...string[]]\n}\n\n/**\n * 模板AI提示词构建器\n * 用于组装模板选项的AI提示词描述\n */\nexport function templatePromptBuilder(\n  templates: TemplateList[],\n  prefix: string,\n): string {\n  const flattened = flattenTemplateList(templates)\n  const descriptions = flattened.map((template) => {\n    return `- ${template.value}: ${template.description || '暂无描述'}`\n  })\n\n  return `${prefix}: \\n${descriptions.join('\\n')}`\n}\n"
  },
  {
    "path": "packages/mcp/test/promptBuilder.test.ts",
    "content": "import { MODULES, UI } from '@create-uni/config'\nimport templates from '@create-uni/config/src/template.data'\nimport { expect, it } from 'vitest'\nimport { getConfigValuesAsEnum, getTemplateValuesAsEnum, promptBuilder, templatePromptBuilder } from '../src/utils'\n\nit('promptBuilder', () => {\n  expect(promptBuilder(MODULES, '需要安装的模块列表，增强应用功能')).toMatchInlineSnapshot(`\n    \"需要安装的模块列表，增强应用功能: \n    - pinia: 符合直觉的 Vue.js 状态管理库\n    - unocss: 即时按需的原子级 CSS 引擎\n    - uniNetwork: 为 uni-app 打造的基于 Promise 的网络请求库\n    - uniUse: uni-app 组合式工具集\n    - uniPromises: uni-app promise 化的 API\n    - uniEcharts: 适用于 uni-app 的 Apache ECharts 组件\n    - zPaging: 高性能、全平台兼容的 uni-app 分页组件\"\n  `)\n\n  expect(promptBuilder(UI, '是否需要安装UI组件库')).toMatchInlineSnapshot(`\n    \"是否需要安装UI组件库: \n    - \" \": 不安装\n    - uni: UniApp官方组件库\n    - wot: 高颜值、轻量化的uni-app组件库\n    - tdesign: Tencent Design 组件库的 uni-app 版本\n    - uview-pro: 全面支持 Vue3.0、TypeScript 的 uni-app 生态框架\n    - nut: 京东风格的轻量级移动端组件库\n    - uv: 多平台快速开发的UI框架\n    - ano: 轻量级、漂亮、快速的 UnoCSS 组件库\"\n  `)\n})\n\nit('getConfigValuesAsEnum', () => {\n  expect(getConfigValuesAsEnum(UI)).toMatchInlineSnapshot(`\n    [\n      \" \",\n      \"uni\",\n      \"wot\",\n      \"tdesign\",\n      \"uview-pro\",\n      \"nut\",\n      \"uv\",\n      \"ano\",\n    ]\n  `)\n})\n\nit('templatePromptBuilder', () => {\n  expect(templatePromptBuilder(templates, '请选择项目模板')).toMatchInlineSnapshot(`\n    \"请选择项目模板: \n    - vitesse: 由Uni Helper维护的快速启动模板\n    - wot-starter: 由Wot UI提供的基于 vitesse-uni-app 的快速启动模板\n    - wot-starter-retail: 基于Wot UI的 uni-app 零售行业模板\n    - uview-pro-starter: 由 uView Pro 提供的基于 vitesse-uni-app 的快速启动模板\n    - uview-pro-demo: 由 uView Pro 提供的完整组件演示模板\n    - unisave: 拥抱 web 开发，拯救uniapp。适配所有 (app、mp、web) 平台\n    - tmui32: 优质 Vue3 TS Pinia Vite 跨端组件库模板\"\n  `)\n})\n\nit('getTemplateValuesAsEnum', () => {\n  expect(getTemplateValuesAsEnum(templates)).toMatchInlineSnapshot(`\n    [\n      \"vitesse\",\n      \"wot-starter\",\n      \"wot-starter-retail\",\n      \"uview-pro-starter\",\n      \"uview-pro-demo\",\n      \"unisave\",\n      \"tmui32\",\n    ]\n  `)\n})\n"
  },
  {
    "path": "packages/mcp/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ES2022\",\n    \"rootDir\": \"./src\",\n    \"module\": \"esnext\",\n    \"moduleResolution\": \"node\",\n    \"resolveJsonModule\": true,\n    \"strict\": true,\n    \"outDir\": \"./build\",\n    \"esModuleInterop\": true,\n    \"forceConsistentCasingInFileNames\": true,\n    \"skipLibCheck\": true\n  },\n  \"include\": [\"src/**/*\"],\n  \"exclude\": [\"node_modules\"]\n}\n"
  },
  {
    "path": "packages/mcp/tsup.config.ts",
    "content": "import { defineConfig } from 'tsup'\n\nexport default ({ watch }: { watch: boolean }) => (\n  defineConfig({\n    entry: {\n      outfile: 'src/index.ts',\n    },\n    format: 'cjs',\n    platform: 'node',\n    target: 'node14',\n    minify: watch ? false : 'terser',\n    clean: true,\n  })\n)\n"
  },
  {
    "path": "packages/shared/package.json",
    "content": "{\n  \"name\": \"@create-uni/shared\",\n  \"type\": \"module\",\n  \"version\": \"0.0.1\",\n  \"private\": true,\n  \"packageManager\": \"pnpm@9.9.0\",\n  \"description\": \"create-uni 公用方法\",\n  \"author\": \"FliPPeDround <flippedround@qq.com>\",\n  \"license\": \"MIT\",\n  \"funding\": \"https://afdian.com/a/flippedround\",\n  \"homepage\": \"https://github.com/uni-helper/create-uni#readme\",\n  \"repository\": {\n    \"directory\": \"packages/shared\",\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/uni-helper/create-uni.git\"\n  },\n  \"bugs\": \"https://github.com/uni-helper/create-uni/issues\",\n  \"exports\": {\n    \".\": \"./src/index.ts\",\n    \"./*\": \"./*\"\n  },\n  \"main\": \"./src/index.ts\",\n  \"typesVersions\": {\n    \"*\": {\n      \"*\": [\n        \"./*\"\n      ]\n    }\n  },\n  \"files\": [\n    \"src\"\n  ],\n  \"dependencies\": {\n    \"kolorist\": \"^1.8.0\"\n  }\n}\n"
  },
  {
    "path": "packages/shared/src/canSkipEmptying.ts",
    "content": "import { existsSync, readdirSync } from 'node:fs'\n\nexport function canSkipEmptying(dir: string) {\n  if (!existsSync(dir))\n    return true\n\n  const files = readdirSync(dir)\n  if (files.length === 0)\n    return true\n\n  if (files.length === 1 && files[0] === '.git')\n    return true\n\n  return false\n}\n"
  },
  {
    "path": "packages/shared/src/generateBanner.ts",
    "content": "import process from 'node:process'\nimport { bold, lightCyan } from 'kolorist'\n\nexport function generateBanner(text: string) {\n  console.log()\n  // 检查是否在支持颜色的终端中运行\n  const supportsColor = () => {\n    if (!process.stdout.isTTY)\n      return false\n    const colorDepth = process.stdout.getColorDepth()\n    const colorterm = process.env.COLORTERM\n    return colorDepth > 8 || colorterm === 'truecolor' || colorterm === '24bit'\n  }\n\n  if (!supportsColor())\n    return lightCyan(` ${text} `)\n\n  let colorText = ''\n\n  const startColor = { r: 0x3B, g: 0xD1, b: 0x91 }\n  const endColor = { r: 0x2B, g: 0x4C, b: 0xEE }\n\n  for (let i = 0; i < text.length; i++) {\n    const ratio = i / (text.length - 1)\n    const red = Math.round(startColor.r + (endColor.r - startColor.r) * ratio)\n    const green = Math.round(startColor.g + (endColor.g - startColor.g) * ratio)\n    const blue = Math.round(startColor.b + (endColor.b - startColor.b) * ratio)\n    colorText += bold(`\\x1B[38;2;${red};${green};${blue}m${text[i]}\\x1B[0m`)\n  }\n\n  return colorText\n}\n"
  },
  {
    "path": "packages/shared/src/index.ts",
    "content": "export * from './canSkipEmptying'\nexport * from './generateBanner'\nexport * from './ora'\n"
  },
  {
    "path": "packages/shared/src/ora.ts",
    "content": "import process from 'node:process'\nimport { green, red } from 'kolorist'\n\nclass Ora {\n  private message: string\n  private interval: NodeJS.Timeout | null\n  private frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏']\n  private cross = '✖'\n  private tick = '✔'\n\n  constructor(message: string) {\n    this.message = message\n    this.interval = null\n  }\n\n  private setFinishMessage(newMessage: string): string {\n    return newMessage + ' '.repeat(this.message.length - newMessage.length)\n  }\n\n  start(): Ora {\n    let i = 0\n    process.stdout.write('\\r' + `${green(this.frames[i % 9])} ${this.message}`)\n    this.interval = setInterval(() => {\n      process.stdout.write('\\r' + `${green(this.frames[i % 9])} ${this.message}`)\n      i++\n    }, 100)\n    return this\n  }\n\n  fail(message: string): void {\n    if (!this.interval)\n      return\n    clearInterval(this.interval)\n    process.stdout.write('\\r' + `${red(this.cross)} ${this.setFinishMessage(message)}\\n`)\n  }\n\n  succeed(message: string): void {\n    if (!this.interval)\n      return\n    clearInterval(this.interval)\n    process.stdout.write('\\r' + `${green(this.tick)} ${this.setFinishMessage(message)}\\n`)\n  }\n\n  finish(): void {\n    if (!this.interval)\n      return\n    clearInterval(this.interval)\n    process.stdout.write('')\n  }\n}\n\nexport function ora(message: string) {\n  return new Ora(message)\n}\n"
  },
  {
    "path": "packages/ui/.gitignore",
    "content": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\npnpm-debug.log*\nlerna-debug.log*\n\nnode_modules\ndist\ndist-ssr\n*.local\n\n# Editor directories and files\n.vscode/*\n!.vscode/extensions.json\n.idea\n.DS_Store\n*.suo\n*.ntvs*\n*.njsproj\n*.sln\n*.sw?\n"
  },
  {
    "path": "packages/ui/components.json",
    "content": "{\n  \"$schema\": \"https://ui.shadcn.com/schema.json\",\n  \"style\": \"new-york\",\n  \"rsc\": false,\n  \"tsx\": true,\n  \"tailwind\": {\n    \"config\": \"tailwind.config.js\",\n    \"css\": \"src/style.css\",\n    \"baseColor\": \"zinc\",\n    \"cssVariables\": true,\n    \"prefix\": \"\"\n  },\n  \"aliases\": {\n    \"components\": \"@/components\",\n    \"utils\": \"@/lib/utils\",\n    \"ui\": \"@/components/ui\",\n    \"lib\": \"@/lib\",\n    \"hooks\": \"@/hooks\"\n  },\n  \"iconLibrary\": \"lucide\"\n}\n"
  },
  {
    "path": "packages/ui/index.html",
    "content": "<html>\n  <body>\n    <div id=\"app\"></div>\n\t\t<script>\n      ;(function () {\n        const prefersDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches\n        const setting = localStorage.getItem('color-schema') || 'auto'\n        if (setting === 'dark' || (prefersDark && setting !== 'light'))\n          document.documentElement.classList.toggle('dark', true)\n      })()\n    </script>\n    <script type=\"module\" src=\"./src/index.tsx\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "packages/ui/package.json",
    "content": "{\n  \"name\": \"@create-uni/ui\",\n  \"type\": \"module\",\n  \"private\": true,\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"@radix-ui/react-checkbox\": \"^1.1.3\",\n    \"@radix-ui/react-context-menu\": \"^2.2.4\",\n    \"@radix-ui/react-dialog\": \"^1.1.4\",\n    \"@radix-ui/react-dropdown-menu\": \"^2.1.4\",\n    \"@radix-ui/react-label\": \"^2.1.1\",\n    \"@radix-ui/react-popover\": \"^1.1.4\",\n    \"@radix-ui/react-radio-group\": \"^1.2.2\",\n    \"@radix-ui/react-select\": \"^2.1.4\",\n    \"@radix-ui/react-slot\": \"^1.1.1\",\n    \"ansi-to-react\": \"^6.1.6\",\n    \"class-variance-authority\": \"^0.7.1\",\n    \"clsx\": \"^2.1.1\",\n    \"cmdk\": \"1.0.0\",\n    \"lucide-react\": \"^0.469.0\",\n    \"preact\": \"^10.25.3\",\n    \"tailwind-merge\": \"^2.6.0\",\n    \"tailwindcss-animate\": \"^1.0.7\",\n    \"vaul\": \"^1.1.2\"\n  },\n  \"devDependencies\": {\n    \"@create-uni/config\": \"workspace:*\",\n    \"@preact/preset-vite\": \"^2.9.3\",\n    \"autoprefixer\": \"^10.4.20\",\n    \"postcss\": \"^8.4.49\",\n    \"tailwindcss\": \"^3.4.17\",\n    \"typescript\": \"^5.5.4\",\n    \"vite\": \"^6.0.4\",\n    \"vite-plugin-singlefile\": \"^2.1.0\"\n  }\n}\n"
  },
  {
    "path": "packages/ui/postcss.config.js",
    "content": "export default {\n  plugins: {\n    tailwindcss: {},\n    autoprefixer: {},\n  },\n}\n"
  },
  {
    "path": "packages/ui/src/components/UICheck.tsx",
    "content": "import {\n  DrawerDescription,\n  DrawerHeader,\n  DrawerTitle,\n} from '@/components/ui/drawer'\n\nimport {\n  Select,\n  SelectContent,\n  SelectItem,\n  SelectTrigger,\n  SelectValue,\n} from '@/components/ui/select'\nimport { USER_EVENT } from '@/constants/USER_EVENT'\nimport { BookText, Github } from 'lucide-react'\n\ninterface TemplateItemProps {\n  item: typeof window.create_uni_data.ui[number]\n}\n\nfunction UIItem({ item }: TemplateItemProps) {\n  return (\n    <SelectItem\n      value={item.value}\n      content={(\n        <div className=\"mx-auto w-full max-w-sm items-start\">\n          <DrawerHeader className=\"border-b border-dashed border-zinc-500/50 mx-2\">\n            <DrawerTitle>{item.name}</DrawerTitle>\n            <DrawerDescription>\n              {item.hint}\n            </DrawerDescription>\n          </DrawerHeader>\n          <div className=\"flex justify-center text-2xl mt-4 space-x-3 \">\n            {item.github && (\n              <Github\n                onClick={() => window.ipc.postMessage(`${USER_EVENT.OPEN}|${item.github}`)}\n                className=\"cursor-pointer hover:-translate-y-0.5 transition-transform duration-200\"\n                stroke=\"#888\"\n              />\n            )}\n            {\n              item.website && (\n                <BookText\n                  onClick={() => window.ipc.postMessage(`${USER_EVENT.OPEN}|${item.website}`)}\n                  className=\"cursor-pointer hover:-translate-y-0.5 transition-transform duration-20\"\n                  stroke=\"#888\"\n                />\n              )\n            }\n          </div>\n        </div>\n      )}\n    >\n      {item.name}\n    </SelectItem>\n  )\n}\n\ninterface OptionCheckProps {\n  value?: string\n  options: typeof window.create_uni_data.plugin\n  onChange: (value: string) => void\n}\nexport function UICheck({ value, options, onChange }: OptionCheckProps) {\n  return (\n    <Select onValueChange={onChange} value={value}>\n      <SelectTrigger\n        className=\"w-full bg-zinc-50 dark:bg-zinc-800 border-zinc-300 dark:border-zinc-700 focus:border-zinc-500 dark:focus:border-zinc-400 focus:ring-zinc-500 dark:focus:ring-zinc-400\"\n      >\n        <SelectValue\n          placeholder=\"不需要组件库\"\n        />\n      </SelectTrigger>\n      <SelectContent>\n        {\n          options.map((item) => {\n            if (item.value) {\n              return <UIItem item={item} />\n            }\n            else {\n              return <SelectItem value={item.value}>{item.name}</SelectItem>\n            }\n          },\n          )\n        }\n      </SelectContent>\n    </Select>\n  )\n}\n"
  },
  {
    "path": "packages/ui/src/components/footer/index.tsx",
    "content": "import { Button } from '@/components/ui/button'\nimport { USER_EVENT } from '@/constants/USER_EVENT'\nimport { Moon, Sun } from 'lucide-react'\nimport { useEffect, useState } from 'preact/hooks'\n\nexport function Footer() {\n  const [darkMode, setDarkMode] = useState(document.documentElement.classList.contains('dark'))\n\n  useEffect(() => {\n    if (darkMode) {\n      document.documentElement.classList.add('dark')\n    }\n    else {\n      document.documentElement.classList.remove('dark')\n    }\n  }, [darkMode])\n\n  const toggleDarkMode = () => {\n    setDarkMode(!darkMode)\n  }\n\n  return (\n    <footer className=\"mt-auto p-4 bg-zinc-100 dark:bg-zinc-800 text-zinc-600 dark:text-zinc-400 text-xs rounded-t-xl\">\n      <div className=\"flex justify-between items-center\">\n        <div class=\"italic\">\n          <p>\n            © 2025 Design by\n            {' '}\n            <span\n              className=\"hover:underline whitespace-pre cursor-pointer\"\n              onClick={() => window.ipc.postMessage(`${USER_EVENT.OPEN}|https://github.com/FliPPeDround`)}\n            >\n              FliPPeDround\n            </span>\n            .\n          </p>\n          <span\n            className=\"text-zinc-400/70 hover:underline whitespace-pre cursor-pointer\"\n            onClick={() => window.ipc.postMessage(`${USER_EVENT.OPEN}|https://github.com/uni-helper/create-uni`)}\n          >\n            MIT License\n          </span>\n        </div>\n\n        <Button\n          onClick={toggleDarkMode}\n          variant=\"outline\"\n          size=\"icon\"\n          className=\"w-8 h-8 rounded-full\"\n        >\n          {darkMode ? <Sun className=\"h-4 w-4\" /> : <Moon className=\"h-4 w-4\" />}\n        </Button>\n      </div>\n    </footer>\n  )\n}\n"
  },
  {
    "path": "packages/ui/src/components/header/index.tsx",
    "content": "import { USER_EVENT } from '@/constants/USER_EVENT'\n\nexport function Header() {\n  return (\n    <div\n      className=\"flex items-start p-6 select-none\"\n      onMouseMove={() => window.ipc.postMessage(USER_EVENT.DRAG_WINDOW)}\n      style={{ 'app-region': 'drag' }}\n    >\n      <h1 className=\"text-3xl font-bold text-zinc-800 dark:text-zinc-200\">Uni Creator</h1>\n      <span className=\"ml-2 px-2 py-1 text-xs font-semibold bg-zinc-200 dark:bg-zinc-700 text-zinc-700 dark:text-zinc-300 rounded-md\">Beta</span>\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/ui/src/components/icons/demo.tsx",
    "content": "import type { SVGProps } from 'preact/compat'\n\nexport function Demo(props: SVGProps<SVGSVGElement>) {\n  return (\n    <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"1em\" height=\"1em\" viewBox=\"0 0 32 32\" {...props}>\n      <path fill=\"#888888\" d=\"M20 2v12l10-6z\"></path>\n      <path fill=\"#888888\" d=\"M28 14v8H4V6h10V4H4a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h8v4H8v2h16v-2h-4v-4h8a2 2 0 0 0 2-2v-8zM18 28h-4v-4h4z\"></path>\n    </svg>\n  )\n}\n"
  },
  {
    "path": "packages/ui/src/components/icons/eslint.tsx",
    "content": "import type { SVGProps } from 'preact/compat'\n\nexport function Eslint(props: SVGProps<SVGSVGElement>) {\n  return (\n    <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"1em\" height=\"1em\" viewBox=\"0 0 24 24\" {...props}><path fill=\"currentColor\" d=\"m7.95 9.55l3.89-2.25c.1-.05.22-.05.32 0l3.89 2.25c.1.06.16.16.16.27v4.5c0 .11-.06.21-.16.27l-3.89 2.25a.36.36 0 0 1-.32 0l-3.89-2.25a.32.32 0 0 1-.16-.27v-4.5c0-.11.06-.21.16-.27m14.17 2.05c.17.29.17.63 0 .93l-4.65 8.03c-.17.3-.47.44-.82.44h-9.3c-.35 0-.65-.15-.82-.44l-4.65-8.03a.95.95 0 0 1 0-.95L6.53 3.5c.17-.28.47-.5.82-.5h9.3c.35 0 .65.22.82.5zm-3.85 3.9V8.65c0-.12-.07-.23-.18-.29l-5.93-3.41a.33.33 0 0 0-.33 0L5.91 8.36c-.11.06-.18.17-.18.29v6.85c0 .11.07.22.18.28l5.93 3.41c.1.06.23.06.33 0l5.92-3.41a.33.33 0 0 0 .18-.28\"></path></svg>\n  )\n}\n"
  },
  {
    "path": "packages/ui/src/components/icons/gitee.tsx",
    "content": "import type { SVGProps } from 'preact/compat'\n\nexport function Gitee(props: SVGProps<SVGSVGElement>) {\n  return (\n    <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"1em\" height=\"1em\" viewBox=\"0 0 24 24\" {...props}><path fill=\"#888888\" d=\"M11.984 0A12 12 0 0 0 0 12a12 12 0 0 0 12 12a12 12 0 0 0 12-12A12 12 0 0 0 12 0zm6.09 5.333c.328 0 .593.266.592.593v1.482a.594.594 0 0 1-.593.592H9.777c-.982 0-1.778.796-1.778 1.778v5.63c0 .327.266.592.593.592h5.63c.982 0 1.778-.796 1.778-1.778v-.296a.593.593 0 0 0-.592-.593h-4.15a.59.59 0 0 1-.592-.592v-1.482a.593.593 0 0 1 .593-.592h6.815c.327 0 .593.265.593.592v3.408a4 4 0 0 1-4 4H5.926a.593.593 0 0 1-.593-.593V9.778a4.444 4.444 0 0 1 4.445-4.444h8.296Z\"></path></svg>\n  )\n}\n"
  },
  {
    "path": "packages/ui/src/components/icons/github.tsx",
    "content": "import type { SVGProps } from 'preact/compat'\n\nexport function Github(props: SVGProps<SVGSVGElement>) {\n  return (\n    <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"1em\" height=\"1em\" viewBox=\"0 0 24 24\" {...props}><path fill=\"#888888\" d=\"M12 .297c-6.63 0-12 5.373-12 12c0 5.303 3.438 9.8 8.205 11.385c.6.113.82-.258.82-.577c0-.285-.01-1.04-.015-2.04c-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729c1.205.084 1.838 1.236 1.838 1.236c1.07 1.835 2.809 1.305 3.495.998c.108-.776.417-1.305.76-1.605c-2.665-.3-5.466-1.332-5.466-5.93c0-1.31.465-2.38 1.235-3.22c-.135-.303-.54-1.523.105-3.176c0 0 1.005-.322 3.3 1.23c.96-.267 1.98-.399 3-.405c1.02.006 2.04.138 3 .405c2.28-1.552 3.285-1.23 3.285-1.23c.645 1.653.24 2.873.12 3.176c.765.84 1.23 1.91 1.23 3.22c0 4.61-2.805 5.625-5.475 5.92c.42.36.81 1.096.81 2.22c0 1.606-.015 2.896-.015 3.286c0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12\"></path></svg>\n  )\n}\n"
  },
  {
    "path": "packages/ui/src/components/icons/guide.tsx",
    "content": "import type { SVGProps } from 'preact/compat'\n\nexport function Guide(props: SVGProps<SVGSVGElement>) {\n  return (\n    <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"1em\" height=\"1em\" viewBox=\"0 0 24 24\" {...props}><path fill=\"#888888\" d=\"M5 21q-.825 0-1.412-.587T3 19V5q0-.825.588-1.412T5 3h14q.825 0 1.413.588T21 5v14q0 .825-.587 1.413T19 21zM5 5v14h14V5h-2v6.125q0 .3-.25.438t-.5-.013l-1.225-.75q-.25-.15-.525-.15t-.525.15l-1.225.75q-.25.15-.5.013t-.25-.438V5zm0 14V5z\"></path></svg>\n  )\n}\n"
  },
  {
    "path": "packages/ui/src/components/icons/rename.tsx",
    "content": "import type { SVGProps } from 'preact/compat'\n\nexport function Rename(props: SVGProps<SVGSVGElement>) {\n  return (\n    <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"1em\" height=\"1em\" viewBox=\"0 0 16 16\" {...props}><path fill=\"currentColor\" d=\"M6.5 2a.5.5 0 0 0 0 1h1v10h-1a.5.5 0 0 0 0 1h3a.5.5 0 0 0 0-1h-1V3h1a.5.5 0 0 0 0-1zM4 4h2.5v1H4a1 1 0 0 0-1 1v3.997a1 1 0 0 0 1 1h2.5v1H4a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2m8 6.997H9.5v1H12a2 2 0 0 0 2-2V6a2 2 0 0 0-2-2H9.5v1H12a1 1 0 0 1 1 1v3.997a1 1 0 0 1-1 1\"></path></svg>\n  )\n}\n"
  },
  {
    "path": "packages/ui/src/components/icons/template.tsx",
    "content": "import type { SVGProps } from 'preact/compat'\n\nexport function Template(props: SVGProps<SVGSVGElement>) {\n  return (\n    <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"1em\" height=\"1em\" viewBox=\"0 0 24 24\" {...props}><path fill=\"none\" stroke=\"currentColor\" strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth=\"2\" d=\"M4 5a1 1 0 0 1 1-1h14a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1zm0 8a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v6a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1zm10-1h6m-6 4h6m-6 4h6\"></path></svg>\n  )\n}\n"
  },
  {
    "path": "packages/ui/src/components/icons/typeScript.tsx",
    "content": "import type { SVGProps } from 'preact/compat'\n\nexport function Typescript(props: SVGProps<SVGSVGElement>) {\n  return (\n    <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"1em\" height=\"1em\" viewBox=\"0 0 24 24\" {...props}>\n      <g fill=\"none\" stroke=\"currentColor\" strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth=\"2\">\n        <path d=\"M15 17.5c.32.32.754.5 1.207.5h.543c.69 0 1.25-.56 1.25-1.25v-.25a1.5 1.5 0 0 0-1.5-1.5a1.5 1.5 0 0 1-1.5-1.5v-.25c0-.69.56-1.25 1.25-1.25h.543c.453 0 .887.18 1.207.5M9 12h4m-2 0v6\"></path>\n        <path d=\"M21 19V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2\"></path>\n      </g>\n    </svg>\n  )\n}\n"
  },
  {
    "path": "packages/ui/src/components/icons/vitepress.tsx",
    "content": "import type { SVGProps } from 'preact/compat'\n\nexport function Vitepress(props: SVGProps<SVGSVGElement>) {\n  return (\n    <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"1em\" height=\"1em\" viewBox=\"0 0 24 24\" {...props}><path fill=\"#888888\" d=\"M17.029.001a2 2 0 0 0-.187.018L4.085 1.833A1.86 1.86 0 0 0 2.518 3.94l2.56 18.457a1.846 1.846 0 0 0 2.08 1.586l12.757-1.816a1.86 1.86 0 0 0 1.567-2.106l-2.56-18.455A1.85 1.85 0 0 0 17.029 0m.127.932a.926.926 0 0 1 .853.8l2.56 18.458a.93.93 0 0 1-.782 1.053L7.03 23.058a.92.92 0 0 1-1.04-.793L3.43 3.81a.93.93 0 0 1 .783-1.053L16.97.941a1 1 0 0 1 .186-.008m-3.644 5.354L9.967 7.521a.136.136 0 0 0-.09.141l.318 3.87c.008.09.1.149.184.116l.982-.378a.136.136 0 0 1 .184.136l-.09 1.54c-.006.103.1.176.193.132l.6-.281c.093-.044.198.03.192.135l-.147 2.418c-.01.15.195.203.258.066l.04-.092L14.716 8.9c.035-.107-.066-.21-.172-.173l-1.018.351c-.095.033-.191-.049-.177-.15l.343-2.49a.137.137 0 0 0-.142-.157c-.016 0-.042.009-.037.006zm2.822.799a.3.3 0 0 0-.08.014L14 7.85l-.076.56l.455-.156a.636.636 0 0 1 .81.803l-2.13 6.449l-.053.117a.64.64 0 0 1-.738.352a.64.64 0 0 1-.473-.657l.11-1.808a.638.638 0 0 1-.948-.594l.057-.976l-.454.175a.64.64 0 0 1-.863-.543L9.453 8.6l-3.062-.123c-.23-.01-.364.255-.223.44l6.29 8.23a.27.27 0 0 0 .468-.069l3.668-9.619a.275.275 0 0 0-.26-.373\"></path></svg>\n  )\n}\n"
  },
  {
    "path": "packages/ui/src/components/optionCheck.tsx",
    "content": "import { Drawer, DrawerClose, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerTitle, DrawerTrigger } from '@/components/ui/drawer'\nimport { USER_EVENT } from '@/constants/USER_EVENT'\nimport { BookText, Ellipsis, Github } from 'lucide-react'\nimport { Button } from './ui/button'\nimport { Checkbox } from './ui/checkbox'\nimport { Label } from './ui/label'\n\ninterface OptionCheckProps {\n  checkList: string[]\n  options: typeof window.create_uni_data.plugin\n  onChange: (value: string) => void\n}\n\nexport function OptionCheck({ checkList, options, onChange }: OptionCheckProps) {\n  return (\n\n    <div className=\"max-h-60 space-y-2\">\n      {options.map(plugin => (\n        <div key={plugin} className=\"flex items-center space-x-2\">\n          <Checkbox\n            id={plugin.value}\n            checked={checkList.includes(plugin.value)}\n            onCheckedChange={() => onChange(plugin.value)}\n            className=\"border-zinc-300 dark:border-zinc-700 text-zinc-600 dark:text-zinc-400\"\n          />\n          <Label htmlFor={plugin.value} className=\"text-zinc-600 dark:text-zinc-300 flex justify-between  items-center w-full\">\n            {plugin.name}\n            <Drawer>\n              <DrawerTrigger>\n                <Ellipsis\n                  className=\"cursor-pointer opacity-50 hover:opacity-100\"\n                />\n              </DrawerTrigger>\n              <DrawerContent>\n                <DrawerHeader className=\"border-b border-dashed border-zinc-500/50 mx-2\">\n                  <DrawerTitle>{plugin.name}</DrawerTitle>\n                  <DrawerDescription>\n                    {plugin.hint}\n                  </DrawerDescription>\n                </DrawerHeader>\n                <div className=\"flex justify-center text-2xl mt-4 space-x-3 \">\n                  <Github\n                    onClick={() => window.ipc.postMessage(`${USER_EVENT.OPEN}|${plugin.github}`)}\n                    className=\"cursor-pointer hover:-translate-y-0.5 transition-transform duration-200\"\n                    stroke=\"#888\"\n                  />\n                  {\n                    plugin.website && (\n                      <BookText\n                        onClick={() => window.ipc.postMessage(`${USER_EVENT.OPEN}|${plugin.website}`)}\n                        className=\"cursor-pointer hover:-translate-y-0.5 transition-transform duration-20\"\n                        stroke=\"#888\"\n                      />\n                    )\n                  }\n                </div>\n                <DrawerFooter>\n                  <DrawerClose asChild>\n                    <Button variant=\"outline\">Cancel</Button>\n                  </DrawerClose>\n                </DrawerFooter>\n              </DrawerContent>\n            </Drawer>\n          </Label>\n        </div>\n      ))}\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/ui/src/components/templateCheck.tsx",
    "content": "import {\n  DrawerDescription,\n  DrawerHeader,\n  DrawerTitle,\n} from '@/components/ui/drawer'\n\nimport {\n  Select,\n  SelectContent,\n  SelectGroup,\n  SelectItem,\n  SelectLabel,\n  SelectTrigger,\n  SelectValue,\n} from '@/components/ui/select'\nimport { USER_EVENT } from '@/constants/USER_EVENT'\n\nimport Ansi from 'ansi-to-react'\nimport { BookText, Github } from 'lucide-react'\nimport { Demo } from './icons/demo'\nimport { Gitee } from './icons/gitee'\n\ninterface TemplateItemProps {\n  item: typeof window.create_uni_data.templateList[number]\n}\n\nfunction TemplateItem({ item }: TemplateItemProps) {\n  return (\n    <SelectItem\n      value={item.value}\n      content={(\n        <div className=\"mx-auto w-full max-w-sm items-start\">\n          <DrawerHeader className=\"border-b border-dashed border-zinc-500/50 mx-2\">\n            <DrawerTitle>{item.label}</DrawerTitle>\n            <DrawerDescription>\n              <Ansi>\n                {item.description}\n              </Ansi>\n            </DrawerDescription>\n          </DrawerHeader>\n          <div className=\"flex justify-center text-2xl mt-4 space-x-3 \">\n            {\n              Object.keys(item.url).map((key) => {\n                if (key === 'github') {\n                  return (\n                    <Github\n                      onClick={() => window.ipc.postMessage(`${USER_EVENT.OPEN}|${item.url[key]}`)}\n                      className=\"cursor-pointer hover:-translate-y-0.5 transition-transform duration-200\"\n                      stroke=\"#888\"\n                    />\n                  )\n                }\n                if (key === 'gitee') {\n                  return (\n                    <Gitee\n                      onClick={() => window.ipc.postMessage(`${USER_EVENT.OPEN}|${item.url[key]}`)}\n                      class=\"cursor-pointer hover:-translate-y-0.5 transition-transform duration-20\"\n                    />\n                  )\n                }\n                else {\n                  return null\n                }\n              })\n            }\n            {\n              item.website && (\n                <BookText\n                  onClick={() => window.ipc.postMessage(`${USER_EVENT.OPEN}|${item.website}`)}\n                  className=\"cursor-pointer hover:-translate-y-0.5 transition-transform duration-20\"\n                  stroke=\"#888\"\n                />\n              )\n            }\n            {\n              item.playground && (\n                <Demo\n                  onClick={() => window.ipc.postMessage(`${USER_EVENT.OPEN}|${item.playground}`)}\n                  className=\"cursor-pointer hover:-translate-y-0.5 transition-transform duration-20\"\n                />\n              )\n            }\n          </div>\n        </div>\n      )}\n    >\n      {item.label}\n    </SelectItem>\n  )\n}\n\nconst templateList = window.create_uni_data.templateList\ntemplateList.unshift({\n  label: '自定义模板',\n  value: 'custom',\n} as TemplateItemProps['item'])\n\nexport function TemplateCheck({ useTemplate, onChange }: { useTemplate: string, onChange: (value: string) => void }) {\n  return (\n    <Select onValueChange={onChange} value={useTemplate}>\n      <SelectTrigger\n        className=\"w-full bg-zinc-50 dark:bg-zinc-800 border-zinc-300 dark:border-zinc-700 focus:border-zinc-500 dark:focus:border-zinc-400 focus:ring-zinc-500 dark:focus:ring-zinc-400\"\n      >\n        <SelectValue\n          placeholder=\"自定义模板\"\n        />\n      </SelectTrigger>\n      <SelectContent>\n        {\n          templateList.map((item) => {\n            if (item.list) {\n              return (\n                <SelectGroup className=\"border-b border-dashed border-zinc-500/50\">\n                  <SelectLabel>{item.label}</SelectLabel>\n                  {\n                    item.list.map((item) => {\n                      return <TemplateItem item={item} />\n                    })\n                  }\n                </SelectGroup>\n              )\n            }\n            else if (item.url) {\n              return <TemplateItem item={item} />\n            }\n            else {\n              return <SelectItem value={item.value}>{item.label}</SelectItem>\n            }\n          },\n          )\n        }\n      </SelectContent>\n    </Select>\n  )\n}\n"
  },
  {
    "path": "packages/ui/src/components/ui/badge.tsx",
    "content": "import { cn } from '@/lib/utils'\nimport { cva, type VariantProps } from 'class-variance-authority'\n\nimport * as React from 'react'\n\nconst badgeVariants = cva(\n  'inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2',\n  {\n    variants: {\n      variant: {\n        default:\n          'border-transparent bg-primary text-primary-foreground shadow hover:bg-primary/80',\n        secondary:\n          'border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80',\n        destructive:\n          'border-transparent bg-destructive text-destructive-foreground shadow hover:bg-destructive/80',\n        outline: 'text-foreground',\n      },\n    },\n    defaultVariants: {\n      variant: 'default',\n    },\n  },\n)\n\nexport interface BadgeProps\n  extends React.HTMLAttributes<HTMLDivElement>,\n  VariantProps<typeof badgeVariants> {}\n\nfunction Badge({ className, variant, ...props }: BadgeProps) {\n  return (\n    <div className={cn(badgeVariants({ variant }), className)} {...props} />\n  )\n}\n\nexport { Badge, badgeVariants }\n"
  },
  {
    "path": "packages/ui/src/components/ui/button.tsx",
    "content": "import { cn } from '@/lib/utils'\nimport { Slot } from '@radix-ui/react-slot'\nimport { cva, type VariantProps } from 'class-variance-authority'\n\nimport * as React from 'react'\n\nconst buttonVariants = cva(\n  'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0',\n  {\n    variants: {\n      variant: {\n        default:\n          'bg-primary text-primary-foreground shadow hover:bg-primary/90',\n        destructive:\n          'bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90',\n        outline:\n          'border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground',\n        secondary:\n          'bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80',\n        ghost: 'hover:bg-accent hover:text-accent-foreground',\n        link: 'text-primary underline-offset-4 hover:underline',\n      },\n      size: {\n        default: 'h-9 px-4 py-2',\n        sm: 'h-8 rounded-md px-3 text-xs',\n        lg: 'h-10 rounded-md px-8',\n        icon: 'h-9 w-9',\n      },\n    },\n    defaultVariants: {\n      variant: 'default',\n      size: 'default',\n    },\n  },\n)\n\nexport interface ButtonProps\n  extends React.ButtonHTMLAttributes<HTMLButtonElement>,\n  VariantProps<typeof buttonVariants> {\n  asChild?: boolean\n}\n\nconst Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n  ({ className, variant, size, asChild = false, ...props }, ref) => {\n    const Comp = asChild ? Slot : 'button'\n    return (\n      <Comp\n        className={cn(buttonVariants({ variant, size, className }))}\n        ref={ref}\n        {...props}\n      />\n    )\n  },\n)\nButton.displayName = 'Button'\n\nexport { Button, buttonVariants }\n"
  },
  {
    "path": "packages/ui/src/components/ui/checkbox.tsx",
    "content": "import { cn } from '@/lib/utils'\nimport * as CheckboxPrimitive from '@radix-ui/react-checkbox'\nimport { Check } from 'lucide-react'\n\nimport * as React from 'react'\n\nconst Checkbox = React.forwardRef<\n  React.ElementRef<typeof CheckboxPrimitive.Root>,\n  React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root>\n>(({ className, ...props }, ref) => (\n  <CheckboxPrimitive.Root\n    ref={ref}\n    className={cn(\n      'peer h-4 w-4 shrink-0 rounded-sm border border-primary shadow focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground',\n      className,\n    )}\n    {...props}\n  >\n    <CheckboxPrimitive.Indicator\n      className={cn('flex items-center justify-center text-current')}\n    >\n      <Check className=\"h-4 w-4\" />\n    </CheckboxPrimitive.Indicator>\n  </CheckboxPrimitive.Root>\n))\nCheckbox.displayName = CheckboxPrimitive.Root.displayName\n\nexport { Checkbox }\n"
  },
  {
    "path": "packages/ui/src/components/ui/context-menu.tsx",
    "content": "import { cn } from '@/lib/utils'\nimport * as ContextMenuPrimitive from '@radix-ui/react-context-menu'\nimport { Check, ChevronRight, Circle } from 'lucide-react'\n\nimport * as React from 'react'\n\nconst ContextMenu = ContextMenuPrimitive.Root\n\nconst ContextMenuTrigger = ContextMenuPrimitive.Trigger\n\nconst ContextMenuGroup = ContextMenuPrimitive.Group\n\nconst ContextMenuPortal = ContextMenuPrimitive.Portal\n\nconst ContextMenuSub = ContextMenuPrimitive.Sub\n\nconst ContextMenuRadioGroup = ContextMenuPrimitive.RadioGroup\n\nconst ContextMenuSubTrigger = React.forwardRef<\n  React.ElementRef<typeof ContextMenuPrimitive.SubTrigger>,\n  React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.SubTrigger> & {\n    inset?: boolean\n  }\n>(({ className, inset, children, ...props }, ref) => (\n  <ContextMenuPrimitive.SubTrigger\n    ref={ref}\n    className={cn(\n      'flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground',\n      inset && 'pl-8',\n      className,\n    )}\n    {...props}\n  >\n    {children}\n    <ChevronRight className=\"ml-auto h-4 w-4\" />\n  </ContextMenuPrimitive.SubTrigger>\n))\nContextMenuSubTrigger.displayName = ContextMenuPrimitive.SubTrigger.displayName\n\nconst ContextMenuSubContent = React.forwardRef<\n  React.ElementRef<typeof ContextMenuPrimitive.SubContent>,\n  React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.SubContent>\n>(({ className, ...props }, ref) => (\n  <ContextMenuPrimitive.SubContent\n    ref={ref}\n    className={cn(\n      'z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',\n      className,\n    )}\n    {...props}\n  />\n))\nContextMenuSubContent.displayName = ContextMenuPrimitive.SubContent.displayName\n\nconst ContextMenuContent = React.forwardRef<\n  React.ElementRef<typeof ContextMenuPrimitive.Content>,\n  React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Content>\n>(({ className, ...props }, ref) => (\n  <ContextMenuPrimitive.Portal>\n    <ContextMenuPrimitive.Content\n      ref={ref}\n      className={cn(\n        'z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',\n        className,\n      )}\n      {...props}\n    />\n  </ContextMenuPrimitive.Portal>\n))\nContextMenuContent.displayName = ContextMenuPrimitive.Content.displayName\n\nconst ContextMenuItem = React.forwardRef<\n  React.ElementRef<typeof ContextMenuPrimitive.Item>,\n  React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Item> & {\n    inset?: boolean\n  }\n>(({ className, inset, ...props }, ref) => (\n  <ContextMenuPrimitive.Item\n    ref={ref}\n    className={cn(\n      'relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',\n      inset && 'pl-8',\n      className,\n    )}\n    {...props}\n  />\n))\nContextMenuItem.displayName = ContextMenuPrimitive.Item.displayName\n\nconst ContextMenuCheckboxItem = React.forwardRef<\n  React.ElementRef<typeof ContextMenuPrimitive.CheckboxItem>,\n  React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.CheckboxItem>\n>(({ className, children, checked, ...props }, ref) => (\n  <ContextMenuPrimitive.CheckboxItem\n    ref={ref}\n    className={cn(\n      'relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',\n      className,\n    )}\n    checked={checked}\n    {...props}\n  >\n    <span className=\"absolute left-2 flex h-3.5 w-3.5 items-center justify-center\">\n      <ContextMenuPrimitive.ItemIndicator>\n        <Check className=\"h-4 w-4\" />\n      </ContextMenuPrimitive.ItemIndicator>\n    </span>\n    {children}\n  </ContextMenuPrimitive.CheckboxItem>\n))\nContextMenuCheckboxItem.displayName\n  = ContextMenuPrimitive.CheckboxItem.displayName\n\nconst ContextMenuRadioItem = React.forwardRef<\n  React.ElementRef<typeof ContextMenuPrimitive.RadioItem>,\n  React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.RadioItem>\n>(({ className, children, ...props }, ref) => (\n  <ContextMenuPrimitive.RadioItem\n    ref={ref}\n    className={cn(\n      'relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',\n      className,\n    )}\n    {...props}\n  >\n    <span className=\"absolute left-2 flex h-3.5 w-3.5 items-center justify-center\">\n      <ContextMenuPrimitive.ItemIndicator>\n        <Circle className=\"h-4 w-4 fill-current\" />\n      </ContextMenuPrimitive.ItemIndicator>\n    </span>\n    {children}\n  </ContextMenuPrimitive.RadioItem>\n))\nContextMenuRadioItem.displayName = ContextMenuPrimitive.RadioItem.displayName\n\nconst ContextMenuLabel = React.forwardRef<\n  React.ElementRef<typeof ContextMenuPrimitive.Label>,\n  React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Label> & {\n    inset?: boolean\n  }\n>(({ className, inset, ...props }, ref) => (\n  <ContextMenuPrimitive.Label\n    ref={ref}\n    className={cn(\n      'px-2 py-1.5 text-sm font-semibold text-foreground',\n      inset && 'pl-8',\n      className,\n    )}\n    {...props}\n  />\n))\nContextMenuLabel.displayName = ContextMenuPrimitive.Label.displayName\n\nconst ContextMenuSeparator = React.forwardRef<\n  React.ElementRef<typeof ContextMenuPrimitive.Separator>,\n  React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Separator>\n>(({ className, ...props }, ref) => (\n  <ContextMenuPrimitive.Separator\n    ref={ref}\n    className={cn('-mx-1 my-1 h-px bg-border', className)}\n    {...props}\n  />\n))\nContextMenuSeparator.displayName = ContextMenuPrimitive.Separator.displayName\n\nfunction ContextMenuShortcut({\n  className,\n  ...props\n}: React.HTMLAttributes<HTMLSpanElement>) {\n  return (\n    <span\n      className={cn(\n        'ml-auto text-xs tracking-widest text-muted-foreground',\n        className,\n      )}\n      {...props}\n    />\n  )\n}\nContextMenuShortcut.displayName = 'ContextMenuShortcut'\n\nexport {\n  ContextMenu,\n  ContextMenuCheckboxItem,\n  ContextMenuContent,\n  ContextMenuGroup,\n  ContextMenuItem,\n  ContextMenuLabel,\n  ContextMenuPortal,\n  ContextMenuRadioGroup,\n  ContextMenuRadioItem,\n  ContextMenuSeparator,\n  ContextMenuShortcut,\n  ContextMenuSub,\n  ContextMenuSubContent,\n  ContextMenuSubTrigger,\n  ContextMenuTrigger,\n}\n"
  },
  {
    "path": "packages/ui/src/components/ui/drawer.tsx",
    "content": "import { cn } from '@/lib/utils'\nimport * as React from 'react'\n\nimport { Drawer as DrawerPrimitive } from 'vaul'\n\nfunction Drawer({\n  shouldScaleBackground = true,\n  ...props\n}: React.ComponentProps<typeof DrawerPrimitive.Root>) {\n  return (\n    <DrawerPrimitive.Root\n      shouldScaleBackground={shouldScaleBackground}\n      {...props}\n    />\n  )\n}\nDrawer.displayName = 'Drawer'\n\nconst DrawerTrigger = DrawerPrimitive.Trigger\n\nconst DrawerPortal = DrawerPrimitive.Portal\n\nconst DrawerClose = DrawerPrimitive.Close\n\nconst DrawerOverlay = React.forwardRef<\n  React.ElementRef<typeof DrawerPrimitive.Overlay>,\n  React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Overlay>\n>(({ className, ...props }, ref) => (\n  <DrawerPrimitive.Overlay\n    ref={ref}\n    className={cn('fixed inset-0 z-50 bg-black/80', className)}\n    {...props}\n  />\n))\nDrawerOverlay.displayName = DrawerPrimitive.Overlay.displayName\n\nconst DrawerContent = React.forwardRef<\n  React.ElementRef<typeof DrawerPrimitive.Content>,\n  React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Content>\n>(({ className, children, ...props }, ref) => (\n  <DrawerPortal>\n    <DrawerOverlay />\n    <DrawerPrimitive.Content\n      ref={ref}\n      className={cn(\n        'fixed inset-x-0 bottom-0 z-50 mt-24 flex h-auto flex-col rounded-t-[10px] border bg-background',\n        className,\n      )}\n      {...props}\n    >\n      <div className=\"mx-auto mt-4 h-2 w-[100px] rounded-full bg-muted\" />\n      {children}\n    </DrawerPrimitive.Content>\n  </DrawerPortal>\n))\nDrawerContent.displayName = 'DrawerContent'\n\nfunction DrawerHeader({\n  className,\n  ...props\n}: React.HTMLAttributes<HTMLDivElement>) {\n  return (\n    <div\n      className={cn('grid gap-1.5 p-4 text-center sm:text-left', className)}\n      {...props}\n    />\n  )\n}\nDrawerHeader.displayName = 'DrawerHeader'\n\nfunction DrawerFooter({\n  className,\n  ...props\n}: React.HTMLAttributes<HTMLDivElement>) {\n  return (\n    <div\n      className={cn('mt-auto flex flex-col gap-2 p-4', className)}\n      {...props}\n    />\n  )\n}\nDrawerFooter.displayName = 'DrawerFooter'\n\nconst DrawerTitle = React.forwardRef<\n  React.ElementRef<typeof DrawerPrimitive.Title>,\n  React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Title>\n>(({ className, ...props }, ref) => (\n  <DrawerPrimitive.Title\n    ref={ref}\n    className={cn(\n      'text-lg font-semibold leading-none tracking-tight',\n      className,\n    )}\n    {...props}\n  />\n))\nDrawerTitle.displayName = DrawerPrimitive.Title.displayName\n\nconst DrawerDescription = React.forwardRef<\n  React.ElementRef<typeof DrawerPrimitive.Description>,\n  React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Description>\n>(({ className, ...props }, ref) => (\n  <DrawerPrimitive.Description\n    ref={ref}\n    className={cn('text-sm text-muted-foreground', className)}\n    {...props}\n  />\n))\nDrawerDescription.displayName = DrawerPrimitive.Description.displayName\n\nexport {\n  Drawer,\n  DrawerClose,\n  DrawerContent,\n  DrawerDescription,\n  DrawerFooter,\n  DrawerHeader,\n  DrawerOverlay,\n  DrawerPortal,\n  DrawerTitle,\n  DrawerTrigger,\n}\n"
  },
  {
    "path": "packages/ui/src/components/ui/input.tsx",
    "content": "import { cn } from '@/lib/utils'\n\nimport * as React from 'react'\n\nconst Input = React.forwardRef<HTMLInputElement, React.ComponentProps<'input'>>(\n  ({ className, type, ...props }, ref) => {\n    return (\n      <input\n        type={type}\n        className={cn(\n          'flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm',\n          className,\n        )}\n        ref={ref}\n        {...props}\n      />\n    )\n  },\n)\nInput.displayName = 'Input'\n\nexport { Input }\n"
  },
  {
    "path": "packages/ui/src/components/ui/label.tsx",
    "content": "import { cn } from '@/lib/utils'\nimport * as LabelPrimitive from '@radix-ui/react-label'\nimport { cva, type VariantProps } from 'class-variance-authority'\n\nimport * as React from 'react'\n\nconst labelVariants = cva(\n  'text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70',\n)\n\nconst Label = React.forwardRef<\n  React.ElementRef<typeof LabelPrimitive.Root>,\n  React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> &\n  VariantProps<typeof labelVariants>\n>(({ className, ...props }, ref) => (\n  <LabelPrimitive.Root\n    ref={ref}\n    className={cn(labelVariants(), className)}\n    {...props}\n  />\n))\nLabel.displayName = LabelPrimitive.Root.displayName\n\nexport { Label }\n"
  },
  {
    "path": "packages/ui/src/components/ui/radio-group.tsx",
    "content": "import { cn } from '@/lib/utils'\nimport * as RadioGroupPrimitive from '@radix-ui/react-radio-group'\nimport { Circle } from 'lucide-react'\n\nimport * as React from 'react'\n\nconst RadioGroup = React.forwardRef<\n  React.ElementRef<typeof RadioGroupPrimitive.Root>,\n  React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Root>\n>(({ className, ...props }, ref) => {\n  return (\n    <RadioGroupPrimitive.Root\n      className={cn('grid gap-2', className)}\n      {...props}\n      ref={ref}\n    />\n  )\n})\nRadioGroup.displayName = RadioGroupPrimitive.Root.displayName\n\nconst RadioGroupItem = React.forwardRef<\n  React.ElementRef<typeof RadioGroupPrimitive.Item>,\n  React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Item>\n>(({ className, ...props }, ref) => {\n  return (\n    <RadioGroupPrimitive.Item\n      ref={ref}\n      className={cn(\n        'aspect-square h-4 w-4 rounded-full border border-primary text-primary shadow focus:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50',\n        className,\n      )}\n      {...props}\n    >\n      <RadioGroupPrimitive.Indicator className=\"flex items-center justify-center\">\n        <Circle className=\"h-3.5 w-3.5 fill-primary\" />\n      </RadioGroupPrimitive.Indicator>\n    </RadioGroupPrimitive.Item>\n  )\n})\nRadioGroupItem.displayName = RadioGroupPrimitive.Item.displayName\n\nexport { RadioGroup, RadioGroupItem }\n"
  },
  {
    "path": "packages/ui/src/components/ui/select.tsx",
    "content": "import {\n  Drawer,\n  DrawerClose,\n  DrawerContent,\n  DrawerFooter,\n  DrawerTrigger,\n} from '@/components/ui/drawer'\n\nimport { cn } from '@/lib/utils'\nimport * as SelectPrimitive from '@radix-ui/react-select'\nimport { ChevronDown, ChevronUp, Ellipsis } from 'lucide-react'\nimport * as React from 'react'\nimport { Button } from './button'\n\nconst Select = SelectPrimitive.Root\n\nconst SelectGroup = SelectPrimitive.Group\n\nconst SelectValue = SelectPrimitive.Value\n\nconst SelectTrigger = React.forwardRef<\n  React.ElementRef<typeof SelectPrimitive.Trigger>,\n  React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>\n>(({ className, children, ...props }, ref) => (\n  <SelectPrimitive.Trigger\n    ref={ref}\n    className={cn(\n      'flex h-9 w-full items-center justify-between whitespace-nowrap rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-ring disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1',\n      className,\n    )}\n    {...props}\n  >\n    {children}\n    <SelectPrimitive.Icon asChild>\n      <ChevronDown className=\"h-4 w-4 opacity-50\" />\n    </SelectPrimitive.Icon>\n  </SelectPrimitive.Trigger>\n))\nSelectTrigger.displayName = SelectPrimitive.Trigger.displayName\n\nconst SelectScrollUpButton = React.forwardRef<\n  React.ElementRef<typeof SelectPrimitive.ScrollUpButton>,\n  React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollUpButton>\n>(({ className, ...props }, ref) => (\n  <SelectPrimitive.ScrollUpButton\n    ref={ref}\n    className={cn(\n      'flex cursor-default items-center justify-center py-1',\n      className,\n    )}\n    {...props}\n  >\n    <ChevronUp className=\"h-4 w-4\" />\n  </SelectPrimitive.ScrollUpButton>\n))\nSelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName\n\nconst SelectScrollDownButton = React.forwardRef<\n  React.ElementRef<typeof SelectPrimitive.ScrollDownButton>,\n  React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollDownButton>\n>(({ className, ...props }, ref) => (\n  <SelectPrimitive.ScrollDownButton\n    ref={ref}\n    className={cn(\n      'flex cursor-default items-center justify-center py-1',\n      className,\n    )}\n    {...props}\n  >\n    <ChevronDown className=\"h-4 w-4\" />\n  </SelectPrimitive.ScrollDownButton>\n))\nSelectScrollDownButton.displayName\n  = SelectPrimitive.ScrollDownButton.displayName\n\nconst SelectContent = React.forwardRef<\n  React.ElementRef<typeof SelectPrimitive.Content>,\n  React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>\n>(({ className, children, position = 'popper', ...props }, ref) => (\n  <SelectPrimitive.Portal>\n    <SelectPrimitive.Content\n      ref={ref}\n      className={cn(\n        'relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',\n        position === 'popper'\n        && 'data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1',\n        className,\n      )}\n      position={position}\n      {...props}\n    >\n      <SelectScrollUpButton />\n      <SelectPrimitive.Viewport\n        className={cn(\n          'p-1',\n          position === 'popper'\n          && 'h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]',\n        )}\n      >\n        {children}\n      </SelectPrimitive.Viewport>\n      <SelectScrollDownButton />\n    </SelectPrimitive.Content>\n  </SelectPrimitive.Portal>\n))\nSelectContent.displayName = SelectPrimitive.Content.displayName\n\nconst SelectLabel = React.forwardRef<\n  React.ElementRef<typeof SelectPrimitive.Label>,\n  React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label>\n>(({ className, ...props }, ref) => (\n  <SelectPrimitive.Label\n    ref={ref}\n    className={cn('px-2 py-1.5 text-sm font-medium opacity-50 border-b border-dashed !border-zinc-500', className)}\n    {...props}\n  />\n))\nSelectLabel.displayName = SelectPrimitive.Label.displayName\n\ninterface SelectItemProps extends React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item> {\n  content?: React.ReactNode\n}\n\nconst SelectItem = React.forwardRef<\n  React.ElementRef<typeof SelectPrimitive.Item>,\n  SelectItemProps\n>(({ className, children, content, ...props }, ref) => (\n  <div className=\"relative\">\n    <SelectPrimitive.Item\n      ref={ref}\n      className={cn(\n        'flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-2 pr-8 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',\n        className,\n      )}\n      {...props}\n    >\n      <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>\n\n      {/* <span className=\"absolute right-2 flex h-3.5 w-3.5 items-center justify-center\">\n        <SelectPrimitive.ItemIndicator>\n          <Check className=\"h-4 w-4\" />\n        </SelectPrimitive.ItemIndicator>\n      </span> */}\n    </SelectPrimitive.Item>\n\n    {content && (\n      <span className=\"absolute right-2 top-1/2 transform -translate-y-1/2 flex h-3.5 w-3.5 items-center justify-center\">\n        <Drawer>\n          <DrawerTrigger asChild>\n            <Ellipsis\n              className=\"cursor-pointer\"\n              onClick={e => e.stopPropagation()}\n            />\n          </DrawerTrigger>\n          <DrawerContent>\n            {content}\n            <DrawerFooter>\n              <DrawerClose asChild>\n                <Button variant=\"outline\">Cancel</Button>\n              </DrawerClose>\n            </DrawerFooter>\n          </DrawerContent>\n        </Drawer>\n      </span>\n    )}\n  </div>\n))\nSelectItem.displayName = SelectPrimitive.Item.displayName\n\nconst SelectSeparator = React.forwardRef<\n  React.ElementRef<typeof SelectPrimitive.Separator>,\n  React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>\n>(({ className, ...props }, ref) => (\n  <SelectPrimitive.Separator\n    ref={ref}\n    className={cn('-mx-1 my-1 h-px bg-muted', className)}\n    {...props}\n  />\n))\nSelectSeparator.displayName = SelectPrimitive.Separator.displayName\n\nexport {\n  Select,\n  SelectContent,\n  SelectGroup,\n  SelectItem,\n  SelectLabel,\n  SelectScrollDownButton,\n  SelectScrollUpButton,\n  SelectSeparator,\n  SelectTrigger,\n  SelectValue,\n}\n"
  },
  {
    "path": "packages/ui/src/constants/USER_EVENT.ts",
    "content": "export enum USER_EVENT {\n  /** 打开文件路径 */\n  FILE_PATH = 'file_path',\n  /** 关闭窗口 */\n  CLOSE = 'close',\n  /** 最小化 */\n  MINIMIZE = 'minimize',\n  /** 拖动窗口 */\n  DRAG_WINDOW = 'drag_window',\n  /** 打开浏览器 */\n  OPEN = 'open',\n  /** 安装 */\n  INSTALL = 'install',\n}\n"
  },
  {
    "path": "packages/ui/src/index.tsx",
    "content": "import {\n  ContextMenu,\n  ContextMenuContent,\n  ContextMenuItem,\n  ContextMenuSeparator,\n  ContextMenuTrigger,\n} from '@/components/ui/context-menu'\nimport CLIInterface from '@/page/index'\nimport { render } from 'preact'\nimport { Footer } from './components/footer'\nimport { Header } from './components/header'\nimport { USER_EVENT } from './constants/USER_EVENT'\nimport './style.css'\n\nexport function App() {\n  return (\n    <ContextMenu>\n      <ContextMenuTrigger>\n        <div class=\"bg-white dark:bg-zinc-900 text-zinc-900 dark:text-zinc-100 h-[100vh] overflow-y-auto transition-colors duration-200 flex flex-col\">\n          <Header />\n          <CLIInterface />\n          <Footer />\n        </div>\n      </ContextMenuTrigger>\n      <ContextMenuContent className=\"w-40\">\n        <ContextMenuItem\n          onClick={() => window.ipc.postMessage(`${USER_EVENT.OPEN}|https://github.com/uni-helper/create-uni`)}\n        >\n          Github\n        </ContextMenuItem>\n        <ContextMenuItem\n          onClick={() => window.ipc.postMessage(`${USER_EVENT.OPEN}|https://afdian.com/a/flippedround`)}\n        >\n          Sponsor\n        </ContextMenuItem>\n        <ContextMenuSeparator />\n        <ContextMenuItem\n          onClick={() => window.location.reload()}\n        >\n          Reload\n        </ContextMenuItem>\n        <ContextMenuItem\n          onClick={() => window.ipc.postMessage(USER_EVENT.CLOSE)}\n        >\n          Exit\n        </ContextMenuItem>\n      </ContextMenuContent>\n    </ContextMenu>\n\n  )\n}\n\nrender(<App />, document.getElementById('app'))\n"
  },
  {
    "path": "packages/ui/src/lib/utils.ts",
    "content": "import { type ClassValue, clsx } from 'clsx'\nimport { twMerge } from 'tailwind-merge'\n\nexport function cn(...inputs: ClassValue[]) {\n  return twMerge(clsx(inputs))\n}\n"
  },
  {
    "path": "packages/ui/src/page/index.tsx",
    "content": "import { Eslint } from '@/components/icons/eslint'\nimport { Rename } from '@/components/icons/rename'\nimport { Template } from '@/components/icons/template'\nimport { Typescript } from '@/components/icons/typeScript'\nimport { OptionCheck } from '@/components/optionCheck'\nimport { TemplateCheck } from '@/components/templateCheck'\nimport { Button } from '@/components/ui/button'\nimport { Input } from '@/components/ui/input'\nimport { Label } from '@/components/ui/label'\nimport { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group'\nimport { UICheck } from '@/components/UICheck'\nimport { USER_EVENT } from '@/constants/USER_EVENT'\nimport { ArrowLeft, ArrowRight, Blocks, Check, Folder, Package, Puzzle } from 'lucide-react'\nimport React, { useState } from 'react'\n\nconst customSteps = [\n  {\n    title: 'Project Name',\n    icon: <Rename />,\n    value: 'name',\n  },\n  { title: 'Template', icon: <Template />, value: 'template' },\n  { title: 'TypeScript', icon: <Typescript />, value: 'ts' },\n  { title: 'Plugins', icon: <Blocks size={18} />, value: 'plugins' },\n  { title: 'Modules', icon: <Package size={18} />, value: 'modules' },\n  { title: 'UI', icon: <Puzzle size={18} />, value: 'ui' },\n  { title: 'ESLint', icon: <Eslint />, value: 'eslint' },\n  { title: 'Install Path', icon: <Folder size={18} />, value: 'path' },\n] as const\n\nconst templateSteps = [\n  {\n    title: 'Project Name',\n    icon: <Rename />,\n    value: 'name',\n  },\n  { title: 'Template', icon: <Template />, value: 'template' },\n  { title: 'Install Path', icon: <Folder size={18} />, value: 'path' },\n] as any\n\nexport default function CLIInterface() {\n  const [steps, setSteps] = useState(customSteps)\n\n  const [currentStep, setCurrentStep] = useState<typeof customSteps[number]['value']>('name')\n  const [formData, setFormData] = useState({\n    projectName: '',\n    useTemplate: 'custom',\n    requireTypeScript: true,\n    requiredPlugins: [],\n    requiredModules: [],\n    requireUI: null,\n    requireESLint: true,\n    installationPath: window.create_uni_current_dir,\n  })\n\n  window.addEventListener('pathEvent', (event) => {\n    const message = event.detail.path\n    setFormData({ ...formData, installationPath: message })\n  })\n\n  const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n    const { name, value } = e.target as HTMLInputElement\n    setFormData({ ...formData, [name]: value })\n  }\n\n  const handleTemplateChange = (value: string) => {\n    console.log('Template changed:', value)\n    setFormData({ ...formData, useTemplate: value })\n    if (value !== 'custom') {\n      setSteps(templateSteps)\n    }\n    else {\n      setSteps(customSteps)\n    }\n  }\n\n  const handleUIChange = (value: string) => {\n    setFormData({ ...formData, requireUI: value })\n  }\n\n  const handleRadioChange = (value: string, field: string) => {\n    setFormData({ ...formData, [field]: value })\n  }\n\n  const handleCheckboxChange = (value: string, field: string) => {\n    const currentValues = formData[field as keyof typeof formData] as string[]\n    const updatedValues = currentValues.includes(value)\n      ? currentValues.filter(item => item !== value)\n      : [...currentValues, value]\n    setFormData({ ...formData, [field]: updatedValues })\n  }\n\n  const handleNext = () => {\n    const currentIndex = steps.findIndex(item => item.value === currentStep)\n    if (currentIndex < steps.length - 1) {\n      setCurrentStep(steps[currentIndex + 1].value)\n    }\n  }\n\n  const handleBack = () => {\n    const currentIndex = steps.findIndex(item => item.value === currentStep)\n    if (currentIndex > 0) {\n      setCurrentStep(steps[currentIndex - 1].value)\n    }\n  }\n\n  const StepLabel = (value: string) => {\n    const index = steps.findIndex(item => item.value === value)\n    return (\n      <div className=\"flex items-center pb-2\">\n        <div className=\"mr-2 text-zinc-500 text-xl\">{steps[index].icon}</div>\n        <Label className=\"text-sm font-medium text-zinc-700 dark:text-zinc-300\">{steps[index].title}</Label>\n      </div>\n    )\n  }\n\n  const renderStep = () => {\n    switch (currentStep) {\n      case 'name':\n        return (\n          <div className=\"space-y-2\">\n            {StepLabel(currentStep)}\n            <Input\n              id=\"projectName\"\n              name=\"projectName\"\n              value={formData.projectName}\n              onChange={handleInputChange}\n              placeholder=\"uni-app\"\n              className=\"w-full bg-zinc-50 dark:bg-zinc-800 border-zinc-300 dark:border-zinc-700 focus:border-zinc-500 dark:focus:border-zinc-400 focus:ring-zinc-500 dark:focus:ring-zinc-400\"\n            />\n          </div>\n        )\n      case 'template':\n        return (\n          <div className=\"space-y-2\">\n            {StepLabel(currentStep)}\n\n            <TemplateCheck\n              useTemplate={formData.useTemplate}\n              onChange={handleTemplateChange}\n            />\n          </div>\n        )\n      case 'ts':\n        return (\n          <RadioGroup\n            value={formData.requireTypeScript as unknown as string}\n            onValueChange={value => handleRadioChange(value, 'requireTypeScript')}\n          >\n            <div className=\"space-y-2\">\n              {StepLabel(currentStep)}\n\n              <div className=\"flex items-center space-x-2\">\n                <RadioGroupItem value={true as unknown as string} id=\"typescript-yes\" className=\"border-zinc-300 dark:border-zinc-700 text-zinc-600 dark:text-zinc-400\" />\n                <Label htmlFor=\"typescript-yes\" className=\"text-zinc-600 dark:text-zinc-400\">Yes</Label>\n              </div>\n              <div className=\"flex items-center space-x-2\">\n                <RadioGroupItem value={false as unknown as string} id=\"typescript-no\" className=\"border-zinc-300 dark:border-zinc-700 text-zinc-600 dark:text-zinc-400\" />\n                <Label htmlFor=\"typescript-no\" className=\"text-zinc-600 dark:text-zinc-400\">No</Label>\n              </div>\n            </div>\n          </RadioGroup>\n        )\n      case 'plugins':\n        return (\n          <div className=\"space-y-2\">\n            {StepLabel(currentStep)}\n\n            <OptionCheck\n              checkList={formData.requiredPlugins}\n              options={window.create_uni_data.plugin}\n              onChange={value => handleCheckboxChange(value, 'requiredPlugins')}\n            />\n\n          </div>\n        )\n      case 'modules':\n        return (\n          <div className=\"space-y-2\">\n            {StepLabel(currentStep)}\n\n            <OptionCheck\n              checkList={formData.requiredModules}\n              options={window.create_uni_data.module}\n              onChange={value => handleCheckboxChange(value, 'requiredModules')}\n            />\n\n          </div>\n        )\n      case 'ui':\n        return (\n          <div className=\"space-y-2\">\n            {StepLabel(currentStep)}\n\n            <UICheck\n              value={formData.requireUI}\n              options={window.create_uni_data.ui}\n              onChange={handleUIChange}\n            />\n          </div>\n        )\n      case 'eslint':\n        return (\n          <RadioGroup\n            value={formData.requireESLint as unknown as string}\n            onValueChange={value => handleRadioChange(value, 'requireESLint')}\n          >\n            <div className=\"space-y-2\">\n              {StepLabel(currentStep)}\n\n              <div className=\"flex items-center space-x-2\">\n                <RadioGroupItem value={true as unknown as string} id=\"eslint-yes\" className=\"border-zinc-300 dark:border-zinc-700 text-zinc-600 dark:text-zinc-400\" />\n                <Label htmlFor=\"eslint-yes\" className=\"text-zinc-600 dark:text-zinc-400\">Yes</Label>\n              </div>\n              <div className=\"flex items-center space-x-2\">\n                <RadioGroupItem value={false as unknown as string} id=\"eslint-no\" className=\"border-zinc-300 dark:border-zinc-700 text-zinc-600 dark:text-zinc-400\" />\n                <Label htmlFor=\"eslint-no\" className=\"text-zinc-600 dark:text-zinc-400\">No</Label>\n              </div>\n            </div>\n          </RadioGroup>\n        )\n      case 'path':\n        return (\n          <div className=\"space-y-2\">\n            {StepLabel(currentStep)}\n\n            <div className=\"flex flex-col items-center\">\n              <Label className=\"pt-2\">{formData.installationPath}</Label>\n\n              <div className=\" w-full border-b border-1 border-dashed border-zinc-500/50 my-2\" />\n\n              <Button\n                variant=\"outline\"\n                className=\"w-full !ml-0 \"\n                onClick={() => window.ipc.postMessage(USER_EVENT.FILE_PATH)}\n              >\n                Pick Folder\n              </Button>\n            </div>\n          </div>\n        )\n      default:\n        return null\n    }\n  }\n\n  return (\n    <div className=\"p-6 pt-0\">\n      <div className=\"mb-6\">\n        <div className=\"h-1 bg-zinc-200 dark:bg-zinc-700 rounded-full\">\n          <div\n            className=\"h-full bg-zinc-600 dark:bg-zinc-400 rounded-full transition-all duration-300 ease-in-out\"\n            style={{ width: `${((steps.findIndex(item => item.value === currentStep) + 1) / steps.length) * 100}%` }}\n          >\n          </div>\n        </div>\n        <div className=\"text-xs mt-2 text-zinc-500 dark:text-zinc-400\">\n          Step\n          {' '}\n          {steps.findIndex(item => item.value === currentStep) + 1}\n          {' '}\n          of\n          {' '}\n          {steps.length}\n          :\n          {' '}\n          {steps.find(item => item.value === currentStep).title}\n        </div>\n      </div>\n      <div className=\"bg-gradient-to-b from-zinc-100 to-white dark:from-zinc-800 dark:to-zinc-900 p-6 rounded-lg mb-6\">\n        <div className=\"mb-6\">{renderStep()}</div>\n      </div>\n      <div className=\"flex justify-between\">\n        <Button\n          onClick={handleBack}\n          disabled={currentStep === 'name'}\n          variant=\"outline\"\n          size=\"sm\"\n          className=\"w-[80px] border-zinc-300 dark:border-zinc-700 text-zinc-600 dark:text-zinc-400 hover:bg-zinc-100 dark:hover:bg-zinc-800 disabled:opacity-50\"\n        >\n          <ArrowLeft className=\"w-4 h-4 mr-1\" />\n          Back\n        </Button>\n        {currentStep !== 'path'\n          ? (\n              <Button\n                onClick={handleNext}\n                size=\"sm\"\n                className=\"w-[80px] bg-zinc-800 dark:bg-zinc-200 text-zinc-100 dark:text-zinc-900 hover:bg-zinc-700 dark:hover:bg-zinc-300\"\n              >\n                Next\n                <ArrowRight className=\"w-4 h-4 ml-1\" />\n              </Button>\n            )\n          : (\n              <Button\n                onClick={() => window.ipc.postMessage(`${USER_EVENT.INSTALL}|${JSON.stringify(formData)}`)}\n                size=\"sm\"\n                className=\"w-[80px] bg-zinc-800 dark:bg-zinc-200 text-zinc-100 dark:text-zinc-900 hover:bg-zinc-700 dark:hover:bg-zinc-300\"\n              >\n                Install\n                <Check className=\"w-4 h-4 ml-1\" />\n              </Button>\n            )}\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/ui/src/style.css",
    "content": "@tailwind base;\n@tailwind components;\n@tailwind utilities;\n\n@layer base {\n  :root {\n    --background: 0 0% 100%;\n    --foreground: 240 10% 3.9%;\n    --card: 0 0% 100%;\n    --card-foreground: 240 10% 3.9%;\n    --popover: 0 0% 100%;\n    --popover-foreground: 240 10% 3.9%;\n    --primary: 240 5.9% 10%;\n    --primary-foreground: 0 0% 98%;\n    --secondary: 240 4.8% 95.9%;\n    --secondary-foreground: 240 5.9% 10%;\n    --muted: 240 4.8% 95.9%;\n    --muted-foreground: 240 3.8% 46.1%;\n    --accent: 240 4.8% 95.9%;\n    --accent-foreground: 240 5.9% 10%;\n    --destructive: 0 84.2% 60.2%;\n    --destructive-foreground: 0 0% 98%;\n    --border: 240 5.9% 90%;\n    --input: 240 5.9% 90%;\n    --ring: 240 10% 3.9%;\n    --chart-1: 12 76% 61%;\n    --chart-2: 173 58% 39%;\n    --chart-3: 197 37% 24%;\n    --chart-4: 43 74% 66%;\n    --chart-5: 27 87% 67%;\n    --radius: 0.5rem\n  }\n  .dark {\n    --background: 240 10% 3.9%;\n    --foreground: 0 0% 98%;\n    --card: 240 10% 3.9%;\n    --card-foreground: 0 0% 98%;\n    --popover: 240 10% 3.9%;\n    --popover-foreground: 0 0% 98%;\n    --primary: 0 0% 98%;\n    --primary-foreground: 240 5.9% 10%;\n    --secondary: 240 3.7% 15.9%;\n    --secondary-foreground: 0 0% 98%;\n    --muted: 240 3.7% 15.9%;\n    --muted-foreground: 240 5% 64.9%;\n    --accent: 240 3.7% 15.9%;\n    --accent-foreground: 0 0% 98%;\n    --destructive: 0 62.8% 30.6%;\n    --destructive-foreground: 0 0% 98%;\n    --border: 240 3.7% 15.9%;\n    --input: 240 3.7% 15.9%;\n    --ring: 240 4.9% 83.9%;\n    --chart-1: 220 70% 50%;\n    --chart-2: 160 60% 45%;\n    --chart-3: 30 80% 55%;\n    --chart-4: 280 65% 60%;\n    --chart-5: 340 75% 55%\n  }\n}\n@layer base {\n  * {\n    @apply border-border;\n  }\n  body {\n    @apply bg-background text-foreground;\n  }\n}\n\n"
  },
  {
    "path": "packages/ui/src/types/gloabal.d.ts",
    "content": "// global.d.ts\nimport type { TemplateList } from '@create-uni/config'\nimport type { Options } from '@create-uni/config'\n\ndeclare global {\n  interface Window {\n    ipc: {\n      postMessage: (message: string) => void\n    }\n    create_uni_data: {\n      templateList: TemplateList[]\n      plugin: Options[]\n      module: Options[]\n      ui: Options[]\n    }\n    create_uni_current_dir: string\n  }\n\n  interface PathEventDetail {\n    path: string\n  }\n\n  interface PathEvent extends CustomEvent<PathEventDetail> {}\n\n  interface WindowEventMap {\n    pathEvent: PathEvent\n  }\n}\n"
  },
  {
    "path": "packages/ui/tailwind.config.js",
    "content": "/** @type {import('tailwindcss').Config} */\nexport default {\n  darkMode: ['class'],\n  content: ['./index.html', './src/**/*.{ts,tsx,js,jsx}'],\n  theme: {\n    extend: {\n      borderRadius: {\n        lg: 'var(--radius)',\n        md: 'calc(var(--radius) - 2px)',\n        sm: 'calc(var(--radius) - 4px)',\n      },\n      colors: {\n        background: 'hsl(var(--background))',\n        foreground: 'hsl(var(--foreground))',\n        card: {\n          DEFAULT: 'hsl(var(--card))',\n          foreground: 'hsl(var(--card-foreground))',\n        },\n        popover: {\n          DEFAULT: 'hsl(var(--popover))',\n          foreground: 'hsl(var(--popover-foreground))',\n        },\n        primary: {\n          DEFAULT: 'hsl(var(--primary))',\n          foreground: 'hsl(var(--primary-foreground))',\n        },\n        secondary: {\n          DEFAULT: 'hsl(var(--secondary))',\n          foreground: 'hsl(var(--secondary-foreground))',\n        },\n        muted: {\n          DEFAULT: 'hsl(var(--muted))',\n          foreground: 'hsl(var(--muted-foreground))',\n        },\n        accent: {\n          DEFAULT: 'hsl(var(--accent))',\n          foreground: 'hsl(var(--accent-foreground))',\n        },\n        destructive: {\n          DEFAULT: 'hsl(var(--destructive))',\n          foreground: 'hsl(var(--destructive-foreground))',\n        },\n        border: 'hsl(var(--border))',\n        input: 'hsl(var(--input))',\n        ring: 'hsl(var(--ring))',\n        chart: {\n          1: 'hsl(var(--chart-1))',\n          2: 'hsl(var(--chart-2))',\n          3: 'hsl(var(--chart-3))',\n          4: 'hsl(var(--chart-4))',\n          5: 'hsl(var(--chart-5))',\n        },\n      },\n    },\n  },\n  plugins: [require('tailwindcss-animate')],\n}\n"
  },
  {
    "path": "packages/ui/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n\n    /* Preact Config */\n    \"jsx\": \"react-jsx\",\n    \"jsxImportSource\": \"preact\",\n    \"baseUrl\": \".\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"paths\": {\n      \"react\": [\"./node_modules/preact/compat/\"],\n      \"react-dom\": [\"./node_modules/preact/compat/\"],\n      \"@/*\": [\"./src/*\"]\n    },\n    \"allowJs\": true,\n    \"checkJs\": true,\n    \"noEmit\": true,\n    \"skipLibCheck\": true\n\n  },\n  \"include\": [\"node_modules/vite/client.d.ts\", \"**/*\"]\n}\n"
  },
  {
    "path": "packages/ui/vite.config.ts",
    "content": "import { resolve } from 'node:path'\nimport preact from '@preact/preset-vite'\nimport { defineConfig } from 'vite'\nimport { viteSingleFile } from 'vite-plugin-singlefile'\n\n// https://vitejs.dev/config/\nexport default defineConfig({\n  resolve: {\n    alias: {\n      '@': resolve(__dirname, './src'),\n    },\n  },\n  plugins: [\n    preact(),\n    viteSingleFile(),\n  ],\n  server: {\n    port: 4006,\n  },\n  build: {\n    outDir: './../gui/src/ui',\n    emptyOutDir: false,\n    rollupOptions: {\n      input: {\n        main: resolve(__dirname, 'index.html'),\n      },\n    },\n  },\n})\n"
  },
  {
    "path": "pnpm-workspace.yaml",
    "content": "packages:\n  - packages/*\n"
  },
  {
    "path": "scripts/dev.cjs",
    "content": "const { spawn } = require('node:child_process')\nconst fs = require('node:fs')\nconst path = require('node:path')\nconst process = require('node:process')\n\nconst workingDirectory = path.join(__dirname, '../../sample-project')\n\n// 启动开发命令，改为使用 pipe 来捕获错误输出\nconst devProcess = spawn('pnpm', ['dev', 'mp-weixin'], {\n  stdio: ['inherit', 'inherit', 'pipe'],\n  shell: true,\n  cwd: workingDirectory,\n})\n\n// 捕获错误输出\ndevProcess.stderr.on('data', (data) => {\n  console.error(`stderr: ${data}`)\n  if (!data.includes('Warning: To load an ES module, set \"type\": \"module\" in the package.json or use the .mjs extension.')) {\n    devProcess.kill()\n    process.exit(1)\n  }\n})\n\n// 检查文件是否存在\nfunction checkFileExists(filePath) {\n  return new Promise((resolve) => {\n    fs.access(filePath, fs.constants.F_OK, (error) => {\n      resolve(!error)\n    })\n  })\n}\n\n// 等待文件出现\nasync function waitForFile(filePath) {\n  let fileExists = await checkFileExists(filePath)\n  while (!fileExists) {\n    await new Promise(resolve => setTimeout(resolve, 3000))\n    fileExists = await checkFileExists(filePath)\n  }\n}\n\n// 主逻辑\nasync function main() {\n  const expectedFile = path.join(workingDirectory, 'dist/dev/mp-weixin/app.js')\n  await waitForFile(expectedFile)\n  devProcess.kill() // 结束进程\n  process.exit(0)\n}\n\nmain().catch((err) => {\n  console.error(err)\n  process.exit(1)\n})\n"
  },
  {
    "path": "scripts/link.cjs",
    "content": "const { execSync } = require('node:child_process')\nconst consola = require('consola')\n\ntry {\n  execSync('pnpm link ./packages/core')\n  execSync('pnpm link ./packages/info')\n  execSync('pnpm link ./packages/gui')\n  consola.success('Linked packages')\n}\ncatch (error) {\n  consola.error(error)\n}\n"
  },
  {
    "path": "tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"es2018\",\n    \"lib\": [\"esnext\"],\n    \"baseUrl\": \".\",\n    \"module\": \"esnext\",\n    \"moduleResolution\": \"node\",\n    \"resolveJsonModule\": true,\n    \"strict\": true,\n    \"strictNullChecks\": true,\n    \"esModuleInterop\": true,\n    \"skipDefaultLibCheck\": true,\n    \"skipLibCheck\": true\n  }\n}\n"
  },
  {
    "path": "turbo.json",
    "content": "{\n  \"$schema\": \"https://turbo.build/schema.json\",\n  \"tasks\": {\n    \"dev\": {\n      \"cache\": false,\n      \"persistent\": true\n    },\n    \"@create-uni/info#build\": {\n      \"dependsOn\": [\n        \"^build\"\n      ],\n      \"outputs\": [\n        \"dist/outfile.cjs\"\n      ]\n    },\n    \"create-uni#build\": {\n      \"dependsOn\": [\n        \"^build\"\n      ],\n      \"outputs\": [\n        \"dist/outfile.cjs\"\n      ]\n    },\n    \"@create-uni/gui#build\": {\n      \"dependsOn\": [\n        \"@create-uni/ui#build\"\n      ]\n    },\n    \"build\": {\n      \"dependsOn\": [\n        \"^build\"\n      ]\n    }\n  }\n}\n"
  }
]