Showing preview only (303K chars total). Download the full file or copy to clipboard to get everything.
Repository: uni-helper/create-uni
Branch: main
Commit: 12b4a83256fa
Files: 266
Total size: 233.2 KB
Directory structure:
gitextract_q84dp_cp/
├── .gitattributes
├── .github/
│ ├── FUNDING.yml
│ └── workflows/
│ ├── core_release.yml
│ ├── core_test.yml
│ ├── core_test_template.yml
│ ├── gui_release.yml
│ ├── info_release.yml
│ ├── info_test.yml
│ ├── lint.yml
│ ├── mcp_release.yml
│ └── uni-app_update.yml
├── .gitignore
├── .vscode/
│ └── settings.json
├── LICENSE
├── README.md
├── eslint.config.js
├── package.json
├── packages/
│ ├── config/
│ │ ├── package.json
│ │ └── src/
│ │ ├── index.ts
│ │ ├── module.data.ts
│ │ ├── plugin.data.ts
│ │ ├── template.data.ts
│ │ ├── type.d.ts
│ │ └── ui.data.ts
│ ├── core/
│ │ ├── .gitignore
│ │ ├── bump.config.ts
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── command/
│ │ │ │ ├── actions/
│ │ │ │ │ ├── gui.ts
│ │ │ │ │ └── info.ts
│ │ │ │ ├── composeCommand.ts
│ │ │ │ ├── index.ts
│ │ │ │ └── runCommand.ts
│ │ │ ├── constants/
│ │ │ │ └── index.ts
│ │ │ ├── index.ts
│ │ │ ├── question/
│ │ │ │ ├── choices.ts
│ │ │ │ ├── file.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── module/
│ │ │ │ │ └── index.ts
│ │ │ │ ├── name.ts
│ │ │ │ ├── onCancel.ts
│ │ │ │ ├── plugin/
│ │ │ │ │ └── index.ts
│ │ │ │ ├── template/
│ │ │ │ │ └── index.ts
│ │ │ │ ├── type.d.ts
│ │ │ │ └── ui/
│ │ │ │ └── index.ts
│ │ │ └── utils/
│ │ │ ├── clearFile.ts
│ │ │ ├── cloneRepo.ts
│ │ │ ├── deepMerge.ts
│ │ │ ├── directoryTraverse.ts
│ │ │ ├── getCommand.ts
│ │ │ ├── getPkgManager.ts
│ │ │ ├── index.ts
│ │ │ ├── injectUtils.ts
│ │ │ ├── jsonStringifyWithoutKeysQuotes.ts
│ │ │ ├── printFinish.ts
│ │ │ ├── renderTemplate.ts
│ │ │ ├── setPackageName.ts
│ │ │ ├── sortDependencies.ts
│ │ │ ├── types.ts
│ │ │ └── validateArgv.ts
│ │ ├── template/
│ │ │ ├── UI/
│ │ │ │ ├── ano/
│ │ │ │ │ ├── package.json
│ │ │ │ │ ├── src/
│ │ │ │ │ │ └── components/
│ │ │ │ │ │ └── InputEntry.vue
│ │ │ │ │ ├── uno.config.js.data.mjs
│ │ │ │ │ └── vite.config.js.data.mjs
│ │ │ │ ├── nut/
│ │ │ │ │ ├── package.json
│ │ │ │ │ ├── src/
│ │ │ │ │ │ ├── App.vue
│ │ │ │ │ │ └── components/
│ │ │ │ │ │ └── InputEntry.vue
│ │ │ │ │ └── vite.config.js.data.mjs
│ │ │ │ ├── tdesign/
│ │ │ │ │ ├── package.json
│ │ │ │ │ ├── src/
│ │ │ │ │ │ └── components/
│ │ │ │ │ │ └── InputEntry.vue
│ │ │ │ │ └── vite.config.js.data.mjs
│ │ │ │ ├── uni/
│ │ │ │ │ ├── package.json
│ │ │ │ │ ├── src/
│ │ │ │ │ │ └── components/
│ │ │ │ │ │ └── InputEntry.vue
│ │ │ │ │ └── vite.config.js.data.mjs
│ │ │ │ ├── unocss/
│ │ │ │ │ └── src/
│ │ │ │ │ ├── components/
│ │ │ │ │ │ ├── AppFooter.vue
│ │ │ │ │ │ ├── AppLogos.vue
│ │ │ │ │ │ └── InputEntry.vue
│ │ │ │ │ └── pages/
│ │ │ │ │ └── index.vue
│ │ │ │ ├── uv/
│ │ │ │ │ ├── package.json
│ │ │ │ │ ├── src/
│ │ │ │ │ │ ├── App.vue
│ │ │ │ │ │ └── components/
│ │ │ │ │ │ └── InputEntry.vue
│ │ │ │ │ └── vite.config.js.data.mjs
│ │ │ │ ├── uview-pro/
│ │ │ │ │ ├── jsconfig.json
│ │ │ │ │ ├── package.json
│ │ │ │ │ ├── src/
│ │ │ │ │ │ ├── App.vue
│ │ │ │ │ │ ├── components/
│ │ │ │ │ │ │ └── InputEntry.vue
│ │ │ │ │ │ └── main.js.data.mjs
│ │ │ │ │ └── vite.config.js.data.mjs
│ │ │ │ ├── wot/
│ │ │ │ │ ├── .vscode/
│ │ │ │ │ │ └── extensions.json
│ │ │ │ │ ├── jsconfig.json
│ │ │ │ │ ├── package.json
│ │ │ │ │ ├── src/
│ │ │ │ │ │ └── components/
│ │ │ │ │ │ └── InputEntry.vue
│ │ │ │ │ └── vite.config.js.data.mjs
│ │ │ │ └── wot2/
│ │ │ │ ├── .vscode/
│ │ │ │ │ └── extensions.json
│ │ │ │ ├── jsconfig.json
│ │ │ │ ├── package.json
│ │ │ │ ├── src/
│ │ │ │ │ └── components/
│ │ │ │ │ └── InputEntry.vue
│ │ │ │ └── vite.config.js.data.mjs
│ │ │ ├── base/
│ │ │ │ ├── .vscode/
│ │ │ │ │ ├── extensions.json
│ │ │ │ │ └── settings.json
│ │ │ │ ├── _gitignore
│ │ │ │ ├── _npmrc
│ │ │ │ ├── index.html
│ │ │ │ ├── jsconfig.json
│ │ │ │ ├── package.json
│ │ │ │ ├── src/
│ │ │ │ │ ├── App.vue
│ │ │ │ │ ├── components/
│ │ │ │ │ │ ├── AppFooter.vue
│ │ │ │ │ │ ├── AppLogos.vue
│ │ │ │ │ │ └── InputEntry.vue
│ │ │ │ │ ├── main.js.data.mjs
│ │ │ │ │ ├── main.js.ejs
│ │ │ │ │ ├── manifest.json
│ │ │ │ │ ├── pages/
│ │ │ │ │ │ └── index.vue
│ │ │ │ │ ├── pages.json
│ │ │ │ │ ├── theme.json
│ │ │ │ │ └── uni.scss
│ │ │ │ ├── unh.config.js.data.mjs
│ │ │ │ ├── unh.config.js.ejs
│ │ │ │ ├── vite.config.js.data.mjs
│ │ │ │ └── vite.config.js.ejs
│ │ │ ├── config/
│ │ │ │ ├── lint/
│ │ │ │ │ ├── .vscode/
│ │ │ │ │ │ ├── extensions.json
│ │ │ │ │ │ └── settings.json
│ │ │ │ │ ├── eslint.config.js
│ │ │ │ │ └── package.json
│ │ │ │ └── typescript/
│ │ │ │ ├── .vscode/
│ │ │ │ │ └── extensions.json
│ │ │ │ ├── jsconfig.json
│ │ │ │ └── package.json
│ │ │ ├── module/
│ │ │ │ ├── pinia/
│ │ │ │ │ ├── package.json
│ │ │ │ │ └── src/
│ │ │ │ │ ├── main.js.data.mjs
│ │ │ │ │ └── stores/
│ │ │ │ │ └── counter.js
│ │ │ │ ├── uniEcharts/
│ │ │ │ │ ├── jsconfig.json
│ │ │ │ │ ├── package.json
│ │ │ │ │ └── vite.config.js.data.mjs
│ │ │ │ ├── uniNetwork/
│ │ │ │ │ └── package.json
│ │ │ │ ├── uniPromises/
│ │ │ │ │ ├── package.json
│ │ │ │ │ ├── src/
│ │ │ │ │ │ └── main.js.data.mjs
│ │ │ │ │ └── vite.config.js.data.mjs
│ │ │ │ ├── uniUse/
│ │ │ │ │ ├── package.json
│ │ │ │ │ ├── src/
│ │ │ │ │ │ └── main.js.data.mjs
│ │ │ │ │ └── vite.config.js.data.mjs
│ │ │ │ ├── unocss/
│ │ │ │ │ ├── .vscode/
│ │ │ │ │ │ └── extensions.json
│ │ │ │ │ ├── package.json
│ │ │ │ │ ├── src/
│ │ │ │ │ │ └── main.js.data.mjs
│ │ │ │ │ ├── uno.config.js.data.mjs
│ │ │ │ │ ├── uno.config.js.ejs
│ │ │ │ │ └── vite.config.js.data.mjs
│ │ │ │ ├── vitest/
│ │ │ │ │ ├── jsconfig.json
│ │ │ │ │ ├── package.json
│ │ │ │ │ ├── test/
│ │ │ │ │ │ └── index.test.js
│ │ │ │ │ └── vitest.config.js
│ │ │ │ └── zPaging/
│ │ │ │ ├── jsconfig.json
│ │ │ │ ├── package.json
│ │ │ │ └── vite.config.js.data.mjs
│ │ │ └── plugin/
│ │ │ ├── componentPlaceholder/
│ │ │ │ ├── package.json
│ │ │ │ └── vite.config.js.data.mjs
│ │ │ ├── filePlatform/
│ │ │ │ ├── package.json
│ │ │ │ └── vite.config.js.data.mjs
│ │ │ ├── import/
│ │ │ │ ├── package.json
│ │ │ │ └── vite.config.js.data.mjs
│ │ │ ├── layouts/
│ │ │ │ ├── package.json
│ │ │ │ └── vite.config.js.data.mjs
│ │ │ ├── manifest/
│ │ │ │ ├── manifest.config.js
│ │ │ │ ├── package.json
│ │ │ │ ├── unh.config.js.data.mjs
│ │ │ │ └── vite.config.js.data.mjs
│ │ │ ├── pages/
│ │ │ │ ├── jsconfig.json
│ │ │ │ ├── package.json
│ │ │ │ ├── pages.config.js
│ │ │ │ ├── unh.config.js.data.mjs
│ │ │ │ └── vite.config.js.data.mjs
│ │ │ └── root/
│ │ │ ├── package.json
│ │ │ ├── src/
│ │ │ │ └── App.ku.vue
│ │ │ └── vite.config.js.data.mjs
│ │ ├── tsconfig.json
│ │ └── tsup.config.ts
│ ├── gui/
│ │ ├── .cargo/
│ │ │ └── config.toml
│ │ ├── .github/
│ │ │ └── workflows/
│ │ │ └── CI.yml
│ │ ├── .gitignore
│ │ ├── .npmignore
│ │ ├── Cargo.toml
│ │ ├── bin/
│ │ │ └── index.cjs
│ │ ├── build.rs
│ │ ├── bump.config.ts
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── nodemon.json
│ │ ├── npm/
│ │ │ ├── darwin-arm64/
│ │ │ │ ├── README.md
│ │ │ │ └── package.json
│ │ │ ├── darwin-x64/
│ │ │ │ ├── README.md
│ │ │ │ └── package.json
│ │ │ ├── win32-arm64-msvc/
│ │ │ │ ├── README.md
│ │ │ │ └── package.json
│ │ │ ├── win32-ia32-msvc/
│ │ │ │ ├── README.md
│ │ │ │ └── package.json
│ │ │ └── win32-x64-msvc/
│ │ │ ├── README.md
│ │ │ └── package.json
│ │ ├── package.json
│ │ ├── rustfmt.toml
│ │ └── src/
│ │ └── lib.rs
│ ├── info/
│ │ ├── bump.config.ts
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── constants/
│ │ │ │ └── index.ts
│ │ │ ├── index.ts
│ │ │ ├── question/
│ │ │ │ └── index.ts
│ │ │ ├── types/
│ │ │ │ └── index.d.ts
│ │ │ └── utils/
│ │ │ ├── dependencies.ts
│ │ │ ├── extensions.ts
│ │ │ └── whichPm.ts
│ │ └── tsup.config.ts
│ ├── mcp/
│ │ ├── README.md
│ │ ├── bump.config.ts
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── handlers.ts
│ │ │ ├── index.ts
│ │ │ ├── schemas.ts
│ │ │ ├── types.ts
│ │ │ └── utils.ts
│ │ ├── test/
│ │ │ └── promptBuilder.test.ts
│ │ ├── tsconfig.json
│ │ └── tsup.config.ts
│ ├── shared/
│ │ ├── package.json
│ │ └── src/
│ │ ├── canSkipEmptying.ts
│ │ ├── generateBanner.ts
│ │ ├── index.ts
│ │ └── ora.ts
│ └── ui/
│ ├── .gitignore
│ ├── components.json
│ ├── index.html
│ ├── package.json
│ ├── postcss.config.js
│ ├── src/
│ │ ├── components/
│ │ │ ├── UICheck.tsx
│ │ │ ├── footer/
│ │ │ │ └── index.tsx
│ │ │ ├── header/
│ │ │ │ └── index.tsx
│ │ │ ├── icons/
│ │ │ │ ├── demo.tsx
│ │ │ │ ├── eslint.tsx
│ │ │ │ ├── gitee.tsx
│ │ │ │ ├── github.tsx
│ │ │ │ ├── guide.tsx
│ │ │ │ ├── rename.tsx
│ │ │ │ ├── template.tsx
│ │ │ │ ├── typeScript.tsx
│ │ │ │ └── vitepress.tsx
│ │ │ ├── optionCheck.tsx
│ │ │ ├── templateCheck.tsx
│ │ │ └── ui/
│ │ │ ├── badge.tsx
│ │ │ ├── button.tsx
│ │ │ ├── checkbox.tsx
│ │ │ ├── context-menu.tsx
│ │ │ ├── drawer.tsx
│ │ │ ├── input.tsx
│ │ │ ├── label.tsx
│ │ │ ├── radio-group.tsx
│ │ │ └── select.tsx
│ │ ├── constants/
│ │ │ └── USER_EVENT.ts
│ │ ├── index.tsx
│ │ ├── lib/
│ │ │ └── utils.ts
│ │ ├── page/
│ │ │ └── index.tsx
│ │ ├── style.css
│ │ └── types/
│ │ └── gloabal.d.ts
│ ├── tailwind.config.js
│ ├── tsconfig.json
│ └── vite.config.ts
├── pnpm-workspace.yaml
├── scripts/
│ ├── dev.cjs
│ └── link.cjs
├── tsconfig.json
└── turbo.json
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitattributes
================================================
packages/core/template/** linguist-vendored
================================================
FILE: .github/FUNDING.yml
================================================
custom:
- 'https://afdian.com/a/flippedround'
- 'https://afdian.com/a/kejun'
- 'https://github.com/ModyQyW/sponsors'
- 'https://afdian.com/a/zguolee'
================================================
FILE: .github/workflows/core_release.yml
================================================
name: create-uni release CI
on:
push:
tags:
- 'core-v*'
jobs:
release:
name: Release
runs-on: ubuntu-latest
permissions:
contents: write
id-token: write
steps:
- name: Setup JS
uses: sxzz/workflows/setup-js@v1
with:
fetch-all: true
- name: Generate GitHub Changelog
run: pnpx changelogithub
continue-on-error: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Publish to NPM
working-directory: packages/core
run: pnpm publish --access public --no-git-checks
================================================
FILE: .github/workflows/core_test.yml
================================================
name: create-uni Test CI
on:
push:
branches:
- main
tags-ignore:
- '**'
paths:
- 'packages/core/**'
- .github/workflows/core_test.yml
pull_request:
branches:
- main
paths:
- 'packages/core/**'
- .github/workflows/core_test.yml
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
node: [20.x, 22.x]
os: [windows-latest, macos-latest]
fail-fast: false
steps:
- uses: actions/checkout@v4
- name: Install pnpm
uses: pnpm/action-setup@v2
- name: Set node ${{ matrix.node }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
cache: pnpm
- name: Setup
run: npm i -g @antfu/ni
- name: Install
run: nci
- name: Build
run: nr build:core
- uses: actions/cache/save@v4
id: cache
with:
path: packages/core/dist/outfile.cjs
key: ${{ github.sha }}-${{ hashFiles('pnpm-lock.yaml') }}-${{ matrix.os }}-${{ matrix.node }}
test:
needs: build
strategy:
matrix:
flag-for-ts: ['', --ts]
flag-for-eslint: [-e]
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]
flag-for-ui: ['', -u uni, -u ano, -u wot, -u nut, -u uv, -u tdesign]
node: [20.x]
os: [windows-latest, macos-latest]
runs-on: ${{ matrix.os }}
env:
FEATURE_FLAGS: ${{ matrix.flag-for-ts }} ${{ matrix.flag-for-eslint }} ${{ matrix.flag-for-plugin }} ${{ matrix.flag-for-ui }}
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v2
with:
version: 8
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
cache: pnpm
- uses: actions/cache/restore@v4
id: cache-restore
with:
path: packages/core/dist/outfile.cjs
key: ${{ github.sha }}-${{ hashFiles('pnpm-lock.yaml') }}-${{ matrix.os }}-${{ matrix.node }}
- name: 当没有缓存时,执行构建
if: steps.cache-restore.outputs.cache-hit != 'true'
run: pnpm install && pnpm build:core
- if: ${{ (contains(env.FEATURE_FLAGS, '-')) }}
name: 创建多参数项目
working-directory: ../
run: node ./create-uni/packages/core/dist/outfile.cjs sample-project ${{ env.FEATURE_FLAGS }}
- if: ${{ !(contains(env.FEATURE_FLAGS, '-')) }}
name: 创建基础项目
working-directory: ../
run: node ./create-uni/packages/core/dist/outfile.cjs sample-project
- name: 使用npm安装项目依赖
working-directory: ../sample-project
run: npm install --no-frozen-lockfile
- name: 移除node_modules
working-directory: ../sample-project
run: npx rimraf node_modules
- name: 使用pnpm安装项目依赖
working-directory: ../sample-project
run: pnpm install --no-frozen-lockfile
- name: 打包H5项目
working-directory: ../sample-project
run: pnpm build
- name: dev小程序项目
working-directory: ../sample-project
run: node ./../create-uni/scripts/dev.cjs
- name: 打包小程序项目
working-directory: ../sample-project
run: pnpm build mp-weixin
# - name: 输出环境信息
# working-directory: ../sample-project
# run: node ./../create-uni/packages/core/dist/outfile.cjs --info all
================================================
FILE: .github/workflows/core_test_template.yml
================================================
name: create-uni Test Template CI
on:
push:
branches:
- main
tags-ignore:
- '**'
paths:
- 'packages/core/**'
- .github/workflows/core_test.yml
pull_request:
branches:
- main
paths:
- 'packages/core/**'
- .github/workflows/core_test.yml
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
node: [20.x, 22.x]
os: [windows-latest, macos-latest]
fail-fast: false
steps:
- uses: actions/checkout@v4
- name: Install pnpm
uses: pnpm/action-setup@v2
- name: Set node ${{ matrix.node }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
cache: pnpm
- name: Setup
run: npm i -g @antfu/ni
- name: Install
run: nci
- name: Build
run: nr build:core
- uses: actions/cache/save@v4
id: cache
with:
path: packages/core/dist/outfile.cjs
key: ${{ github.sha }}-${{ hashFiles('pnpm-lock.yaml') }}-${{ matrix.os }}-${{ matrix.node }}
test:
needs: build
strategy:
fail-fast: false
matrix:
template: [-t vitesse]
node: [20.x]
os: [windows-latest, macos-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v2
with:
version: 8
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
cache: pnpm
- uses: actions/cache/restore@v4
id: cache-restore
with:
path: packages/core/dist/outfile.cjs
key: ${{ github.sha }}-${{ hashFiles('pnpm-lock.yaml') }}-${{ matrix.os }}-${{ matrix.node }}
- name: 当没有缓存时,执行构建
if: steps.cache-restore.outputs.cache-hit != 'true'
run: pnpm install && pnpm build:core
- name: 创建模板项目
working-directory: ../
run: node ./create-uni/packages/core/dist/outfile.cjs sample-project ${{ matrix.template }}
- name: 使用npm安装项目依赖
working-directory: ../sample-project
run: npm install --no-frozen-lockfile --legacy-peer-deps
- name: 移除node_modules
working-directory: ../sample-project
run: npx rimraf node_modules
- name: 使用pnpm安装项目依赖
working-directory: ../sample-project
run: pnpm install --no-frozen-lockfile
- name: 打包H5项目
working-directory: ../sample-project
run: pnpm build h5
- name: 打包小程序项目
working-directory: ../sample-project
run: pnpm build wx
================================================
FILE: .github/workflows/gui_release.yml
================================================
name: create-uni/gui CI
env:
DEBUG: napi:*
APP_NAME: create-uni/gui
MACOSX_DEPLOYMENT_TARGET: '10.13'
CARGO_INCREMENTAL: '1'
permissions:
contents: write
id-token: write
on:
push:
branches:
- main
tags-ignore:
- '**'
paths:
- 'packages/gui/**'
- 'packages/ui/**'
- .github/workflows/gui_release.yml
pull_request: null
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build:
strategy:
fail-fast: false
matrix:
settings:
- host: macos-latest
target: x86_64-apple-darwin
build: pnpm build --target x86_64-apple-darwin
- host: macos-latest
target: aarch64-apple-darwin
build: pnpm build --target aarch64-apple-darwin
- host: windows-latest
build: pnpm build --target x86_64-pc-windows-msvc
target: x86_64-pc-windows-msvc
- host: windows-latest
build: pnpm build --target i686-pc-windows-msvc
target: i686-pc-windows-msvc
- host: windows-latest
target: aarch64-pc-windows-msvc
build: pnpm build --target aarch64-pc-windows-msvc
name: stable - ${{ matrix.settings.target }} - node@20
runs-on: ${{ matrix.settings.host }}
steps:
- uses: actions/checkout@v4
- name: setup pnpm
uses: pnpm/action-setup@v4
- name: Setup node
uses: actions/setup-node@v4
with:
node-version: 20
cache: pnpm
- name: Install
uses: dtolnay/rust-toolchain@stable
with:
toolchain: stable
targets: ${{ matrix.settings.target }}
- name: Cache cargo
uses: actions/cache@v4
with:
path: |
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
~/.napi-rs
.cargo-cache
target/
key: ${{ matrix.settings.target }}-cargo-${{ matrix.settings.host }}
- name: build UI
working-directory: packages/ui
run: |
pnpm install
pnpm build
- name: Install dependencies
working-directory: packages/gui
run: pnpm install
- name: Setup node x86
uses: actions/setup-node@v4
if: matrix.settings.target == 'i686-pc-windows-msvc'
with:
node-version: 20
cache: pnpm
architecture: x86
- name: Build
working-directory: packages/gui
run: ${{ matrix.settings.build }}
shell: bash
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: bindings-${{ matrix.settings.target }}
path: 'packages/gui/*.node'
if-no-files-found: error
publish:
name: Publish
runs-on: ubuntu-latest
needs:
- build
steps:
- uses: actions/checkout@v4
- name: setup pnpm
uses: pnpm/action-setup@v4
- name: Setup node
uses: actions/setup-node@v4
with:
node-version: 20
cache: pnpm
- name: Install dependencies
working-directory: packages/gui
run: pnpm install
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: packages/gui/artifacts
- name: Move artifacts
working-directory: packages/gui
run: pnpm artifacts
- name: List packages
working-directory: packages/gui
run: ls -R ./npm
shell: bash
- name: Publish
working-directory: packages/gui
run: |
npm config set provenance true
if git log -1 --pretty=%B | grep "^v\?[0-9]\+\.[0-9]\+\.[0-9]\+$";
then
echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >> ~/.npmrc
npm publish --access public
elif git log -1 --pretty=%B | grep "^v\?[0-9]\+\.[0-9]\+\.[0-9]\+";
then
echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >> ~/.npmrc
npm publish --tag next --access public
else
echo "Not a release, skipping publish"
fi
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }}
================================================
FILE: .github/workflows/info_release.yml
================================================
name: create-uni/info release CI
on:
push:
tags:
- 'info-v*'
jobs:
release:
name: Release
runs-on: ubuntu-latest
permissions:
contents: write
id-token: write
steps:
- name: Setup JS
uses: sxzz/workflows/setup-js@v1
with:
fetch-all: true
- name: Generate GitHub Changelog
run: pnpx changelogithub
continue-on-error: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Publish to NPM
working-directory: packages/info
run: pnpm publish --access public --no-git-checks
================================================
FILE: .github/workflows/info_test.yml
================================================
name: create-uni/info Test CI
on:
push:
branches:
- main
tags-ignore:
- '**'
paths:
- 'packages/info/**'
- .github/workflows/info_test.yml
pull_request:
branches:
- main
paths:
- 'packages/info/**'
- .github/workflows/info_test.yml
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
matrix:
node: [20.x]
os: [windows-latest, macos-latest]
fail-fast: false
steps:
- uses: actions/checkout@v4
- name: Install pnpm
uses: pnpm/action-setup@v2
- name: Set node ${{ matrix.node }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
cache: pnpm
- name: Setup
run: npm i -g @antfu/ni
- name: Install
run: nci
- name: Build
run: nr build:info
- name: Test
run: node ./packages/info/dist/outfile.cjs all
================================================
FILE: .github/workflows/lint.yml
================================================
name: Lint
on:
push:
branches:
- main
tags-ignore:
- '**'
pull_request:
branches:
- main
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install pnpm
uses: pnpm/action-setup@v2
- name: Set node
uses: actions/setup-node@v4
with:
node-version: 20.x
cache: pnpm
- name: Setup
run: npm i -g @antfu/ni
- name: Install
run: nci
- name: ESLint
run: pnpm lint
- name: cargo fmt
run: cd packages/gui && cargo fmt --check
================================================
FILE: .github/workflows/mcp_release.yml
================================================
name: create-uni/mcp release CI
on:
push:
tags:
- 'mcp-v*'
jobs:
release:
name: Release
runs-on: ubuntu-latest
permissions:
contents: write
id-token: write
steps:
- name: Setup JS
uses: sxzz/workflows/setup-js@v1
with:
fetch-all: true
- name: Generate GitHub Changelog
run: pnpx changelogithub
continue-on-error: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Publish to NPM
working-directory: packages/mcp
run: pnpm publish --access public --no-git-checks
================================================
FILE: .github/workflows/uni-app_update.yml
================================================
name: update
on:
schedule:
- cron: '0 1 * * 1'
jobs:
update-dependencies:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install pnpm
uses: pnpm/action-setup@v4
- name: Set node
uses: actions/setup-node@v4
with:
node-version: 20.x
cache: pnpm
- name: update script
run: pnpm run up
- name: Commit and push if changes are made
run: |
git config --global user.email "734243792@qq.com"
git config --global user.name "FliPPeDround"
git add -A
git commit -m "chore: update deps" || echo "No changes to commit"
- name: Create Pull Request
uses: peter-evans/create-pull-request@v5
with:
token: ${{ secrets.MY_GITHUB_TOKEN }}
commit-message: 'chore: update deps'
title: 'chore: update deps'
body: Update dependencies
branch: chore/update-deps
delete-branch: true
base: main
================================================
FILE: .gitignore
================================================
# Created by .ignore support plugin (hsz.mobi)
### Node template
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# TypeScript v1 declaration files
typings/
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
# parcel-bundler cache (https://parceljs.org/)
.cache
# next.js build output
.next
# nuxt.js build output
.nuxt
# Nuxt generate
dist
# vuepress build output
.vuepress/dist
# Serverless directories
.serverless
# IDE
.idea
# turborepo
.turbo
.DS_Store
================================================
FILE: .vscode/settings.json
================================================
{
"cSpell.words": [
"bumpp",
"dcloudio",
"esno",
"execa",
"gitee",
"kolorist",
"outro",
"Pinia",
"taze",
"Unocss"
],
"prettier.enable": false,
"editor.formatOnSave": false,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit",
"source.organizeImports": "never"
},
"eslint.validate": [
"javascript",
"javascriptreact",
"typescript",
"typescriptreact",
"vue",
"html",
"markdown",
"json",
"jsonc",
"yaml"
],
"rust-analyzer.linkedProjects": [
"packages/gui/Cargo.toml"
]
}
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2022 FliPPeDround <https://github.com/FliPPeDround>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
> create-vue is released under the MIT license:
> MIT License
> Copyright (c) 2021-present vuejs
> Permission is hereby granted, free of charge, to any person obtaining a copy
> of this software and associated documentation files (the "Software"), to deal
> in the Software without restriction, including without limitation the rights
> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> copies of the Software, and to permit persons to whom the Software is
> furnished to do so, subject to the following conditions:
> The above copyright notice and this permission notice shall be included in all
> copies or substantial portions of the Software.
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
> SOFTWARE.
================================================
FILE: README.md
================================================
<img src='./blink.svg' />
<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>
<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>
<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>
<br />
# 📦 使用
```shell
# npm
npm create uni@latest
# yarn
yarn create uni
# pnpm
pnpm create uni
```
> [!IMPORTANT]
> 建议添加上标记名(@latest),否则 npm 可能会解析到缓存的过时软件包版本。
>
<!-- <img src='./Terminal.svg' /> -->
## 📖 介绍
`create-uni` 是一个用于快速创建 uni-app 项目的轻量脚手架工具,它可以帮助你快速创建一个基于`vite`和`vue3`的`uni-app`项目,同时提供了一些模板供你选择。
<p align="center"><img src=".github/image/demo.png"></p>
## 🚤 快速使用
```shell
pnpm create uni --gui
```
```shell
pnpm create uni <项目名称> --ts -m pinia -m uniUse -u ano -e
```
```shell
npx @create-uni/info@latest
# --info 获取当前项目环境信息
```
### 参数说明
| 配置项 | 参数 | 别名 | 可选值 |
| :---: | :---: | :---: | :---: |
| Template | —— | t | 见[模板列表](#模板列表) |
| TypeScript | ts | —— | —— |
| Plugin | pluginList | p | 见[插件列表](#插件列表) |
| Module | moduleList | m | 见[模块列表](#模块列表) |
| UI | ui | u | 见[组件列表](#组件列表) |
| Eslint | eslint | e | —— |
| gui | gui | —— | —— |
| info | info | —— | —— |
#### 📦模板列表
| 模板名 | 描述 | 参数名 |
| :---: | :---: | :---: |
| [vitesse-uni-app](https://github.com/uni-helper/vitesse-uni-app) | 由 Vite & uni-app 驱动的跨端快速启动模板 | vitesse |
| [wot-starter](https://github.com/wot-ui/wot-starter) | 基于 vitesse-uni-app 的 wot-ui 快速起手模板 (集成 wot-ui v1) | wot-starter |
| [wot-starter-v2](https://github.com/wot-ui/wot-starter/tree/v2) | 基于 vitesse-uni-app 的 wot-ui 快速起手模板 (集成 @wot-ui/ui@2) | wot-starter-v2 |
| [wot-starter-retail](https://github.com/wot-ui/wot-starter-retail) | 基于 wot-ui 的 uni-app 零售行业模板 | wot-starter-retail |
| [uview-pro-starter](https://github.com/anyup/uView-Pro-Starter) | 基于 vitesse-uni-app 的 uView Pro 快速启动模板 | uview-pro-starter |
| [uview-pro-demo](https://github.com/anyup/uView-Pro) | 基于 uView Pro 的完整组件演示模板 | uview-pro-demo |
| [unisave](https://github.com/sunpm/unisave) | 拥抱 web 开发,拯救 uniapp。适配所有 (app、mp、web) 平台 | unisave |
| [tmui 3.2](https://tmui.design) | 优质 Vue3 TS Pinia Vite 跨端组件库 | tmui32 |
#### 📦插件列表
| 插件名 | 描述 | 参数名 |
| :---: | :---: | :---: |
| [vite-plugin-uni-components](https://github.com/uni-helper/vite-plugin-uni-components) | 按需自动引入组件 | import |
| [vite-plugin-uni-pages](https://github.com/uni-helper/vite-plugin-uni-pages) | 提供基于文件系统的路由 | pages |
| [vite-plugin-uni-layouts](https://github.com/uni-helper/vite-plugin-uni-layouts) | 提供类 nuxt 的 layouts 系统 | layouts |
| [vite-plugin-uni-manifest](https://github.com/uni-helper/vite-plugin-uni-manifest) | 自动生成 manifest.json 文件 | manifest |
| [vite-plugin-uni-platform](https://github.com/uni-helper/vite-plugin-uni-platform) | 基于文件名 (*.<h5\|mp-weixin\|app>.*) 的按平台编译插件 | filePlatform |
| [uni-ku-root](https://github.com/uni-ku/root) | 模拟虚拟根组件 (支持 SFC 的 App.vue) | root |
| [vite-plugin-component-placeholder](https://github.com/chouchouji/vite-plugin-component-placeholder) | 占位组件的原生实现 | componentPlaceholder |
#### 📦模块列表
| 模块名 | 描述 | 参数名 |
| :---: | :---: | :---: |
| [pinia](https://github.com/vuejs/pinia) | 符合直觉的 Vue.js 状态管理库 | pinia |
| [unocss](https://github.com/antfu/unocss) | 即时按需的原子级 CSS 引擎 | unocss |
| [vitest](https://github.com/uni-helper/vitest-environment-uniapp) | 基于 Vite 的测试框架 | vitest |
| [uni-network](https://github.com/uni-helper/uni-network) | 为 uni-app 打造的基于 Promise 的网络请求库 | uniNetwork |
| [uni-use](https://github.com/uni-helper/uni-use) | uni-app 组合式工具集 | uniUse |
| [uni-promises](https://github.com/uni-helper/uni-promises) | 为 uni-app 提供的 Promise 包装器 | uniPromises |
| [uni-echarts](https://uni-echarts.xiaohe.ink) | 适用于 uni-app 的 Apache ECharts 组件 | uniEcharts |
| [z-paging](https://github.com/SmileZXLee/uni-z-paging) | 高性能、全平台兼容的 uni-app 分页组件 | zPaging |
#### 📦组件列表
| 组件名 | 描述 | 参数名 |
| :---: | :---: | :---: |
| [uni-ui](https://uniapp.dcloud.net.cn/component/uniui/uni-ui.html) | UniApp 官方组件库 | uni |
| [wot-ui](https://v1.wot-ui.cn/) | 高颜值、轻量化的 uni-app 组件库(v1) | wot |
| [wot-ui v2](https://wot-ui.cn/) | 轻量、美观、AI友好的 uni-app 组件库 | wot2 |
| [TDesign](https://tdesign.tencent.com/uniapp/) | TDesign 组件库 uni-app 版 | tdesign |
| [uView-Pro](https://uviewpro.cn/) | 全面支持 Vue3.0、TypeScript 的 uni-app 生态框架 | uview-pro |
| [nutui-uniapp](https://uniapp-nutui.tech/) | 京东风格的轻量级移动端组件库 | nut |
| [uv-ui](https://www.uvui.cn/components/intro.html) | 多平台快速开发的 UI 框架 | uv |
| [ano-ui](https://ano-ui.netlify.app/) | 轻量级、漂亮、快速的 UnoCSS 组件库 | ano |
## 🤝 参与贡献
- 提交新功能
- 反馈/解决[`issues`](https://github.com/uni-helper/create-uni/issues)
- 提交新[`模板`](./packages/config/src/template.data.ts)/[`插件`](./packages/config/src/plugin.data.ts)/[`模块`](./packages/config/src/module.data.ts)/[`组件库`](./packages/config/src/ui.data.ts)
## 🛠️ 开发
- Node.js 版本 20+
- Rust 版本 1.64+
- 必须使用`pnpm`作为包管理工具
- `Clone`此仓库
- `pnpm i`安装依赖
- `pnpm dev`运行
- 可本地执行`pnpm create-uni`测试
## 🌸 感谢
项目灵感及部分代码来自 [create-vue](https://github.com/vuejs/create-vue)
## 📄 License
[MIT LICENSE](./LICENSE)
## 🙇🏻♂️[赞助](https://afdian.com/a/flippedround)
<p align="center">
<a href="https://afdian.com/a/flippedround">
<img alt="sponsors" src="https://cdn.jsdelivr.net/gh/FliPPeDround/sponsors/sponsorkit/sponsors.svg"/>
</a>
</p>
================================================
FILE: eslint.config.js
================================================
import uni from '@uni-helper/eslint-config'
export default uni({
rules: {
'no-console': 'warn',
},
ignores: [
'dist/outfile.cjs',
'packages/gui',
'packages/core/template/**/*.test.js',
],
})
================================================
FILE: package.json
================================================
{
"name": "@create-uni/monorepo",
"type": "module",
"private": true,
"packageManager": "pnpm@9.9.0",
"description": "轻松创建你的 uni-app 项目",
"author": "FliPPeDround <flippedround@qq.com>",
"license": "MIT",
"funding": "https://afdian.com/a/flippedround",
"homepage": "https://github.com/uni-helper/create-uni#readme",
"repository": {
"type": "git",
"url": "git+https://github.com/uni-helper/create-uni.git"
},
"bugs": "https://github.com/uni-helper/create-uni/issues",
"keywords": [
"uni",
"uni-app",
"create-uni",
"cli",
"vue",
"miniapp",
"create"
],
"scripts": {
"dev:shared": "turbo dev --filter=./packages/shared",
"dev:core": "turbo dev --filter=./packages/core",
"dev:gui": "turbo dev --filter=./packages/gui",
"dev:info": "turbo dev --filter=./packages/info",
"dev:mcp": "turbo dev --filter=./packages/mcp",
"build:core": "cd ./packages/core && pnpm build",
"build:info": "cd ./packages/info && pnpm build",
"build:ui": "cd ./packages/ui && pnpm build",
"build:mcp": "cd ./packages/mcp && pnpm build",
"release:core": "cd ./packages/core && pnpm release",
"release:info": "cd ./packages/info && pnpm release",
"release:mcp": "cd ./packages/mcp && pnpm release",
"release:gui": "cd ./packages/gui && pnpm release",
"dev": "turbo run dev",
"build": "turbo build",
"lint": "eslint .",
"lint:fix": "eslint . --fix && cd ./packages/gui && cargo fmt",
"typecheck": "tsc --noEmit",
"postinstall": "node scripts/link.cjs",
"up": "cd ./packages/core && pnpm run up"
},
"devDependencies": {
"@antfu/ni": "^0.23.0",
"@types/node": "^18.19.50",
"@uni-helper/eslint-config": "^0.2.0",
"bumpp": "^9.5.2",
"consola": "^3.3.3",
"cross-env": "^7.0.3",
"eslint": "^9.10.0",
"lint-staged": "^15.2.10",
"nodemon": "^3.1.9",
"simple-git-hooks": "^2.11.1",
"terser": "^5.31.6",
"tsup": "^8.2.4",
"turbo": "^2.3.3",
"typescript": "^5.5.4",
"unplugin-preprocessor-directives": "^1.0.3",
"vitest": "^3.2.4"
},
"simple-git-hooks": {
"pre-commit": "pnpm lint-staged"
},
"lint-staged": {
"*": "eslint --fix"
}
}
================================================
FILE: packages/config/package.json
================================================
{
"name": "@create-uni/config",
"type": "module",
"version": "0.0.1",
"private": true,
"packageManager": "pnpm@9.9.0",
"description": "create-uni 模块配置",
"author": "FliPPeDround <flippedround@qq.com>",
"license": "MIT",
"funding": "https://afdian.com/a/flippedround",
"homepage": "https://github.com/uni-helper/create-uni#readme",
"repository": {
"directory": "packages/config",
"type": "git",
"url": "git+https://github.com/uni-helper/create-uni.git"
},
"bugs": "https://github.com/uni-helper/create-uni/issues",
"exports": {
".": "./src/index.ts",
"./*": "./*"
},
"main": "./src/index.ts",
"typesVersions": {
"*": {
"*": [
"./*"
]
}
},
"files": [
"src"
],
"dependencies": {
"kolorist": "^1.8.0"
}
}
================================================
FILE: packages/config/src/index.ts
================================================
import type { BaseTemplateListWithList, Options, TemplateList, TemplateValue } from './type'
import MODULES from './module.data'
import PLUGINS from './plugin.data'
import TEMPLATES from './template.data'
import UI from './ui.data'
export {
MODULES,
PLUGINS,
TEMPLATES,
UI,
}
export type {
BaseTemplateListWithList,
Options,
TemplateList,
TemplateValue,
}
================================================
FILE: packages/config/src/module.data.ts
================================================
import type { Options } from './type'
import { trueColor as rgb } from 'kolorist'
export default [
{
label: rgb(235, 186, 43)('Pinia'),
value: 'pinia',
name: 'pinia',
website: 'https://pinia.vuejs.org/zh/',
github: 'https://github.com/vuejs/pinia',
hint: '符合直觉的 Vue.js 状态管理库',
},
{
label: rgb(204, 204, 204)('Unocss'),
value: 'unocss',
name: 'unocss',
github: 'https://github.com/unocss/unocss',
website: 'https://unocss.dev/',
hint: '即时按需的原子级 CSS 引擎',
},
{
label: rgb(56, 204, 110)('Vitest'),
value: 'vitest',
name: 'vitest',
github: 'https://github.com/uni-helper/vitest-environment-uniapp',
website: 'https://vitest.dev/',
hint: 'Vitest 是一个基于 Vite 的测试框架',
},
{
label: rgb(108, 92, 231)('uni-network'),
value: 'uniNetwork',
name: 'uni-network',
github: 'https://github.com/uni-helper/uni-network',
website: 'https://uni-network.netlify.app/',
hint: '为 uni-app 打造的基于 Promise 的网络请求库',
},
{
label: rgb(63, 168, 125)('uni-use'),
value: 'uniUse',
name: 'uni-use',
github: 'https://github.com/uni-helper/uni-use',
website: 'https://uni-helper.github.io/uni-use/',
hint: 'uni-app 组合式工具集',
},
{
label: rgb(52, 152, 219)('uni-promises'),
value: 'uniPromises',
name: 'uni-promises',
github: 'https://github.com/uni-helper/uni-promises',
hint: 'uni-app promise 化的 API',
},
{
label: rgb(24, 121, 78)('uni-echarts'),
value: 'uniEcharts',
name: 'uni-echarts',
github: 'https://github.com/xiaohe0601/uni-echarts',
hint: '适用于 uni-app 的 Apache ECharts 组件',
},
{
label: rgb(0, 122, 255)('z-paging'),
value: 'zPaging',
name: 'z-paging',
github: 'https://github.com/SmileZXLee/uni-z-paging',
hint: '高性能、全平台兼容的 uni-app 分页组件',
},
] as const satisfies readonly Options[]
================================================
FILE: packages/config/src/plugin.data.ts
================================================
import type { Options } from './type'
import { trueColor as rgb } from 'kolorist'
export default [
{
label: rgb(236, 112, 99)('vite-plugin-uni-components'),
value: 'import',
name: 'vite-plugin-uni-components',
hint: '按需自动引入组件',
github: 'https://github.com/uni-helper/vite-plugin-uni-components',
},
{
label: rgb(243, 156, 18)('vite-plugin-uni-pages'),
value: 'pages',
name: 'vite-plugin-uni-pages',
hint: '提供基于文件系统的路由',
github: 'https://github.com/uni-helper/vite-plugin-uni-pages',
},
{
label: rgb(241, 196, 15)('vite-plugin-uni-layouts'),
value: 'layouts',
name: 'vite-plugin-uni-layouts',
hint: '提供类 nuxt 的 layouts 系统',
github: 'https://github.com/uni-helper/vite-plugin-uni-layouts',
},
{
label: rgb(46, 204, 113)('vite-plugin-uni-manifest'),
value: 'manifest',
name: 'vite-plugin-uni-manifest',
hint: '自动生成 manifest.json 文件',
github: 'https://github.com/uni-helper/vite-plugin-uni-manifest',
},
{
label: rgb(52, 152, 219)('vite-plugin-uni-platform'),
value: 'filePlatform',
name: 'vite-plugin-uni-platform',
hint: '基于文件名 (*.<h5|mp-weixin|app>.*) 的按平台编译插件',
github: 'https://github.com/uni-helper/vite-plugin-uni-platform',
},
{
label: rgb(146, 220, 210)('uni-ku-root'),
value: 'root',
name: 'uni-ku-root',
hint: '模拟虚拟根组件(支持SFC的App.vue)',
github: 'https://github.com/uni-ku/root',
},
{
label: rgb(102, 153, 51)('vite-plugin-component-placeholder'),
value: 'componentPlaceholder',
name: 'vite-plugin-component-placeholder',
hint: '占位组件的原生实现',
github: 'https://github.com/chouchouji/vite-plugin-component-placeholder',
},
] as const satisfies readonly Options[]
================================================
FILE: packages/config/src/template.data.ts
================================================
import type { TemplateList } from './type'
import { green, lightMagenta, trueColor as rgb } from 'kolorist'
export default [
{
label: `vitesse-uni-app`,
description: `由${green('Uni Helper')}维护的快速启动模板`,
value: 'vitesse',
url: {
github: 'https://github.com/uni-helper/vitesse-uni-app.git',
},
website: 'https://vitesse-docs.netlify.app/',
playground: 'https://vitesse-uni-app.netlify.app/',
},
{
label: `wot`,
description: `由${green('Wot UI')}提供的基于 vitesse-uni-app 的快速启动模板`,
value: 'wot',
list: [
{
label: `wot-starter`,
description: `由${rgb(77, 128, 240)('Wot UI')}提供的基于 vitesse-uni-app 的快速启动模板(集成 wot-ui v1)`,
value: 'wot-starter',
url: {
github: '-b v1 https://github.com/wot-ui/wot-starter.git',
},
website: 'https://starter-v1.wot-ui.cn/',
playground: 'https://starter-v1.wot-ui.cn/demo/#/',
},
{
label: `wot-starter-v2`,
description: `由${rgb(77, 128, 240)('Wot UI')}提供的基于 vitesse-uni-app 的快速启动模板(集成 @wot-ui/ui@2)`,
value: 'wot-starter-v2',
url: {
github: '-b v2 https://github.com/wot-ui/wot-starter.git',
},
website: 'https://starter.wot-ui.cn/',
playground: 'https://starter.wot-ui.cn/demo/#/',
},
{
label: 'wot-starter-retail',
description: `基于${rgb(77, 128, 240)('Wot UI')}的 uni-app 零售行业模板`,
value: 'wot-starter-retail',
url: {
github: 'https://github.com/wot-ui/wot-starter-retail.git',
},
playground: 'https://starter-retail.wot-ui.cn/',
},
],
},
{
label: `uView Pro`,
description: `由 ${green('uView Pro')} 提供的快速开发模板`,
value: 'uview-pro',
list: [
{
label: `uView-Pro-Starter`,
description: `由 ${green('uView Pro')} 提供的基于 vitesse-uni-app 的快速启动模板`,
value: 'uview-pro-starter',
url: {
github: 'https://github.com/anyup/uView-Pro-Starter.git',
},
website: 'https://uviewpro.cn/',
playground: 'https://h5.uviewpro.cn/',
},
{
label: `uView-Pro-Demo`,
description: `由 ${green('uView Pro')} 提供的完整组件演示模板`,
value: 'uview-pro-demo',
url: {
github: 'https://github.com/anyup/uView-Pro.git',
},
website: 'https://uviewpro.cn/',
playground: 'https://h5.uviewpro.cn/',
},
],
},
{
label: `unisave`,
description: `拥抱 web 开发,${lightMagenta('拯救')}uniapp。适配所有 (app、mp、web) 平台`,
value: 'unisave',
url: {
github: 'https://github.com/sunpm/unisave.git',
},
website: 'https://unisave-docs.netlify.app/',
playground: 'https://uni-save.netlify.app/',
},
{
label: `tmui3.2`,
description: `优质 Vue3 TS Pinia Vite 跨端组件库模板`,
value: 'tmui32',
url: {
gitee: 'https://gitee.com/LYTB/tmui-design.git',
},
website: 'https://tmui.design/',
playground: 'https://tmui.design/h5by32/',
},
] as TemplateList[]
================================================
FILE: packages/config/src/type.d.ts
================================================
export interface Options {
label: string
hint: string
value: string | null
name: string
github?: string
website?: string
}
interface GithubGitee {
github: string
gitee: string
}
type AtLeastOne<T, U = { [K in keyof T]: Pick<T, K> }> = Partial<T> & U[keyof U]
interface BaseTemplateListCommon {
/**
* 模板名称
*/
label: string
/**
* 模板类型 不能为custom
* @property {string} type - 模板类型
*/
value: string
/**
* 模板描述
*/
description?: string
/**
* 官方网站
*/
website?: string
/**
* 演练场
*/
playground?: string
/**
* 模板下载完成后的回调函数
* @param {string} root - 模板下载的根目录
*/
callBack?: (root: string) => void
}
interface BaseTemplateListWithUrl extends BaseTemplateListCommon {
/**
* 模板地址 github和gitee地址至少存在一个
* @property {string} github - github地址
* @property {string} gitee - gitee地址
*/
url: AtLeastOne<GithubGitee>
list?: never // 确保list不会出现在这个类型中
}
export interface BaseTemplateListWithList extends BaseTemplateListCommon {
url?: never // 确保url不会出现在这个类型中
/**
* 模板列表
* @type {BaseTemplateListWithUrl[]} - 模板列表
*/
list: BaseTemplateListWithUrl[]
}
type BaseTemplateList = BaseTemplateListWithUrl | BaseTemplateListWithList
export type TemplateList = BaseTemplateList
interface CustomTempValue {
type: 'custom'
}
export interface UnCustomTempValue {
type: string
url: AtLeastOne<GithubGitee>
callBack?: (root: string) => void
}
export type TemplateValue = UnCustomTempValue | CustomTempValue
================================================
FILE: packages/config/src/ui.data.ts
================================================
import type { Options } from './type'
import { green, trueColor as rgb } from 'kolorist'
export default [
{
label: '不需要组件库',
name: '不需要组件库',
hint: '',
value: null,
},
{
label: green('Uni Ui'),
hint: 'UniApp官方组件库',
name: 'uni-ui',
value: 'uni',
website: 'https://uniapp.dcloud.net.cn/component/uniui/uni-ui.html',
},
{
label: rgb(77, 128, 240)('Wot Ui'),
hint: '高颜值、轻量化的uni-app组件库',
name: 'wot-design-uni',
value: 'wot',
github: 'https://github.com/Moonofweisheng/wot-design-uni',
website: 'https://v1.wot-ui.cn/',
},
{
label: rgb(28, 100, 253)('Wot Ui V2'),
hint: '轻量、美观、AI友好的 uni-app 组件库',
name: 'wot-ui',
value: 'wot2',
github: 'https://github.com/wot-ui/wot-ui',
website: 'https://wot-ui.cn/',
},
{
label: rgb(0, 82, 217)('TDesign Uni'),
hint: 'TDesign 组件库 uni-app 版',
name: 'TDesign',
value: 'tdesign',
github: 'https://github.com/Tencent/tdesign-miniprogram',
website: 'https://tdesign.tencent.com/uniapp/',
},
{
label: rgb(41, 121, 255)('uView Pro'),
hint: '全面支持 Vue3.0、TypeScript 的 uni-app 生态框架',
name: 'uView Pro',
value: 'uview-pro',
github: 'https://github.com/anyup/uView-Pro',
website: 'https://uviewpro.cn/',
},
{
label: rgb(250, 44, 25)('Nut Ui'),
hint: '京东风格的轻量级移动端组件库',
name: 'nutui-uniapp',
value: 'nut',
github: 'https://github.com/nutui-uniapp/nutui-uniapp',
website: 'https://nutui-uniapp.pages.dev/',
},
{
label: rgb(60, 156, 255)('Uv Ui'),
hint: '多平台快速开发的UI框架',
name: 'uv-ui',
value: 'uv',
github: 'https://github.com/climblee/uv-ui',
website: 'https://www.uvui.cn/',
},
{
label: rgb(147, 85, 224)('Ano UI'),
hint: '轻量级、漂亮、快速的 UnoCSS 组件库',
name: 'ano-ui',
value: 'ano',
github: 'https://github.com/ano-ui/ano-ui',
website: 'https://ano-ui.netlify.app/',
},
] as const satisfies readonly Options[]
================================================
FILE: packages/core/.gitignore
================================================
# Created by .ignore support plugin (hsz.mobi)
### Node template
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# TypeScript v1 declaration files
typings/
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
# parcel-bundler cache (https://parceljs.org/)
.cache
# next.js build output
.next
# nuxt.js build output
.nuxt
# Nuxt generate
dist
# vuepress build output
.vuepress/dist
# Serverless directories
.serverless
# IDE
.idea
# turborepo
.turbo
================================================
FILE: packages/core/bump.config.ts
================================================
// bump.config.ts
import { defineConfig } from 'bumpp'
export default defineConfig({
tag: 'core-v%s',
})
================================================
FILE: packages/core/package.json
================================================
{
"name": "create-uni",
"type": "module",
"version": "2.15.0",
"packageManager": "pnpm@9.9.0",
"description": "轻松创建你的 uni-app 项目",
"author": "FliPPeDround <flippedround@qq.com>",
"license": "MIT",
"funding": "https://afdian.com/a/flippedround",
"homepage": "https://github.com/uni-helper/create-uni#readme",
"repository": {
"directory": "packages/core",
"type": "git",
"url": "git+https://github.com/uni-helper/create-uni.git"
},
"bugs": "https://github.com/uni-helper/create-uni/issues",
"keywords": [
"uni",
"uni-app",
"create-uni",
"cli",
"vue",
"miniapp",
"create"
],
"sideEffects": false,
"bin": {
"create-uni": "dist/outfile.cjs"
},
"files": [
"dist/outfile.cjs",
"template"
],
"scripts": {
"build": "tsup",
"dev": "cross-env CREATE_UNI_DEV=true tsup --watch",
"prepublishOnly": "nr build",
"release": "bumpp",
"up": "cd ./template && pnpx taze@latest major -w -r && cd ./base && pnpx @dcloudio/uvm@latest --manager pnpm"
},
"devDependencies": {
"@clack/prompts": "^0.9.0",
"@create-uni/config": "workspace:*",
"@create-uni/shared": "workspace:*",
"@types/cross-spawn": "^6.0.6",
"@types/ejs": "^3.1.5",
"@types/minimist": "^1.2.5",
"cross-spawn": "^7.0.6",
"ejs": "^3.1.10",
"kolorist": "^1.8.0",
"minimist": "^1.2.8"
}
}
================================================
FILE: packages/core/src/command/actions/gui.ts
================================================
import process from 'node:process'
import { MODULES, PLUGINS, TEMPLATES, UI } from '@create-uni/config'
import { sync } from 'cross-spawn'
import { composeCommand } from '../composeCommand'
export function actionGuiCLI() {
// #if CREATE_UNI_DEV
// @ts-expect-error compile
const fullCustomCommand = 'pnpm create-uni-gui'
// #endif
// #if !CREATE_UNI_DEV
// @ts-expect-error compile
// eslint-disable-next-line ts/no-redeclare
const fullCustomCommand = composeCommand('@create-uni/gui')
// #endif
const input = JSON.stringify({
templateList: TEMPLATES,
plugin: PLUGINS,
module: MODULES,
ui: UI,
})
const [command, ..._args] = fullCustomCommand.split(' ')
process.env.CREATE_UNI_GUI_INPUT = input
const { error, stdout } = sync(command, [..._args], {
stdio: 'pipe',
})
if (error)
throw new Error(`Error executing command: ${error.message}`)
let data: any
if (stdout.length > 0) {
const data_string = stdout.toString()
try {
const _data = JSON.parse(data_string)
if (_data.useTemplate) {
if (_data.projectName === '') {
_data.projectName = 'uni-app'
}
if (_data.useTemplate === 'custom') {
_data.useTemplate = null
}
data = _data
}
}
catch {
process.exit(0)
}
}
if (!data?.projectName) {
process.exit(0)
}
return data
}
================================================
FILE: packages/core/src/command/actions/info.ts
================================================
import { sync } from 'cross-spawn'
import { composeCommand } from '../composeCommand'
export function actionInfoCLI() {
// #if CREATE_UNI_DEV
// @ts-expect-error compile
const fullCustomCommand = 'pnpm create-uni-info'
// #endif
// #if !CREATE_UNI_DEV
// @ts-expect-error compile
// eslint-disable-next-line ts/no-redeclare
const fullCustomCommand = composeCommand('@create-uni/info')
// #endif
const [command, ..._args] = fullCustomCommand.split(' ')
const { error } = sync(command, [..._args], {
stdio: 'inherit',
})
if (error)
throw new Error(`Error executing command: ${error.message}`)
}
================================================
FILE: packages/core/src/command/composeCommand.ts
================================================
import process from 'node:process'
import { pkgFromUserAgent } from '@/utils'
export function composeCommand(
command: string,
) {
const { name, version } = pkgFromUserAgent(process.env.npm_config_user_agent)!
const isYarn1 = name === 'yarn' && version.startsWith('1.')
let pkgManager = 'npx'
if (name === 'pnpm')
pkgManager = 'pnpm dlx'
if (name === 'yarn')
pkgManager = 'yarn dlx'
if (name === 'bun')
pkgManager = 'bun x'
return `${pkgManager} ${command}${isYarn1 ? '' : '@latest'}`
}
================================================
FILE: packages/core/src/command/index.ts
================================================
import process from 'node:process'
import { helpMessage } from '@/constants'
import { actionGuiCLI } from './actions/gui'
import { actionInfoCLI } from './actions/info'
const actions = {
help: () => {
console.log(helpMessage)
process.exit(0)
},
info: () => {
actionInfoCLI()
process.exit(0)
},
gui: () => {
return actionGuiCLI()
},
}
export function commandAction(argv: any) {
if (argv.help) {
actions.help()
}
else if (argv.info) {
actions.info()
}
else if (argv.gui) {
return actions.gui()
}
}
================================================
FILE: packages/core/src/command/runCommand.ts
================================================
import type { StdioOptions } from 'node:child_process'
import { sync } from 'cross-spawn'
export function runCommand(
fullCustomCommand: string,
stdio: StdioOptions,
argv?: any,
) {
const [command, ..._args] = fullCustomCommand.split(' ')
const { error, stdout } = sync(command, [..._args, argv ?? ''], {
stdio,
})
if (error) {
throw new Error(`Error executing command: ${error.message}`)
}
if (stdout.length > 0) {
console.log(stdout.toString())
}
}
================================================
FILE: packages/core/src/constants/index.ts
================================================
export const helpMessage = `\
使用: create-uni [PROJECT_NAME] [OPTION]...
\n
使用CLI创建uni-app项目。
如果没有参数,则进入交互模式。
\n
选项:
-t 使用特定模板
--ts 使用TypeScript
-p 使用特定插件
-m 使用特定模块
-ui 使用特定UI库
-e 使用eslint
-h, --help 显示帮助信息
-i, --info 显示版本信息
-g, --gui 显示图形界面
`
================================================
FILE: packages/core/src/index.ts
================================================
#!/usr/bin/env node
import type { UnCustomTempValue } from '@create-uni/config/src/type'
import type { Answers } from './question'
import {
existsSync,
mkdirSync,
readFileSync,
renameSync,
rmdirSync,
unlinkSync,
writeFileSync,
} from 'node:fs'
import { resolve } from 'node:path'
import process from 'node:process'
import { intro, outro, spinner } from '@clack/prompts'
import { generateBanner } from '@create-uni/shared'
import ejs from 'ejs'
import { green } from 'kolorist'
import minimist from 'minimist'
import { commandAction } from './command'
import { question } from './question'
import askForceOverwrite from './question/file'
import { cancelMesssage } from './question/onCancel'
import {
dowloadTemplate,
getPkgManager,
jsonStringifyWithoutKeysQuotes,
preOrderDirectoryTraverse,
printFinish,
renderTemplate,
replaceProjectName,
} from './utils'
import { postOrderDirectoryTraverse } from './utils/directoryTraverse'
import {
validateModules,
validatePlugins,
validateTemplateType,
validateUIName,
} from './utils/validateArgv'
async function init() {
const argv = minimist(process.argv.slice(2), {
alias: {
templateType: ['t'],
needsTypeScript: ['ts'],
pluginList: ['p'],
moduleList: ['m'],
UIName: ['ui', 'u'],
needsEslint: ['eslint', 'e'],
help: ['h', 'help'],
info: ['info', 'i'],
gui: ['gui', 'g'],
force: ['force', 'f'],
},
string: ['_'],
})
let result: Answers = {}
const guiData = commandAction(argv)
const projectName = argv._[0] || guiData?.projectName
intro(generateBanner('Uni-creator - 快速创建 uni-app 项目'))
const s = spinner()
if (!projectName) {
try {
result = await question()
}
catch (cancelled) {
// eslint-disable-next-line no-console
console.log((<{ message: string }>cancelled).message)
process.exit(1)
}
}
else if (argv._[0]) {
const templateType = validateTemplateType(argv.templateType)
const UIName = validateUIName(argv.UIName)
const pluginList = validatePlugins(argv.pluginList)
const moduleList = validateModules(argv.moduleList)
const shouldOverwrite = argv.force ? true : await askForceOverwrite(projectName)
result = {
projectName,
shouldOverwrite,
templateType,
needsTypeScript: argv['needsTypeScript'!],
pluginList,
moduleList,
UIName,
needsEslint: argv['needsEslint'!],
}
}
else if (guiData.projectName) {
const templateType = validateTemplateType(guiData.useTemplate)
const UIName = validateUIName(guiData.requireUI)
const pluginList = validatePlugins(guiData.requiredPlugins)
const moduleList = validateModules(guiData.requiredModules)
result = {
projectName: guiData.projectName,
shouldOverwrite: true,
templateType,
needsTypeScript: guiData.requireTypeScript,
pluginList,
moduleList,
UIName,
needsEslint: guiData.requireESLint,
}
}
s.start('正在创建模板...')
const cwd = process.cwd()
const root = resolve(guiData?.installationPath ?? cwd, result.projectName!)
const packageManager = getPkgManager()
function emptyDir(dir: string) {
if (!existsSync(dir))
return
postOrderDirectoryTraverse(
dir,
dir => rmdirSync(dir),
file => unlinkSync(file),
)
}
if (existsSync(root) && result.shouldOverwrite)
emptyDir(root)
else if (!existsSync(root))
mkdirSync(root)
if (result.templateType!.type !== 'custom') {
const { templateType, projectName } = result
await dowloadTemplate(templateType as UnCustomTempValue, projectName!, root, s)
printFinish(root, cwd, packageManager, s)
return
}
const templateRoot = resolve(__dirname, './../template')
type Callback = (dataStore: Record<string, any>) => void
const callbacks: Callback[] = []
function render(templateName: string) {
const templateDir = resolve(templateRoot, templateName)
renderTemplate(templateDir, root, callbacks)
}
// Render templates
render('base')
const needUnocss = result.moduleList?.includes('unocss') || ['ano'].includes(result.UIName!)
const needUI = Boolean(result.UIName)
// Render Config
const config = {
typescript: result.needsTypeScript,
lint: result.needsEslint,
}
for (const [key, needs] of Object.entries(config)) {
if (needs)
render(`config/${key}`)
}
// Render Plugins
result.pluginList?.forEach(plugin => render(`plugin/${plugin}`))
if (needUI && !result.pluginList?.includes('import'))
render('plugin/import')
// Render modules
result.moduleList?.forEach(module => render(`module/${module}`))
if (needUnocss && !result.moduleList?.includes('unocss'))
render('module/unocss')
// Render UI
const UI = {
unocss: needUnocss,
[result.UIName!]: needUI,
}
for (const [key, needs] of Object.entries(UI)) {
if (needs)
render(`UI/${key}`)
}
const dataStore: Record<string, any> = {}
// Process callbacks
for (const cb of callbacks)
await cb(dataStore)
preOrderDirectoryTraverse(
root,
() => {},
(filepath) => {
if (filepath.endsWith('.ejs')) {
const template = readFileSync(filepath, 'utf-8')
const dest = filepath.replace(/\.ejs$/, '')
if (dest.includes('vite.config') && dataStore[dest].extraConfig)
dataStore[dest].extraConfig = jsonStringifyWithoutKeysQuotes(dataStore[dest].extraConfig)
const content = ejs.render(template, dataStore[dest])
writeFileSync(dest, content)
unlinkSync(filepath)
}
},
)
if (result.needsTypeScript) {
preOrderDirectoryTraverse(
root,
() => {},
(filepath) => {
// Rename `.js` to `.ts`
if (filepath.endsWith('.js') && !filepath.endsWith('eslint.config.js')) {
const tsFilePath = filepath.replace(/\.js$/, '.ts')
if (existsSync(tsFilePath))
unlinkSync(filepath)
else
renameSync(filepath, tsFilePath)
}
// Rename 'jsconfig.json' to 'tsconfig.json
else if (filepath.endsWith('jsconfig.json')) {
const tsFilePath = filepath.replace('jsconfig.json', 'tsconfig.json')
if (existsSync(tsFilePath))
unlinkSync(filepath)
else
renameSync(filepath, tsFilePath)
}
},
)
// Rename entry in `index.html`
const indexHtmlPath = resolve(root, 'index.html')
const indexHtmlContent = readFileSync(indexHtmlPath, 'utf8')
writeFileSync(indexHtmlPath, indexHtmlContent.replace('src/main.js', 'src/main.ts'))
// Rename <script setup> To <script setup lang="ts">
preOrderDirectoryTraverse(
resolve(root, 'src'),
() => {},
(filepath) => {
if (filepath.endsWith('.vue')) {
const vueContent = readFileSync(filepath, 'utf8')
const vueContentWithTs = vueContent.replace('<script setup>', '<script setup lang="ts">')
writeFileSync(filepath, vueContentWithTs)
}
},
)
}
replaceProjectName(root, result.projectName!)
printFinish(root, cwd, packageManager, s)
}
init()
.catch((error) => {
outro(cancelMesssage)
console.log(error.message.includes('操作已取消') ? '' : error)
console.log(`🚀 遇到问题? 快速反馈:${green('https://github.com/uni-helper/create-uni/issues/new/choose')}`)
process.exit(0)
})
================================================
FILE: packages/core/src/question/choices.ts
================================================
import { confirm } from '@clack/prompts'
export function needsTypeScript() {
return confirm({
message: '是否使用 TypeScript 语法?',
active: '是',
inactive: '否',
initialValue: false,
})
}
export function needsEslint() {
return confirm({
message: '是否使用 ESLint?',
active: '是',
inactive: '否',
initialValue: true,
})
}
================================================
FILE: packages/core/src/question/file.ts
================================================
import { confirm, isCancel } from '@clack/prompts'
import { canSkipEmptying } from '@create-uni/shared'
import { printCancel } from './onCancel'
export default async (targetDir: string): Promise<boolean | undefined> => {
if (canSkipEmptying(targetDir))
return true
const message = `${targetDir === '.' ? '当前文件' : `目标文件"${targetDir}"`}非空,是否覆盖?`
const shouldOverwrite = await confirm({
message,
active: '是',
inactive: '否',
})
if (shouldOverwrite === false || isCancel(shouldOverwrite)) {
printCancel()
}
else {
return shouldOverwrite
}
}
================================================
FILE: packages/core/src/question/index.ts
================================================
import type { TemplateValue } from './template/type'
import { group } from '@clack/prompts'
import { needsEslint, needsTypeScript } from './choices'
import askForceOverwrite from './file'
import moduleList from './module'
import projectName from './name'
import { printCancel } from './onCancel'
import pluginList from './plugin'
import templateType from './template'
import UIName from './ui'
export interface Answers {
projectName?: string
shouldOverwrite?: boolean
templateType?: TemplateValue
needsTypeScript?: boolean
pluginList?: string[]
moduleList?: string[]
UIName?: string | null
needsEslint?: boolean
}
export async function question(): Promise<Answers> {
const answersName = await group(
{
projectName,
shouldOverwrite: ({ results }) => {
return askForceOverwrite(results.projectName!)
},
},
{
onCancel() {
printCancel()
},
},
) as Answers
const template = await templateType()
if (template.type !== 'custom') {
return {
...answersName,
templateType: template,
}
}
const answerOptions = await group(
{
needsTypeScript,
pluginList,
moduleList,
UIName,
needsEslint,
},
{
onCancel() {
printCancel()
},
},
) as Answers
return {
...answersName,
...answerOptions,
templateType: template,
}
}
================================================
FILE: packages/core/src/question/module/index.ts
================================================
import type { MultiSelectOptions } from '@clack/prompts'
import { multiselect } from '@clack/prompts'
import { MODULES } from '@create-uni/config'
export default () => (
multiselect({
message: '选择需要的库:',
options: MODULES as unknown as MultiSelectOptions<string>['options'],
required: false,
})
)
================================================
FILE: packages/core/src/question/name.ts
================================================
import { text } from '@clack/prompts'
export default () => (
text({
message: '请输入项目名称:',
placeholder: 'uni-app',
validate: (value) => {
if (!value)
return '项目名称不能为空'
},
})
)
================================================
FILE: packages/core/src/question/onCancel.ts
================================================
import process from 'node:process'
import { cancel } from '@clack/prompts'
export const cancelMesssage = '操作已取消'
export function printCancel() {
cancel(cancelMesssage)
process.exit(0)
}
================================================
FILE: packages/core/src/question/plugin/index.ts
================================================
import type { MultiSelectOptions } from '@clack/prompts'
import { multiselect } from '@clack/prompts'
import { PLUGINS } from '@create-uni/config'
export default () => (
multiselect({
message: '选择需要的vite插件:',
options: PLUGINS as unknown as MultiSelectOptions<string>['options'],
required: false,
})
)
================================================
FILE: packages/core/src/question/template/index.ts
================================================
import type { BaseTemplateListWithList, TemplateValue } from '@create-uni/config'
import process from 'node:process'
import { cancel, isCancel, select } from '@clack/prompts'
import { TEMPLATES } from '@create-uni/config'
import { cancelMesssage } from '../onCancel'
export default async (): Promise<TemplateValue> => {
const templateType = await select({
message: '请选择 uni-app 模板:',
options: [
{
label: '自定义模板',
value: 'custom',
},
...TEMPLATES.map(item => ({
label: `${item.label}${item.list ? ' ▼' : ''}`,
value: item.value,
hint: item.description,
})),
],
initialValue: 'custom',
})
if (isCancel(templateType)) {
cancel(cancelMesssage)
process.exit(0)
}
if (templateType === 'custom') {
return { type: 'custom' }
}
const group = TEMPLATES.find((item) => {
if (item.value === templateType && item.list) {
return true
}
return false
}) as BaseTemplateListWithList | undefined
if (group) {
const template = await select({
message: `请选择 ${templateType} 模板`,
options: group.list.map(item => ({
label: item.label,
value: item.value,
hint: item.description,
})),
})
if (isCancel(template)) {
cancel(cancelMesssage)
process.exit(0)
}
else {
const temp = group.list.find(item => item.value === template)!
return {
type: template,
url: temp.url,
callBack: temp?.callBack,
}
}
}
else {
const temp = TEMPLATES.find(item => item.value === templateType)!
return {
type: templateType,
url: temp.url!,
callBack: temp?.callBack,
}
}
}
================================================
FILE: packages/core/src/question/type.d.ts
================================================
export interface Options {
label: string
hint: string
value: string | null
name: string
github?: string
website?: string
}
================================================
FILE: packages/core/src/question/ui/index.ts
================================================
import type { SelectOptions } from '@clack/prompts'
import { select } from '@clack/prompts'
import { UI } from '@create-uni/config'
export default () => (
select({
message: '选择需要的组件库:',
options: UI as unknown as SelectOptions<string>['options'],
})
)
================================================
FILE: packages/core/src/utils/clearFile.ts
================================================
import * as fs from 'node:fs'
import * as path from 'node:path'
export function clearDirectory(directoryPath: string): void {
// 获取目录下的所有文件和子目录
const files = fs.readdirSync(directoryPath)
// 遍历所有文件和子目录
for (const file of files) {
const filePath = path.join(directoryPath, file)
// 如果是子目录,则递归清空子目录
if (fs.statSync(filePath).isDirectory()) {
clearDirectory(filePath)
}
else {
// 如果是文件,则删除文件
fs.unlinkSync(filePath)
}
}
}
================================================
FILE: packages/core/src/utils/cloneRepo.ts
================================================
import type { spinner } from '@clack/prompts'
import type { UnCustomTempValue } from '@create-uni/config/src/type'
import { exec } from 'node:child_process'
import { promises as fs } from 'node:fs'
import { join } from 'node:path'
import process from 'node:process'
import { bold } from 'kolorist'
import { replaceProjectName } from './setPackageName'
async function removeGitFolder(localPath: string): Promise<void> {
const gitFolderPath = join(localPath, '.git')
await fs.rm(gitFolderPath, { recursive: true, force: true })
}
async function cloneRepo(gitUrls: string[], localPath: string): Promise<void> {
let lastError = null
for (const gitUrl of gitUrls) {
try {
await new Promise<void>((resolve, reject) => {
exec(`git clone ${gitUrl} ${localPath}`, async (error) => {
if (error) {
reject(error)
return
}
try {
await removeGitFolder(localPath)
resolve()
}
catch (error) {
reject(error)
}
})
})
return
}
catch (error) {
lastError = error
}
}
if (lastError) {
// @ts-expect-error 类型断言
throw new Error(lastError)
}
}
function getRepoUrlList(url: UnCustomTempValue['url']) {
const { github, gitee } = url
// 返回一个数组优先使用 gitee,没有则使用 github的镜像地址githubfast.com,最后使用 github
return [gitee, github?.replace('github.com', 'githubfast.com'), github].filter(Boolean) as string[]
}
export async function dowloadTemplate(data: UnCustomTempValue, name: string, root: string, loading: ReturnType<typeof spinner>) {
const repoUrlList = getRepoUrlList(data.url)
try {
await cloneRepo(repoUrlList, root)
}
catch (error) {
loading.stop(`${bold('模板创建失败!')}`, 2)
console.log(error)
process.exit(1)
}
replaceProjectName(root, name)
data.callBack?.(root)
}
================================================
FILE: packages/core/src/utils/deepMerge.ts
================================================
const isObject = (val: any) => val && typeof val === 'object'
const mergeArrayWithDedupe = (a: any, b: any) => Array.from(new Set([...a, ...b]))
/**
* Recursively merge the content of the new object to the existing one
* @param {object} target the existing object
* @param {object} obj the new object
*/
export function deepMerge(target: any, obj: any) {
for (const key of Object.keys(obj)) {
const oldVal = target[key]
const newVal = obj[key]
if (Array.isArray(oldVal) && Array.isArray(newVal))
target[key] = mergeArrayWithDedupe(oldVal, newVal)
else if (isObject(oldVal) && isObject(newVal))
target[key] = deepMerge(oldVal, newVal)
else
target[key] = newVal
}
return target
}
================================================
FILE: packages/core/src/utils/directoryTraverse.ts
================================================
import * as fs from 'node:fs'
import * as path from 'node:path'
type DirectoryTraverse = (dir: string, dirCallback: (dir: string) => void, fileCallback: (file: string) => void) => void
export const preOrderDirectoryTraverse: DirectoryTraverse = (dir, dirCallback, fileCallback) => {
for (const filename of fs.readdirSync(dir)) {
if (filename === '.git')
continue
const fullpath = path.resolve(dir, filename)
if (fs.lstatSync(fullpath).isDirectory()) {
dirCallback(fullpath)
if (fs.existsSync(fullpath))
preOrderDirectoryTraverse(fullpath, dirCallback, fileCallback)
continue
}
fileCallback(fullpath)
}
}
export const postOrderDirectoryTraverse: DirectoryTraverse = (dir, dirCallback, fileCallback) => {
for (const filename of fs.readdirSync(dir)) {
const fullpath = path.resolve(dir, filename)
if (fs.lstatSync(fullpath).isDirectory()) {
postOrderDirectoryTraverse(fullpath, dirCallback, fileCallback)
dirCallback(fullpath)
continue
}
fileCallback(fullpath)
}
}
================================================
FILE: packages/core/src/utils/getCommand.ts
================================================
export function getCommand(packageManager: string, scriptName: string, args?: string) {
if (scriptName === 'install')
return packageManager === 'yarn' ? 'yarn' : `${packageManager} install`
if (args) {
return packageManager === 'npm'
? `npm run ${scriptName} -- ${args}`
: `${packageManager} ${scriptName} ${args}`
}
else {
return packageManager === 'npm' ? `npm run ${scriptName}` : `${packageManager} ${scriptName}`
}
}
================================================
FILE: packages/core/src/utils/getPkgManager.ts
================================================
import process from 'node:process'
export function getPkgManager() {
const pkgInfo = pkgFromUserAgent(process.env.npm_config_user_agent)
return pkgInfo ? pkgInfo.name : 'npm'
}
export function pkgFromUserAgent(userAgent: string | undefined) {
if (!userAgent)
return undefined
const pkgSpec = userAgent.split(' ')[0]
const pkgSpecArr = pkgSpec.split('/')
return {
name: pkgSpecArr[0] || 'npm',
version: pkgSpecArr[1],
}
}
================================================
FILE: packages/core/src/utils/index.ts
================================================
export * from './clearFile'
export * from './cloneRepo'
export * from './directoryTraverse'
export * from './getPkgManager'
export * from './jsonStringifyWithoutKeysQuotes'
export * from './printFinish'
export * from './renderTemplate'
export * from './setPackageName'
================================================
FILE: packages/core/src/utils/injectUtils.ts
================================================
import type { PluginData } from './types'
import { deepMerge } from './deepMerge'
function addResolver(plugin: PluginData, resolver: string) {
if (plugin.initializer == null || plugin.initializer.includes(resolver)) {
return plugin
}
return {
...plugin,
initializer: plugin.initializer.replace(
/(resolvers\s*:\s*\[)([\s\S]*?)(\])/,
(_, prefix, content, suffix) => {
const cont = content.trim()
return `${prefix}${cont}${cont ? ', ' : ''}${resolver}${suffix}`
},
),
}
}
function mergeExtraConfig(oldConfig: Record<string, any> | null, config: Record<string, any>) {
return deepMerge(oldConfig || {}, config)
}
export const injectUtils = {
deepMerge,
addResolver,
mergeExtraConfig,
}
================================================
FILE: packages/core/src/utils/jsonStringifyWithoutKeysQuotes.ts
================================================
export function jsonStringifyWithoutKeysQuotes(obj: object) {
const jsonString = JSON.stringify(obj, null, 2).slice(1, -1).trim()
return jsonString.replace(/"(\w+)":/g, '$1:')
}
================================================
FILE: packages/core/src/utils/printFinish.ts
================================================
import type { spinner } from '@clack/prompts'
import type { getPkgManager } from './getPkgManager'
import { relative } from 'node:path'
import { note } from '@clack/prompts'
import { dim, lightGreen } from 'kolorist'
import { getCommand } from './getCommand'
export function printFinish(
root: string,
cwd: string,
packageManager: ReturnType<typeof getPkgManager>,
loading: ReturnType<typeof spinner>,
) {
loading.stop('🎉 恭喜!您的项目已准备就绪。')
const cdProjectName = () => {
if (root !== cwd) {
const cdProjectName = relative(cwd, root)
return cdProjectName.includes(' ') ? `"${cdProjectName}"` : cdProjectName
}
}
const gettingStarted = `
${dim('$')} ${lightGreen(`cd ${cdProjectName()}`)}
${dim('$')} ${lightGreen(getCommand(packageManager, 'install'))}
${dim('$')} ${lightGreen(getCommand(packageManager, 'dev'))}
`
note(gettingStarted.trim().replace(/^\t\t\t/gm, ''), dim('Getting Started'))
console.log()
}
================================================
FILE: packages/core/src/utils/renderTemplate.ts
================================================
import * as fs from 'node:fs'
import * as path from 'node:path'
import { pathToFileURL } from 'node:url'
import { deepMerge } from './deepMerge'
import { injectUtils } from './injectUtils'
import { sortDependencies } from './sortDependencies'
/**
* Renders a template folder/file to the file system,
* by recursively copying all files under the `src` directory,
* with the following exception:
* - `_filename` should be renamed to `.filename`
* - Fields in `package.json` should be recursively merged
* @param {string} src source filename to copy
* @param {string} dest destination filename of the copy operation
*/
type Callback = (dataStore: Record<string, any>) => void
export function renderTemplate(src: string, dest: string, callbacks: Callback[]) {
const stats = fs.statSync(src)
if (stats.isDirectory()) {
// skip node_module
if (path.basename(src) === 'node_modules')
return
// if it's a directory, render its subdirectories and files recursively
fs.mkdirSync(dest, { recursive: true })
for (const file of fs.readdirSync(src))
renderTemplate(path.resolve(src, file), path.resolve(dest, file), callbacks)
return
}
const filename = path.basename(src)
if (fs.existsSync(dest)) {
const isPackageJson = filename === 'package.json'
const isExtensionsJson = filename === 'extensions.json' || filename === 'settings.json'
const isJsConfigJson = filename === 'jsconfig.json'
if (isPackageJson || isExtensionsJson || isJsConfigJson) {
const existing = JSON.parse(fs.readFileSync(dest, 'utf8'))
const newContent = JSON.parse(fs.readFileSync(src, 'utf8'))
const merged = deepMerge(existing, newContent)
const result = isPackageJson ? sortDependencies(merged) : merged
fs.writeFileSync(dest, `${JSON.stringify(result, null, 2)}\n`)
return
}
}
if (filename.startsWith('_')) {
// rename `_file` to `.file`
dest = path.resolve(path.dirname(dest), filename.replace(/^_/, '.'))
}
if ((filename === '_gitignore' || filename === '_npmrc') && fs.existsSync(dest)) {
// append to existing .gitignore
const existing = fs.readFileSync(dest, 'utf8')
const newGitignore = fs.readFileSync(src, 'utf8')
fs.writeFileSync(dest, `${existing}\n${newGitignore}`)
return
}
// data file for EJS templates
if (filename.endsWith('.data.mjs')) {
// use dest path as key for the data store
dest = dest.replace(/\.data\.mjs$/, '')
// Add a callback to the array for late usage when template files are being processed
callbacks.push(async (dataStore: Record<string, any>) => {
const getData = (await import(pathToFileURL(src).toString())).default
// Though current `getData` are all sync, we still retain the possibility of async
dataStore[dest] = await getData({
oldData: dataStore[dest] || {},
utils: injectUtils,
})
})
return // skip copying the data file
}
fs.copyFileSync(src, dest)
}
================================================
FILE: packages/core/src/utils/setPackageName.ts
================================================
import { existsSync, readFileSync, writeFileSync } from 'node:fs'
import { join } from 'node:path'
function replaceNameContent(filePath: string, projectName: string) {
if (!existsSync(filePath))
return
const fileContent = JSON.parse(readFileSync(filePath, 'utf8'))
fileContent.name = projectName
writeFileSync(filePath, JSON.stringify(fileContent, null, 2))
}
export function replaceProjectName(root: string, name: string) {
const projectName = name.toLocaleLowerCase().replace(/\s/g, '-')
const pkgPath = join(root, 'package.json')
replaceNameContent(pkgPath, projectName)
}
================================================
FILE: packages/core/src/utils/sortDependencies.ts
================================================
interface PackageJson {
dependencies?: Record<string, string>
devDependencies?: Record<string, string>
peerDependencies?: Record<string, string>
optionalDependencies?: Record<string, string>
[key: string]: any
}
export function sortDependencies(packageJson: PackageJson): PackageJson {
const sorted: Record<string, Record<string, string>> = {}
const depTypes = ['dependencies', 'devDependencies', 'peerDependencies', 'optionalDependencies']
for (const depType of depTypes) {
if (packageJson[depType]) {
sorted[depType] = {}
Object.keys(packageJson[depType])
.sort()
.forEach((name) => {
sorted[depType][name] = packageJson[depType][name]
})
}
}
return {
...packageJson,
...sorted,
}
}
================================================
FILE: packages/core/src/utils/types.ts
================================================
export interface PluginData {
id: string
importer?: string
dynamicImporter?: string
initializer?: string
}
================================================
FILE: packages/core/src/utils/validateArgv.ts
================================================
import type { TemplateValue } from './../question/template/type'
import process from 'node:process'
import { outro } from '@clack/prompts'
import { MODULES, PLUGINS, TEMPLATES, UI } from '@create-uni/config'
import { bold, gray } from 'kolorist'
type ArgvBase = string | null
type ArgvList = ArgvBase | string[]
function validateTemplateType(argvTemplate: ArgvBase): TemplateValue {
if (!argvTemplate)
return { type: 'custom' }
const templateType = TEMPLATES.find(item => item.value === argvTemplate)
if (templateType) {
return {
type: templateType.value,
url: templateType.url!,
}
}
else {
for (const item of TEMPLATES) {
if (item.list) {
const templateType = item.list.find(subItem => subItem.value === argvTemplate)
if (templateType) {
return {
type: templateType.value,
url: templateType.url!,
}
}
}
}
}
outro(`${bold(`暂不支持 ${gray(argvTemplate)} 模板`)}`)
process.exit(1)
}
function validateUIName(argvUIName: ArgvBase) {
if (!argvUIName)
return null
const UIName = UI.find(item => item.value === argvUIName)?.value
if (!UIName) {
outro(`${bold(`暂不支持 ${gray(argvUIName)} UI库`)}`)
process.exit(1)
}
return UIName
}
function validatePlugins(argvPlugins: ArgvList): [] {
if (!argvPlugins)
return []
const pluginList = [argvPlugins].flat()
const missedPluginList = pluginList.filter(item => !PLUGINS.some(plugin => plugin.value === item))
if (missedPluginList.length) {
outro(`${bold(`暂不支持 ${gray(missedPluginList.join(', '))} 插件`)}`)
process.exit(1)
}
return pluginList as []
}
function validateModules(argvModules: ArgvList): [] {
if (!argvModules)
return []
const moduleList = [argvModules].flat()
const missedModuleList = moduleList.filter(item => !MODULES.some(module => module.value === item))
if (missedModuleList.length) {
outro(`${bold(`暂不支持 ${gray(missedModuleList.join(', '))} 模块`)}`)
process.exit(1)
}
return moduleList as []
}
export {
validateModules,
validatePlugins,
validateTemplateType,
validateUIName,
}
================================================
FILE: packages/core/template/UI/ano/package.json
================================================
{
"dependencies": {
"ano-ui": "^0.9.2"
},
"devDependencies": {
"@iconify-json/tabler": "^1.2.33"
}
}
================================================
FILE: packages/core/template/UI/ano/src/components/InputEntry.vue
================================================
<script setup>
import { ref } from 'vue'
const name = ref('')
const notify = ref()
function handleClick() {
notify.value?.show({
duration: 3000,
})
}
</script>
<template>
<view m4 p2 border="1px solid gray">
<input
v-model="name"
placeholder="What's your name?"
>
</view>
<view>
<AButton
type="primary" block
:disabled="!name"
@click="handleClick"
>
Hello
</AButton>
</view>
<ANotify ref="notify">
<ANoticeBar type="primary">
Hello{{ ` ${name}` }} 👏
</ANoticeBar>
</ANotify>
</template>
================================================
FILE: packages/core/template/UI/ano/uno.config.js.data.mjs
================================================
export default function getData({ oldData }) {
const anoUIConfig = {
id: 'ano',
importer: `import { presetAno } from 'ano-ui'`,
initializer: 'presetAno()',
}
return {
...oldData,
config: oldData.config.flatMap(config =>
config.id === 'unocss' ? [config, anoUIConfig] : config,
),
}
}
================================================
FILE: packages/core/template/UI/ano/vite.config.js.data.mjs
================================================
export default function getData({ oldData, utils }) {
const autoImportAnoUiPlugin = {
id: 'ano-ui',
importer: `import { AnoResolver } from '@uni-helper/vite-plugin-uni-components/resolvers'`,
}
return {
...oldData,
plugins: oldData.plugins.flatMap(plugin =>
plugin.id === 'autoImport'
? [utils.addResolver(plugin, 'AnoResolver()'), autoImportAnoUiPlugin]
: plugin,
),
}
}
================================================
FILE: packages/core/template/UI/nut/package.json
================================================
{
"dependencies": {
"nutui-uniapp": "^1.11.2"
}
}
================================================
FILE: packages/core/template/UI/nut/src/App.vue
================================================
<script setup>
import { onLaunch } from '@dcloudio/uni-app'
onLaunch(() => {})
</script>
<style lang="scss">
@import "nutui-uniapp/styles/index.scss";
</style>
================================================
FILE: packages/core/template/UI/nut/src/components/InputEntry.vue
================================================
<script setup>
import { ref } from 'vue'
const name = ref('')
const popupVisible = ref(false)
function handleClick() {
popupVisible.value = true
}
</script>
<template>
<view class="input-box">
<input
v-model="name"
placeholder="What's your name?"
>
</view>
<view>
<nut-button :disabled="!name" block @click="handleClick">
Hello
</nut-button>
</view>
<nut-popup v-model:visible="popupVisible" :custom-style="{ padding: '30px 50px' }">
Hello{{ ` ${name}` }} 👏
</nut-popup>
</template>
<style scoped lang="scss">
.input-box {
margin: 1rem;
padding: 0.5rem;
border-bottom: 1px solid gray;
}
</style>
================================================
FILE: packages/core/template/UI/nut/vite.config.js.data.mjs
================================================
export default function getData({ oldData, utils }) {
const autoImportNutUiPlugin = {
id: 'nutui-uniapp',
importer: `import { NutResolver } from 'nutui-uniapp'`,
}
const nutuiExtraConfig = {
css: {
preprocessorOptions: {
scss: {
additionalData: '@import "nutui-uniapp/styles/variables.scss";',
},
},
},
}
return {
...oldData,
plugins: oldData.plugins.flatMap(plugin =>
plugin.id === 'autoImport'
? [utils.addResolver(plugin, 'NutResolver()'), autoImportNutUiPlugin]
: plugin,
),
extraConfig: utils.mergeExtraConfig(oldData.extraConfig, nutuiExtraConfig),
}
}
================================================
FILE: packages/core/template/UI/tdesign/package.json
================================================
{
"dependencies": {
"@tdesign/uniapp": "^0.8.1"
},
"devDependencies": {
"less": "^4.6.4"
}
}
================================================
FILE: packages/core/template/UI/tdesign/src/components/InputEntry.vue
================================================
<script setup lang="ts">
import { ref } from 'vue'
const name = ref('')
const visible = ref(false)
function handleClick() {
visible.value = true
}
</script>
<template>
<view class="input-box">
<input
v-model="name"
placeholder="What's your name?"
>
</view>
<view>
<t-button
block
size="large"
variant="outline"
theme="primary"
:disabled="!name"
@click="handleClick"
>
Hello
</t-button>
</view>
<t-popup
:visible="visible"
placement="bottom"
@update:visible="visible = $event"
>
<view class="block block--bottom">
Hello{{ ` ${name}` }} 👏
</view>
</t-popup>
</template>
<style scoped lang="scss">
.input-box {
margin: 1rem;
padding: 0.5rem;
border-bottom: 1px solid gray;
}
.block {
color: var(--td-text-color-secondary);
display: flex;
align-items: center;
justify-content: center;
width: 100vw;
height: 240px;
}
</style>
================================================
FILE: packages/core/template/UI/tdesign/vite.config.js.data.mjs
================================================
export default function getData({ oldData, utils }) {
const autoImportTDesignUniPlugin = {
id: 'tdesign-uni',
importer: `import { TDesignUniappResolver } from '@uni-helper/vite-plugin-uni-components/resolvers'`,
}
return {
...oldData,
plugins: oldData.plugins.flatMap(plugin =>
plugin.id === 'autoImport'
? [utils.addResolver(plugin, 'TDesignUniappResolver()'), autoImportTDesignUniPlugin]
: plugin,
),
}
}
================================================
FILE: packages/core/template/UI/uni/package.json
================================================
{
"dependencies": {
"@dcloudio/uni-ui": "^1.5.12"
}
}
================================================
FILE: packages/core/template/UI/uni/src/components/InputEntry.vue
================================================
<script setup>
import { ref } from 'vue'
const name = ref('')
const popup = ref()
function handleClick() {
popup.value.open('top')
}
</script>
<template>
<view class="input-box">
<input
v-model="name"
placeholder="What's your name?"
>
</view>
<view>
<button :disabled="!name" @click="handleClick">
Hello
</button>
</view>
<uni-popup ref="popup" type="bottom">
<text class="popup_label">
Hello{{ ` ${name}` }} 👏
</text>
</uni-popup>
</template>
<style scoped lang="scss">
.input-box {
margin: 1rem;
padding: 0.5rem;
border-bottom: 1px solid gray;
}
.popup_label {
padding: 0.5rem 2rem;
background: gray;
border-radius: 8px;
}
</style>
================================================
FILE: packages/core/template/UI/uni/vite.config.js.data.mjs
================================================
export default function getData({ oldData, utils }) {
const excludeMap = {
'root': 'UniKuAppRoot',
'uni-echarts': 'UniEcharts',
}
const excludes = oldData.plugins
.map(plugin => excludeMap[plugin.id])
.filter(Boolean)
const resolverOptions = excludes.length > 0
? `{ exclude: /^(?:${excludes.join('|')})$/ }`
: ''
const autoImportUniUiPlugin = {
id: 'uni-ui',
importer: `import { UniUIResolver } from '@uni-helper/vite-plugin-uni-components/resolvers'`,
}
return {
...oldData,
plugins: oldData.plugins.flatMap(plugin =>
plugin.id === 'autoImport'
? [utils.addResolver(plugin, `UniUIResolver(${resolverOptions})`), autoImportUniUiPlugin]
: plugin,
),
}
}
================================================
FILE: packages/core/template/UI/unocss/src/components/AppFooter.vue
================================================
<script setup>
function handleClickGithub() {
if (window?.open) {
window.open('https://github.com/uni-helper/create-uni')
}
else {
uni.showToast({
icon: 'none',
title: '请使用浏览器打开',
})
}
}
</script>
<template>
<view
i-carbon:logo-github
absolute
bottom-1rem left="50%"
translate-x="-50%"
color="#888"
@click="handleClickGithub"
/>
</template>
================================================
FILE: packages/core/template/UI/unocss/src/components/AppLogos.vue
================================================
<template>
<view inline-flex cursor-default text-2xl font-300>
<view
flex
flex-col
items-center
hover-class="drop-shadow-md drop-shadow-color-green5"
>
<image inline-block h-18 w-18 src="/static/logo.svg" />
<text mt--2 text-green5 class="uni-helper-logo__label">
uni-helper
</text>
</view>
<view
text="3xl gray4"
m="x-4 y-auto"
i-carbon-add transform transition-all-500 hover:rotate-135
/>
<view flex flex-col hover-class="drop-shadow-md drop-shadow-color-purple5">
<image inline-block h-18 w-18 src="/static/vite.png" />
<text mt--2 text-purple5>
Vite
</text>
</view>
</view>
</template>
================================================
FILE: packages/core/template/UI/unocss/src/components/InputEntry.vue
================================================
<script setup>
import { ref } from 'vue'
const name = ref('')
const show = ref(false)
function handleClick() {
show.value = true
setTimeout(() => {
show.value = false
}, 3000)
}
</script>
<template>
<view m4 p2 border="1px solid gray">
<input
v-model="name"
placeholder="What's your name?"
>
</view>
<view>
<button :disabled="!name" @click="handleClick">
Hello
</button>
</view>
<view v-show="show" fixed top-8 left-0 right-0>
<text px8 py2 bg-gray rounded-1>
Hello{{ ` ${name}` }} 👏
</text>
</view>
</template>
================================================
FILE: packages/core/template/UI/unocss/src/pages/index.vue
================================================
<script setup>
import AppFooter from '@/components/AppFooter.vue'
import AppLogos from '@/components/AppLogos.vue'
import InputEntry from '@/components/InputEntry.vue'
</script>
<template>
<view px-10 py-20 text-center>
<AppLogos />
<InputEntry />
<AppFooter />
</view>
</template>
================================================
FILE: packages/core/template/UI/uv/package.json
================================================
{
"dependencies": {
"@climblee/uv-ui": "^1.1.20"
}
}
================================================
FILE: packages/core/template/UI/uv/src/App.vue
================================================
<script setup>
import { onLaunch } from '@dcloudio/uni-app'
onLaunch(() => {})
</script>
<style lang="scss">
@import '@climblee/uv-ui/index.scss';
</style>
================================================
FILE: packages/core/template/UI/uv/src/components/InputEntry.vue
================================================
<script setup>
import { ref } from 'vue'
const name = ref('')
const popup = ref()
function handleClick() {
popup.value.open('bottom')
}
</script>
<template>
<view class="input-box">
<uv-input
v-model="name"
placeholder="What's your name?"
/>
</view>
<view>
<uv-button
type="primary"
:disabled="!name"
@click="handleClick"
>
Hello
</uv-button>
</view>
<uv-popup ref="popup" round="25">
<div class="popup-box">
Hello{{ ` ${name}` }} 👏
</div>
</uv-popup>
</template>
<style scoped lang="scss">
.input-box {
margin: 1rem;
padding: 0.5rem;
border-bottom: 1px solid gray;
}
.popup-box {
color: black;
height: 100px;
}
</style>
================================================
FILE: packages/core/template/UI/uv/vite.config.js.data.mjs
================================================
export default function getData({ oldData, utils }) {
const autoImportUvUiPlugin = {
id: 'uv-ui',
importer: `import { UvResolver } from '@uni-helper/vite-plugin-uni-components/resolvers'`,
}
return {
...oldData,
plugins: oldData.plugins.flatMap(plugin =>
plugin.id === 'autoImport'
? [utils.addResolver(plugin, 'UvResolver()'), autoImportUvUiPlugin]
: plugin,
),
}
}
================================================
FILE: packages/core/template/UI/uview-pro/jsconfig.json
================================================
{
"compilerOptions": {
"types": [
"uview-pro/types"
]
}
}
================================================
FILE: packages/core/template/UI/uview-pro/package.json
================================================
{
"dependencies": {
"uview-pro": "^0.5.18"
}
}
================================================
FILE: packages/core/template/UI/uview-pro/src/App.vue
================================================
<script setup>
import { onLaunch } from '@dcloudio/uni-app'
onLaunch(() => {})
</script>
<style lang="scss">
@import "uview-pro/index.scss";
</style>
================================================
FILE: packages/core/template/UI/uview-pro/src/components/InputEntry.vue
================================================
<script setup>
import { ref } from 'vue'
const name = ref('')
const popupShow = ref(false)
function handleClick() {
popupShow.value = true
}
</script>
<template>
<view class="input-box">
<input
v-model="name"
placeholder="What's your name?"
>
</view>
<view>
<u-button :disabled="!name" type="primary" @click="handleClick">
Hello
</u-button>
</view>
<u-popup v-model="popupShow" mode="bottom" border-radius="14" height="300px">
<view class="popup-box">
Hello{{ ` ${name}` }} 👏
</view>
</u-popup>
</template>
<style scoped lang="scss">
.input-box {
margin: 1rem;
padding: 0.5rem;
border-bottom: 1px solid gray;
}
.popup-box {
display: flex;
justify-content: center;
align-items: center;
height: 100%;
font-size: 1.5rem;
}
</style>
================================================
FILE: packages/core/template/UI/uview-pro/src/main.js.data.mjs
================================================
export default function getData({ oldData }) {
const uViewProEntries = {
id: 'uview-pro',
importer: 'import uViewPro from \'uview-pro\'',
use: 'app.use(uViewPro)',
}
return {
...oldData,
entries: oldData.entries.flatMap(entry =>
entry.id === 'vue' ? [entry, uViewProEntries] : entry,
),
}
}
================================================
FILE: packages/core/template/UI/uview-pro/vite.config.js.data.mjs
================================================
export default function getData({ oldData, utils }) {
const autoImportUviewProPlugin = {
id: 'uview-pro',
importer: `import { uViewProResolver } from '@uni-helper/vite-plugin-uni-components/resolvers'`,
}
const uviewProExtraConfig = {
css: {
preprocessorOptions: {
scss: {
additionalData: '@import "uview-pro/theme.scss";',
},
},
},
}
return {
...oldData,
plugins: oldData.plugins.flatMap(plugin =>
plugin.id === 'autoImport'
? [utils.addResolver(plugin, 'uViewProResolver()'), autoImportUviewProPlugin]
: plugin,
),
extraConfig: utils.mergeExtraConfig(oldData.extraConfig, uviewProExtraConfig),
}
}
================================================
FILE: packages/core/template/UI/wot/.vscode/extensions.json
================================================
{
"recommendations": [
"wot-ui.wot-ui-intellisense"
]
}
================================================
FILE: packages/core/template/UI/wot/jsconfig.json
================================================
{
"compilerOptions": {
"types": [
"wot-design-uni/global.d.ts"
]
}
}
================================================
FILE: packages/core/template/UI/wot/package.json
================================================
{
"dependencies": {
"wot-design-uni": "^1.14.0"
}
}
================================================
FILE: packages/core/template/UI/wot/src/components/InputEntry.vue
================================================
<script setup>
import { ref } from 'vue'
const name = ref('')
const popupShow = ref(false)
function handleClick() {
popupShow.value = true
}
</script>
<template>
<view class="input-box">
<input
v-model="name"
placeholder="What's your name?"
>
</view>
<view>
<wd-button :disabled="!name" @click="handleClick">
Hello
</wd-button>
</view>
<wd-popup v-model="popupShow" custom-style="padding: 30px 40px;">
Hello{{ ` ${name}` }} 👏
</wd-popup>
</template>
<style scoped lang="scss">
.input-box {
margin: 1rem;
padding: 0.5rem;
border-bottom: 1px solid gray;
}
</style>
================================================
FILE: packages/core/template/UI/wot/vite.config.js.data.mjs
================================================
export default function getData({ oldData, utils }) {
const autoImportWotDesignUiPlugin = {
id: 'wot-design-ui',
importer: `import { WotResolver } from '@uni-helper/vite-plugin-uni-components/resolvers'`,
}
return {
...oldData,
plugins: oldData.plugins.flatMap(plugin =>
plugin.id === 'autoImport'
? [utils.addResolver(plugin, 'WotResolver()'), autoImportWotDesignUiPlugin]
: plugin,
),
}
}
================================================
FILE: packages/core/template/UI/wot2/.vscode/extensions.json
================================================
{
"recommendations": [
"wot-ui.wot-ui-intellisense"
]
}
================================================
FILE: packages/core/template/UI/wot2/jsconfig.json
================================================
{
"compilerOptions": {
"types": [
"@wot-ui/ui/global.d.ts"
]
}
}
================================================
FILE: packages/core/template/UI/wot2/package.json
================================================
{
"dependencies": {
"@wot-ui/ui": "^2.0.4"
},
"devDependencies": {
"sass": "^1.99.0"
}
}
================================================
FILE: packages/core/template/UI/wot2/src/components/InputEntry.vue
================================================
<script setup>
import { ref } from 'vue'
const name = ref('')
const popupShow = ref(false)
function handleClick() {
popupShow.value = true
}
</script>
<template>
<view class="input-box">
<input
v-model="name"
placeholder="What's your name?"
>
</view>
<view>
<wd-button :disabled="!name" @click="handleClick">
Hello
</wd-button>
</view>
<wd-popup v-model="popupShow" custom-style="padding: 30px 40px;">
Hello{{ ` ${name}` }} 👏
</wd-popup>
</template>
<style scoped lang="scss">
.input-box {
margin: 1rem;
padding: 0.5rem;
border-bottom: 1px solid gray;
}
</style>
================================================
FILE: packages/core/template/UI/wot2/vite.config.js.data.mjs
================================================
export default function getData({ oldData, utils }) {
const autoImportWotUiPlugin = {
id: 'wot-ui',
importer: `import { WotV2Resolver } from '@uni-helper/vite-plugin-uni-components/resolvers'`,
}
return {
...oldData,
plugins: oldData.plugins.flatMap(plugin =>
plugin.id === 'autoImport'
? [utils.addResolver(plugin, 'WotV2Resolver()'), autoImportWotUiPlugin]
: plugin,
),
}
}
================================================
FILE: packages/core/template/base/.vscode/extensions.json
================================================
{
"recommendations": [
"vue.volar",
"mrmaoddxxaa.create-uniapp-view",
"uni-helper.uni-helper-vscode",
"uni-helper.uni-app-schemas-vscode",
"uni-helper.uni-highlight-vscode",
"uni-helper.uni-ui-snippets-vscode",
"uni-helper.uni-app-snippets-vscode",
"uni-helper.uni-cloud-snippets-vscode"
]
}
================================================
FILE: packages/core/template/base/.vscode/settings.json
================================================
{
"files.associations": {
"pages.json": "jsonc",
"manifest.json": "jsonc"
}
}
================================================
FILE: packages/core/template/base/_gitignore
================================================
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
.DS_Store
dist
*.local
# Editor directories and files
.idea
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
================================================
FILE: packages/core/template/base/_npmrc
================================================
strict-peer-dependencies=false
auto-install-peers=true
shamefully-hoist=true
================================================
FILE: packages/core/template/base/index.html
================================================
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<link rel="icon" href="static/logo.svg">
<script>
const coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)')
|| CSS.supports('top: constant(a)'))
document.write(
`<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0${
coverSupport ? ', viewport-fit=cover' : ''}" />`)
</script>
<title></title>
<!--preload-links-->
<!--app-context-->
</head>
<body>
<div id="app"><!--app-html--></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>
================================================
FILE: packages/core/template/base/jsconfig.json
================================================
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
},
"types": [
"vite/client",
"@dcloudio/types",
"@mini-types/alipay",
"miniprogram-api-typings",
"@uni-helper/uni-types"
]
},
"vueCompilerOptions": {
"plugins": ["@uni-helper/uni-types/volar-plugin"]
}
}
================================================
FILE: packages/core/template/base/package.json
================================================
{
"name": "uni-app",
"type": "module",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "unh dev",
"build": "unh build",
"about": "unh info"
},
"dependencies": {
"@dcloudio/uni-app": "3.0.0-5000720260410001",
"@dcloudio/uni-app-harmony": "3.0.0-5000720260410001",
"@dcloudio/uni-app-plus": "3.0.0-5000720260410001",
"@dcloudio/uni-components": "3.0.0-5000720260410001",
"@dcloudio/uni-h5": "3.0.0-5000720260410001",
"@dcloudio/uni-mp-alipay": "3.0.0-5000720260410001",
"@dcloudio/uni-mp-baidu": "3.0.0-5000720260410001",
"@dcloudio/uni-mp-harmony": "3.0.0-5000720260410001",
"@dcloudio/uni-mp-jd": "3.0.0-5000720260410001",
"@dcloudio/uni-mp-kuaishou": "3.0.0-5000720260410001",
"@dcloudio/uni-mp-lark": "3.0.0-5000720260410001",
"@dcloudio/uni-mp-qq": "3.0.0-5000720260410001",
"@dcloudio/uni-mp-toutiao": "3.0.0-5000720260410001",
"@dcloudio/uni-mp-weixin": "3.0.0-5000720260410001",
"@dcloudio/uni-mp-xhs": "3.0.0-5000720260410001",
"@dcloudio/uni-quickapp-webview": "3.0.0-5000720260410001",
"vue": "3.4.21",
"vue-i18n": "9.6.2",
"vue-router": "4.5.1"
},
"devDependencies": {
"@dcloudio/types": "3.4.28",
"@dcloudio/uni-automator": "3.0.0-5000720260410001",
"@dcloudio/uni-cli-shared": "3.0.0-5000720260410001",
"@dcloudio/uni-stacktracey": "3.0.0-5000720260410001",
"@dcloudio/vite-plugin-uni": "3.0.0-5000720260410001",
"@mini-types/alipay": "^3.0.14",
"@uni-helper/plugin-uni": "0.1.0",
"@uni-helper/unh": "^0.3.1",
"@uni-helper/uni-types": "^1.0.0-alpha.8",
"@vue/runtime-core": "3.4.21",
"miniprogram-api-typings": "^5.1.3",
"sass": "1.64.2",
"vite": "5.2.8"
}
}
================================================
FILE: packages/core/template/base/src/App.vue
================================================
<script setup>
import { onLaunch } from '@dcloudio/uni-app'
onLaunch(() => {})
</script>
<style></style>
================================================
FILE: packages/core/template/base/src/components/AppFooter.vue
================================================
<script setup>
function handleClickGithub() {
if (window?.open) {
window.open('https://github.com/uni-helper/create-uni')
}
else {
uni.showToast({
icon: 'none',
title: '请使用浏览器打开',
})
}
}
</script>
<template>
<view class="footer" @click="handleClickGithub">
<image class="uni-helper-github__image" src="/static/github.svg" />
</view>
</template>
<style>
.footer{
position: absolute;
bottom: 1rem;
left: 50%;
transform: translateX(-50%);
color: #888;
}
.uni-helper-github__image {
display: inline-block;
height: 1em;
width: 1em;
}
</style>
================================================
FILE: packages/core/template/base/src/components/AppLogos.vue
================================================
<script setup>
</script>
<template>
<view class="container">
<view class="uni-helper-logo">
<image class="uni-helper-logo__image" src="/static/logo.svg" />
<text class="uni-helper-logo__label green">
uni-helper
</text>
</view>
<text class="link-bar">
+
</text>
<view class="uni-helper-logo">
<image class="uni-helper-logo__image" src="/static/vite.png" />
<text class="uni-helper-logo__label purple">
Vite
</text>
</view>
</view>
</template>
<style scoped lang="scss">
.container {
display: inline-flex;
font-size: 1.5rem;
font-weight: 300;
&:hover {
.link-bar {
transform: rotate(135deg);
}
}
}
.uni-helper-logo {
display: flex;
flex-direction: column;
align-items: center;
.uni-helper-logo__image {
display: inline-block;
height: 4.5rem;
width: 4.5rem;
}
.uni-helper-logo__label {
margin-top: -0.5rem;
}
.green {
color: #22c55e;
};
.purple {
color: #a855f7;
}
}
.link-bar {
color: #9ca3af;
margin: auto 1em;
transition: all 500ms cubic-bezier(0.4, 0, 0.2, 1);
}
</style>
================================================
FILE: packages/core/template/base/src/components/InputEntry.vue
================================================
<script setup>
import { ref } from 'vue'
const name = ref('')
const show = ref(false)
function handleClick() {
show.value = true
setTimeout(() => {
show.value = false
}, 3000)
}
</script>
<template>
<view class="input-box">
<input
v-model="name"
placeholder="What's your name?"
>
</view>
<view>
<button :disabled="!name" @click="handleClick">
Hello
</button>
</view>
<view v-show="show" class="popup">
<text class="popup_label">
Hello{{ ` ${name}` }} 👏
</text>
</view>
</template>
<style scoped lang="scss">
.input-box {
margin: 1rem;
padding: 0.5rem;
border-bottom: 1px solid gray;
}
.popup {
position: fixed;
top: 2rem;
left: 0px;
right: 0px;
.popup_label {
padding: 0.5rem 2rem;
background: gray;
border-radius: 8px;
}
}
</style>
================================================
FILE: packages/core/template/base/src/main.js.data.mjs
================================================
export default function getData() {
return {
entries: [{
id: 'vue',
importer: `import { createSSRApp } from 'vue'`,
use: 'const app = createSSRApp(App)',
returner: 'app,',
}],
}
}
================================================
FILE: packages/core/template/base/src/main.js.ejs
================================================
<%_ for (const { importer } of entries) { _%>
<%- importer %>
<%_ } _%>
import App from './App.vue'
export function createApp() {
<%_ for (const { use } of entries) { _%>
<%_ if (use) { _%>
<%- use %>
<%_ } _%>
<%_ } _%>
return {
<%_ for (const { returner } of entries) { _%>
<%_ if (returner) { _%>
<%- returner %>
<%_ } _%>
<%_ } _%>
}
}
================================================
FILE: packages/core/template/base/src/manifest.json
================================================
{
"name": "",
"appid": "",
"description": "",
"versionName": "1.0.0",
"versionCode": "100",
"transformPx": false,
"uniStatistics": {
"enable": false
},
"app-plus": {
"usingComponents": true,
"nvueStyleCompiler": "uni-app",
"compilerVersion": 3,
"splashscreen": {
"alwaysShowBeforeRender": true,
"waiting": true,
"autoclose": true,
"delay": 0
},
"modules": {},
"distribute": {
"android": {
"permissions": [
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
"<uses-feature android:name=\"android.hardware.camera\"/>",
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
]
},
"ios": {},
"sdkConfigs": {}
}
},
"h5": {
"darkmode": true,
"themeLocation": "theme.json"
},
"quickapp": {},
"mp-weixin": {
"appid": "",
"setting": {
"urlCheck": false
},
"usingComponents": true,
"darkmode": true,
"themeLocation": "theme.json"
},
"mp-alipay": {
"usingComponents": true
},
"mp-baidu": {
"usingComponents": true
},
"mp-toutiao": {
"usingComponents": true
},
"vueVersion": "3"
}
================================================
FILE: packages/core/template/base/src/pages/index.vue
================================================
<script setup>
import AppFooter from '@/components/AppFooter.vue'
import AppLogos from '@/components/AppLogos.vue'
import InputEntry from '@/components/InputEntry.vue'
</script>
<template>
<view class="root-container">
<AppLogos />
<InputEntry />
<AppFooter />
</view>
</template>
<style scoped>
.root-container {
padding: 5rem 2.5rem;
text-align: center;
}
</style>
================================================
FILE: packages/core/template/base/src/pages.json
================================================
{
"pages": [
{
"path": "pages/index",
"type": "home"
}
],
"globalStyle": {
"backgroundColor": "@bgColor",
"backgroundColorBottom": "@bgColorBottom",
"backgroundColorTop": "@bgColorTop",
"backgroundTextStyle": "@bgTxtStyle",
"navigationBarBackgroundColor": "#000000",
"navigationBarTextStyle": "@navTxtStyle",
"navigationBarTitleText": "Uni Creator",
"navigationStyle": "custom"
},
"subPackages": []
}
================================================
FILE: packages/core/template/base/src/theme.json
================================================
{
"light": {
"bgColor": "#fcfcfc",
"bgColorBottom": "#fcfcfc",
"bgColorTop": "#ff6b00",
"bgTxtStyle": "dark",
"navBgColor": "#ff6b00",
"navTxtStyle": "white",
"tabBgColor": "#fcfcfc",
"tabBorderStyle": "black",
"tabFontColor": "#1f2937",
"tabSelectedColor": "#ff6b00"
},
"dark": {
"bgColor": "#181818",
"bgColorBottom": "#181818",
"bgColorTop": "#ff6b00",
"bgTxtStyle": "light",
"navBgColor": "#ff6b00",
"navTxtStyle": "white",
"tabBgColor": "#181818",
"tabBorderStyle": "white",
"tabFontColor": "#f3f4f6",
"tabSelectedColor": "#ff6b00"
}
}
================================================
FILE: packages/core/template/base/src/uni.scss
================================================
/**
* 这里是uni-app内置的常用样式变量
*
* uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量
* 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App
*
*/
/**
* 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能
*
* 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
*/
/* 颜色变量 */
/* 行为相关颜色 */
$uni-color-primary: #007aff;
$uni-color-success: #4cd964;
$uni-color-warning: #f0ad4e;
$uni-color-error: #dd524d;
/* 文字基本颜色 */
$uni-text-color: #333; // 基本色
$uni-text-color-inverse: #fff; // 反色
$uni-text-color-grey: #999; // 辅助灰色,如加载更多的提示信息
$uni-text-color-placeholder: #808080;
$uni-text-color-disable: #c0c0c0;
/* 背景颜色 */
$uni-bg-color: #fff;
$uni-bg-color-grey: #f8f8f8;
$uni-bg-color-hover: #f1f1f1; // 点击状态颜色
$uni-bg-color-mask: rgba(0, 0, 0, 0.4); // 遮罩颜色
/* 边框颜色 */
$uni-border-color: #c8c7cc;
/* 尺寸变量 */
/* 文字尺寸 */
$uni-font-size-sm: 12px;
$uni-font-size-base: 14px;
$uni-font-size-lg: 16px;
/* 图片尺寸 */
$uni-img-size-sm: 20px;
$uni-img-size-base: 26px;
$uni-img-size-lg: 40px;
/* Border Radius */
$uni-border-radius-sm: 2px;
$uni-border-radius-base: 3px;
$uni-border-radius-lg: 6px;
$uni-border-radius-circle: 50%;
/* 水平间距 */
$uni-spacing-row-sm: 5px;
$uni-spacing-row-base: 10px;
$uni-spacing-row-lg: 15px;
/* 垂直间距 */
$uni-spacing-col-sm: 4px;
$uni-spacing-col-base: 8px;
$uni-spacing-col-lg: 12px;
/* 透明度 */
$uni-opacity-disabled: 0.3; // 组件禁用态的透明度
/* 文章场景相关 */
$uni-color-title: #2c405a; // 文章标题颜色
$uni-font-size-title: 20px;
$uni-color-subtitle: #555; // 二级标题颜色
$uni-font-size-subtitle: 18px;
$uni-color-paragraph: #3f536e; // 文章段落颜色
$uni-font-size-paragraph: 15px;
================================================
FILE: packages/core/template/base/unh.config.js.data.mjs
================================================
export default function getData() {
return {
autoGenerate: {
pages: false,
manifest: false,
},
}
}
================================================
FILE: packages/core/template/base/unh.config.js.ejs
================================================
import { defineConfig } from '@uni-helper/unh'
/**
* unh 配置文件
* 更多配置请参考:https://uni-helper.js.org/unh/
*/
export default defineConfig({
platform: {
// 默认平台
default: 'h5',
// 平台别名
alias: {
'h5': ['w', 'h'],
'mp-weixin': 'wx',
},
},
<%_ if (autoGenerate.pages || autoGenerate.manifest) { _%>
autoGenerate: {
<%_ if (autoGenerate.pages) { _%>
pages: <%= autoGenerate.pages %>,
<%_ } _%>
<%_ if (autoGenerate.manifest) { _%>
manifest: <%= autoGenerate.manifest %>,
<%_ } _%>
},
<%_ } _%>
})
================================================
FILE: packages/core/template/base/vite.config.js.data.mjs
================================================
export default function getData() {
return {
plugins: [{
id: 'uni',
importer: `import Uni from '@uni-helper/plugin-uni'`,
initializer: `// https://uni-helper.js.org/plugin-uni
Uni()`,
}],
extraConfig: null,
dynamic: false,
}
}
================================================
FILE: packages/core/template/base/vite.config.js.ejs
================================================
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
<%_ for (const { importer } of plugins) { _%>
<%_ if (importer) { _%>
<%- importer %>
<%_ } _%>
<%_ } _%>
<%_ if (dynamic) { _%>
export default defineConfig(async () => {
<%_ for (const { dynamicImporter } of plugins) { _%>
<%_ if (dynamicImporter) { _%>
<%- dynamicImporter %>
<%_ } _%>
<%_ } _%>
return {
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
}
},
plugins: [
<%_ for (const { initializer } of plugins) { _%>
<%_ if (initializer) { _%>
<%- initializer _%>,
<%_ } _%>
<%_ } _%>
],
<%_ if (extraConfig) { _%>
<%- extraConfig _%>
<%_ } _%>
}
})
<%_ } else { _%>
export default defineConfig({
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
}
},
plugins: [
<%_ for (const { initializer } of plugins) { _%>
<%_ if (initializer) { _%>
<%- initializer _%>,
<%_ } _%>
<%_ } _%>
],
<%_ if (extraConfig) { _%>
<%- extraConfig _%>
<%_ } _%>
})
<%_ } _%>
================================================
FILE: packages/core/template/config/lint/.vscode/extensions.json
================================================
{
"recommendations": [
"dbaeumer.vscode-eslint"
]
}
================================================
FILE: packages/core/template/config/lint/.vscode/settings.json
================================================
{
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit",
"source.organizeImports": "never"
},
"prettier.enable": false,
"editor.formatOnSave": false,
"eslint.validate": [
"javascript",
"javascriptreact",
"typescript",
"typescriptreact",
"vue",
"nvue",
"uvue",
"html",
"markdown",
"json",
"jsonc",
"yaml",
"toml",
"xml",
"gql",
"graphql",
"astro",
"svelte",
"css",
"less",
"scss",
"pcss",
"postcss"
]
}
================================================
FILE: packages/core/template/config/lint/eslint.config.js
================================================
import uniHelper from '@uni-helper/eslint-config'
export default uniHelper()
================================================
FILE: packages/core/template/config/lint/package.json
================================================
{
"scripts": {
"lint": "eslint .",
"lint:fix": "eslint . --fix"
},
"devDependencies": {
"@uni-helper/eslint-config": "^0.7.1",
"eslint": "^10.2.1"
}
}
================================================
FILE: packages/core/template/config/typescript/.vscode/extensions.json
================================================
{
"recommendations": [
"yoavbls.pretty-ts-errors",
"johnsoncodehk.vscode-tsconfig-helper"
]
}
================================================
FILE: packages/core/template/config/typescript/jsconfig.json
================================================
{
"compilerOptions": {
"lib": ["DOM", "DOM.Iterable", "ESNext"],
"module": "ESNext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"jsx": "preserve",
"jsxImportSource": "vue",
"noImplicitThis": true,
"strict": true,
"verbatimModuleSyntax": true,
"target": "ESNext",
"useDefineForClassFields": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"skipLibCheck": true
},
"includes": ["src/**/*.ts", "src/**/*.tsx"]
}
================================================
FILE: packages/core/template/config/typescript/package.json
================================================
{
"scripts": {
"type-check": "vue-tsc --noEmit"
},
"devDependencies": {
"@types/node": "^25.6.0",
"@vue/tsconfig": "^0.9.1",
"typescript": "5.9.3",
"vue-tsc": "^3.2.7"
}
}
================================================
FILE: packages/core/template/module/pinia/package.json
================================================
{
"dependencies": {
"pinia": "2.2.4"
}
}
================================================
FILE: packages/core/template/module/pinia/src/main.js.data.mjs
================================================
export default function getData({ oldData }) {
const piniaEntries = {
id: 'pinia',
importer: 'import * as Pinia from \'pinia\'',
use: 'app.use(Pinia.createPinia())',
returner: 'Pinia,',
}
return {
...oldData,
entries: oldData.entries.flatMap(entry =>
entry.id === 'vue' ? [entry, piniaEntries] : entry,
),
}
}
================================================
FILE: packages/core/template/module/pinia/src/stores/counter.js
================================================
import { defineStore } from 'pinia'
import { ref } from 'vue'
export const useCounterStore = defineStore('counter', () => {
const count = ref(0)
function increment() {
count.value++
}
return { count, increment }
})
================================================
FILE: packages/core/template/module/uniEcharts/jsconfig.json
================================================
{
"compilerOptions": {
"types": [
"uni-echarts/global"
]
}
}
================================================
FILE: packages/core/template/module/uniEcharts/package.json
================================================
{
"dependencies": {
"echarts": "^6.0.0",
"uni-echarts": "^2.5.1"
}
}
================================================
FILE: packages/core/template/module/uniEcharts/vite.config.js.data.mjs
================================================
export default function getData({ oldData, utils }) {
const uniEchartsPlugin = {
id: 'uni-echarts',
importer: `import { UniEcharts } from 'uni-echarts/vite'`,
initializer: `// https://uni-echarts.xiaohe.ink
UniEcharts()`,
}
const autoImportUniEchartsPlugin = {
id: 'uni-echarts-auto-import',
importer: `import { UniEchartsResolver } from 'uni-echarts/resolver'`,
}
const uniEchartsExtraConfig = {
optimizeDeps: {
exclude: ['uni-echarts'],
},
}
return {
...oldData,
plugins: oldData.plugins.flatMap((plugin) => {
if (plugin.id === 'uni') {
return [uniEchartsPlugin, plugin]
}
if (plugin.id === 'autoImport') {
return [utils.addResolver(plugin, 'UniEchartsResolver()'), autoImportUniEchartsPlugin]
}
return plugin
}),
extraConfig: utils.mergeExtraConfig(oldData.extraConfig, uniEchartsExtraConfig),
}
}
================================================
FILE: packages/core/template/module/uniNetwork/package.json
================================================
{
"dependencies": {
"@uni-helper/uni-network": "^0.23.1"
}
}
================================================
FILE: packages/core/template/module/uniPromises/package.json
================================================
{
"dependencies": {
"@uni-helper/uni-promises": "^0.2.1"
}
}
================================================
FILE: packages/core/template/module/uniPromises/src/main.js.data.mjs
================================================
export default function getData({ oldData }) {
const uniPromisesEntry = {
id: 'uniPromises',
}
return {
...oldData,
entries: oldData.entries.some(item => item.id === 'uniUse')
? oldData.entries
: oldData.entries.flatMap(entry =>
entry.id === 'vue' ? [entry, uniPromisesEntry] : entry,
),
}
}
================================================
FILE: packages/core/template/module/uniPromises/vite.config.js.data.mjs
================================================
export default function getData({ oldData, utils }) {
const promisesExtraConfig = {
build: {
target: 'es6',
cssTarget: 'chrome61',
},
optimizeDeps: {
exclude: ['vue-demi'],
},
}
return {
...oldData,
extraConfig: utils.mergeExtraConfig(oldData.extraConfig, promisesExtraConfig),
}
}
================================================
FILE: packages/core/template/module/uniUse/package.json
================================================
{
"dependencies": {
"@uni-helper/uni-use": "^0.19.17",
"@vueuse/core": "9.13.0"
}
}
================================================
FILE: packages/core/template/module/uniUse/src/main.js.data.mjs
================================================
export default function getData({ oldData }) {
const uniUseEntry = {
id: 'uniUse',
}
return {
...oldData,
entries: oldData.entries.some(item => item.id === 'uniPromises')
? oldData.entries
: oldData.entries.flatMap(entry =>
entry.id === 'vue' ? [entry, uniUseEntry] : entry,
),
}
}
================================================
FILE: packages/core/template/module/uniUse/vite.config.js.data.mjs
================================================
export default function getData({ oldData, utils }) {
const uniUseExtraConfig = {
build: {
target: 'es6',
cssTarget: 'chrome61', // https://cn.vitejs.dev/config/build-options.html#build-csstarget
},
optimizeDeps: {
exclude: ['vue-demi'],
},
}
return {
...oldData,
extraConfig: utils.mergeExtraConfig(oldData.extraConfig, uniUseExtraConfig),
}
}
================================================
FILE: packages/core/template/module/unocss/.vscode/extensions.json
================================================
{
"recommendations": [
"antfu.unocss"
]
}
================================================
FILE: packages/core/template/module/unocss/package.json
================================================
{
"devDependencies": {
"@iconify-json/carbon": "^1.2.20",
"@uni-helper/unocss-preset-uni": "^0.2.11",
"unocss": "66.0.0"
},
"pnpm": {
"overrides": {
"unconfig": "7.3.2"
}
},
"overrides": {
"unconfig": "7.3.2"
},
"resolutions": {
"unconfig": "7.3.2"
}
}
================================================
FILE: packages/core/template/module/unocss/src/main.js.data.mjs
================================================
export default function getData({ oldData }) {
const unocssEntry = {
id: 'unocss',
importer: 'import \'uno.css\'',
}
return {
...oldData,
entries: oldData.entries.flatMap(entry =>
entry.id === 'vue' ? [entry, unocssEntry] : entry,
),
}
}
================================================
FILE: packages/core/template/module/unocss/uno.config.js.data.mjs
================================================
export default function getData() {
return {
config: [{
id: 'unocss',
importer: `import { presetUni } from '@uni-helper/unocss-preset-uni'`,
initializer: 'presetUni()',
}],
}
}
================================================
FILE: packages/core/template/module/unocss/uno.config.js.ejs
================================================
import {
defineConfig,
presetIcons,
transformerDirectives,
transformerVariantGroup,
} from 'unocss'
<%_ for (const { importer } of config) { _%>
<%_ if (importer) { _%>
<%- importer %>
<%_ } _%>
<%_ } _%>
export default defineConfig({
presets: [
<%_ for (const { initializer } of config) { _%>
<%_ if (initializer) { _%>
<%- initializer _%>,
<%_ } _%>
<%_ } _%>
presetIcons({
scale: 1.2,
warn: true,
extraProperties: {
'display': 'inline-block',
'vertical-align': 'middle',
},
}),
],
transformers: [
transformerDirectives(),
transformerVariantGroup(),
],
})
================================================
FILE: packages/core/template/module/unocss/vite.config.js.data.mjs
================================================
export default function getData({ oldData }) {
const UnoCSSPlugin = {
id: 'UnoCSS',
importer: `import UnoCSS from 'unocss/vite'`,
initializer: 'UnoCSS()',
}
return {
...oldData,
plugins: oldData.plugins.flatMap(plugin =>
plugin.id === 'uni' ? [plugin, UnoCSSPlugin] : plugin,
),
}
}
================================================
FILE: packages/core/template/module/vitest/jsconfig.json
================================================
{
"compilerOptions": {
"types": [
"vitest-environment-uniapp/types"
]
}
}
================================================
FILE: packages/core/template/module/vitest/package.json
================================================
{
"scripts": {
"test": "vitest"
},
"devDependencies": {
"vitest": "^4.1.5",
"vitest-environment-uniapp": "^0.0.5"
}
}
================================================
FILE: packages/core/template/module/vitest/test/index.test.js
================================================
import { beforeAll, describe, expect, it } from 'vitest'
describe('test title', () => {
let page: Page
beforeAll(async () => {
page = await program.currentPage()
await page.waitFor(3000)
})
it('check uni-helper logo label', async () => {
const el = await page.$('.uni-helper-logo__label')
const titleText = await el.text()
expect(titleText).toEqual('uni-helper')
})
})
================================================
FILE: packages/core/template/module/vitest/vitest.config.js
================================================
import { defineConfig } from 'vitest/config'
export default defineConfig({
test: {
environment: 'uniapp',
environmentOptions: {
uniapp: {
platform: 'mp-weixin',
projectPath: './src',
port: 5121,
},
},
},
})
================================================
FILE: packages/core/template/module/zPaging/jsconfig.json
================================================
{
"compilerOptions": {
"types": [
"z-paging/types"
]
}
}
================================================
FILE: packages/core/template/module/zPaging/package.json
================================================
{
"dependencies": {
"z-paging": "^2.8.8"
}
}
================================================
FILE: packages/core/template/module/zPaging/vite.config.js.data.mjs
================================================
export default function getData({ oldData, utils }) {
const autoImportZPagingPlugin = {
id: 'z-paging-auto-import',
importer: `import { ZPagingResolver } from '@uni-helper/vite-plugin-uni-components/resolvers'`,
}
return {
...oldData,
plugins: oldData.plugins.flatMap(plugin =>
plugin.id === 'autoImport'
? [utils.addResolver(plugin, 'ZPagingResolver()'), autoImportZPagingPlugin]
: plugin,
),
}
}
================================================
FILE: packages/core/template/plugin/componentPlaceholder/package.json
================================================
{
"devDependencies": {
"@binbinji/vite-plugin-component-placeholder": "^0.0.15"
}
}
================================================
FILE: packages/core/template/plugin/componentPlaceholder/vite.config.js.data.mjs
================================================
export default function getData({ oldData }) {
const componentPlaceholderPlugin = {
id: 'componentPlaceholder',
importer: `import ComponentPlaceholder from '@binbinji/vite-plugin-component-placeholder'`,
initializer: `// https://github.com/chouchouji/vite-plugin-component-placeholder
ComponentPlaceholder()`,
}
return {
...oldData,
plugins: oldData.plugins.flatMap(plugin =>
plugin.id === 'uni' ? [componentPlaceholderPlugin, plugin] : plugin,
),
}
}
================================================
FILE: packages/core/template/plugin/filePlatform/package.json
================================================
{
"devDependencies": {
"@uni-helper/vite-plugin-uni-platform": "^0.0.5"
}
}
================================================
FILE: packages/core/template/plugin/filePlatform/vite.config.js.data.mjs
================================================
export default function getData({ oldData }) {
const platformPlugin = {
id: 'platform',
importer: `import UniPlatform from '@uni-helper/vite-plugin-uni-platform'`,
initializer: `// https://uni-helper.js.org/vite-plugin-uni-platform
UniPlatform()`,
}
return {
...oldData,
plugins: oldData.plugins.flatMap(plugin =>
plugin.id === 'uni' ? [platformPlugin, plugin] : plugin,
),
}
}
================================================
FILE: packages/core/template/plugin/import/package.json
================================================
{
"devDependencies": {
"@uni-helper/vite-plugin-uni-components": "^0.2.10"
}
}
================================================
FILE: packages/core/template/plugin/import/vite.config.js.data.mjs
================================================
export default function getData({ oldData }) {
const autoImportPlugin = {
id: 'autoImport',
importer: `import Components from '@uni-helper/vite-plugin-uni-components'`,
initializer: `// https://uni-helper.js.org/vite-plugin-uni-components
Components({
dts: true,
resolvers: []
})`,
}
return {
...oldData,
plugins: oldData.plugins.flatMap(plugin =>
plugin.id === 'uni' ? [autoImportPlugin, plugin] : plugin,
),
}
}
================================================
FILE: packages/core/template/plugin/layouts/package.json
================================================
{
"devDependencies": {
"@uni-helper/vite-plugin-uni-layouts": "^0.1.11"
}
}
================================================
FILE: packages/core/template/plugin/layouts/vite.config.js.data.mjs
================================================
export default function getData({ oldData }) {
const layoutsPlugin = {
id: 'layouts',
importer: `import UniLayouts from '@uni-helper/vite-plugin-uni-layouts'`,
initializer: `// https://uni-helper.js.org/vite-plugin-uni-layouts
UniLayouts()`,
}
return {
...oldData,
plugins: oldData.plugins.flatMap(plugin =>
plugin.id === 'uni' ? [layoutsPlugin, plugin] : plugin,
),
}
}
================================================
FILE: packages/core/template/plugin/manifest/manifest.config.js
================================================
import { defineManifestConfig } from '@uni-helper/vite-plugin-uni-manifest'
export default defineManifestConfig({
'name': '',
'appid': '',
'description': '',
'versionName': '1.0.0',
'versionCode': '100',
'transformPx': false,
/* 5+App特有相关 */
'app-plus': {
usingComponents: true,
nvueStyleCompiler: 'uni-app',
compilerVersion: 3,
splashscreen: {
alwaysShowBeforeRender: true,
waiting: true,
autoclose: true,
delay: 0,
},
/* 模块配置 */
modules: {},
/* 应用发布信息 */
distribute: {
/* android打包配置 */
android: {
permissions: [
'<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>',
'<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>',
'<uses-permission android:name="android.permission.VIBRATE"/>',
'<uses-permission android:name="android.permission.READ_LOGS"/>',
'<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>',
'<uses-feature android:name="android.hardware.camera.autofocus"/>',
'<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>',
'<uses-permission android:name="android.permission.CAMERA"/>',
'<uses-permission android:name="android.permission.GET_ACCOUNTS"/>',
'<uses-permission android:name="android.permission.READ_PHONE_STATE"/>',
'<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>',
'<uses-permission android:name="android.permission.WAKE_LOCK"/>',
'<uses-permission android:name="android.permission.FLASHLIGHT"/>',
'<uses-feature android:name="android.hardware.camera"/>',
'<uses-permission android:name="android.permission.WRITE_SETTINGS"/>',
],
},
/* ios打包配置 */
ios: {},
/* SDK配置 */
sdkConfigs: {},
},
},
/* 快应用特有相关 */
'quickapp': {},
/* 小程序特有相关 */
'mp-weixin': {
appid: '',
setting: {
urlCheck: false,
},
usingComponents: true,
darkmode: true,
themeLocation: 'theme.json',
},
'mp-alipay': {
usingComponents: true,
},
'mp-baidu': {
usingComponents: true,
},
'mp-toutiao': {
usingComponents: true,
},
'h5': {
darkmode: true,
themeLocation: 'theme.json',
},
'uniStatistics': {
enable: false,
},
'vueVersion': '3',
})
================================================
FILE: packages/core/template/plugin/manifest/package.json
================================================
{
"devDependencies": {
"@uni-helper/vite-plugin-uni-manifest": "^0.2.12"
}
}
================================================
FILE: packages/core/template/plugin/manifest/unh.config.js.data.mjs
================================================
export default function getData({ oldData }) {
return {
autoGenerate: {
...oldData.autoGenerate,
manifest: true,
},
}
}
================================================
FILE: packages/core/template/plugin/manifest/vite.config.js.data.mjs
================================================
export default function getData({ oldData }) {
const manifestPlugin = {
id: 'manifest',
importer: `import UniManifest from '@uni-helper/vite-plugin-uni-manifest'`,
initializer: `// https://uni-helper.js.org/vite-plugin-uni-manifest
UniManifest()`,
}
return {
...oldData,
plugins: oldData.plugins.flatMap(plugin =>
plugin.id === 'uni' ? [manifestPlugin, plugin] : plugin,
),
}
}
================================================
FILE: packages/core/template/plugin/pages/jsconfig.json
================================================
{
"compilerOptions": {
"types": [
"@uni-helper/vite-plugin-uni-pages"
]
}
}
================================================
FILE: packages/core/template/plugin/pages/package.json
================================================
{
"devDependencies": {
"@uni-helper/vite-plugin-uni-pages": "^0.3.24"
}
}
================================================
FILE: packages/core/template/plugin/pages/pages.config.js
================================================
import { defineUniPages } from '@uni-helper/vite-plugin-uni-pages'
export default defineUniPages({
pages: [],
globalStyle: {
backgroundColor: '@bgColor',
backgroundColorBottom: '@bgColorBottom',
backgroundColorTop: '@bgColorTop',
backgroundTextStyle: '@bgTxtStyle',
navigationBarBackgroundColor: '#000000',
navigationBarTextStyle: '@navTxtStyle',
navigationBarTitleText: 'Uni Creator',
navigationStyle: 'custom',
},
subPackages: [],
})
================================================
FILE: packages/core/template/plugin/pages/unh.config.js.data.mjs
================================================
export default function getData({ oldData }) {
return {
autoGenerate: {
...oldData.autoGenerate,
pages: true,
},
}
}
================================================
FILE: packages/core/template/plugin/pages/vite.config.js.data.mjs
================================================
export default function getData({ oldData }) {
const pagesPlugin = {
id: 'pages',
importer: `import UniPages from '@uni-helper/vite-plugin-uni-pages'`,
initializer: `// https://uni-helper.js.org/vite-plugin-uni-pages
UniPages()`,
}
return {
...oldData,
plugins: oldData.plugins.flatMap(plugin =>
plugin.id === 'uni' ? [pagesPlugin, plugin] : plugin,
),
}
}
================================================
FILE: packages/core/template/plugin/root/package.json
================================================
{
"devDependencies": {
"@uni-ku/root": "^1.4.1"
}
}
================================================
FILE: packages/core/template/plugin/root/src/App.ku.vue
================================================
<script setup>
function handleClickGithub() {
if (window?.open) {
window.open('https://github.com/uni-ku/root')
}
else {
uni.showToast({
icon: 'none',
title: '请使用浏览器打开',
})
}
}
</script>
<template>
<div>
<KuRootView />
<div class="root-bar">
Root component By
<span class="color-blue" @click="handleClickGithub">uni-ku/root</span>
</div>
</div>
</template>
<style>
.root-bar {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
height: 40px;
background-color: #f5f5f5;
display: flex;
align-items: center;
justify-content: center;
color: #999;
font-size: 14px;
line-height: 40px;
text-align: center;
box-sizing: border-box;
padding: 0 20px;
}
.color-blue {
color: #409eff;
cursor: pointer;
}
</style>
================================================
FILE: packages/core/template/plugin/root/vite.config.js.data.mjs
================================================
export default function getData({ oldData }) {
const rootPlugin = {
id: 'root',
importer: `import UniRoot from '@uni-ku/root'`,
initializer: `// https://github.com/uni-ku/root
UniRoot()`,
}
return {
...oldData,
plugins: oldData.plugins.flatMap(plugin =>
plugin.id === 'uni' ? [rootPlugin, plugin] : plugin,
),
}
}
================================================
FILE: packages/core/tsconfig.json
================================================
{
"compilerOptions": {
"target": "es2018",
"lib": ["esnext"],
"baseUrl": ".",
"module": "esnext",
"moduleResolution": "node",
"paths": {
"@/*": ["src/*"]
},
"resolveJsonModule": true,
"strict": true,
"strictNullChecks": true,
"esModuleInterop": true,
"skipDefaultLibCheck": true,
"skipLibCheck": true
},
"include": ["src"]
}
================================================
FILE: packages/core/tsup.config.ts
================================================
import { defineConfig } from 'tsup'
import PreprocessorDirectives from 'unplugin-preprocessor-directives/esbuild'
export default ({ watch }: { watch: boolean }) => (
defineConfig({
entry: {
outfile: 'src/index.ts',
},
format: 'cjs',
platform: 'node',
target: 'node14',
minify: watch ? false : 'terser',
clean: true,
esbuildPlugins: [
PreprocessorDirectives(),
],
})
)
================================================
FILE: packages/gui/.cargo/config.toml
================================================
[target.x86_64-pc-windows-msvc]
rustflags = [
"-C",
"target-feature=+crt-static"
]
================================================
FILE: packages/gui/.github/workflows/CI.yml
================================================
name: CI
env:
DEBUG: napi:*
APP_NAME: gui
MACOSX_DEPLOYMENT_TARGET: '10.13'
permissions:
contents: write
id-token: write
on:
push:
branches:
- main
tags-ignore:
- '**'
paths-ignore:
- '**/*.md'
- LICENSE
- '**/*.gitignore'
- .editorconfig
- docs/**
pull_request: null
jobs:
build:
strategy:
fail-fast: false
matrix:
settings:
- host: macos-latest
target: x86_64-apple-darwin
build: yarn build --target x86_64-apple-darwin
- host: windows-latest
build: yarn build --target x86_64-pc-windows-msvc
target: x86_64-pc-windows-msvc
- host: windows-latest
build: |
yarn build --target i686-pc-windows-msvc
yarn test
target: i686-pc-windows-msvc
- host: macos-latest
target: aarch64-apple-darwin
build: yarn build --target aarch64-apple-darwin
- host: windows-latest
target: aarch64-pc-windows-msvc
build: yarn build --target aarch64-pc-windows-msvc
name: stable - ${{ matrix.settings.target }} - node@20
runs-on: ${{ matrix.settings.host }}
steps:
- uses: actions/checkout@v4
- name: Setup node
uses: actions/setup-node@v4
if: ${{ !matrix.settings.docker }}
with:
node-version: 20
cache: yarn
- name: Install
uses: dtolnay/rust-toolchain@stable
if: ${{ !matrix.settings.docker }}
with:
toolchain: stable
targets: ${{ matrix.settings.target }}
- name: Cache cargo
uses: actions/cache@v4
with:
path: |
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
.cargo-cache
target/
key: ${{ matrix.settings.target }}-cargo-${{ matrix.settings.host }}
- uses: goto-bus-stop/setup-zig@v2
if: ${{ matrix.settings.target == 'armv7-unknown-linux-gnueabihf' || matrix.settings.target == 'armv7-unknown-linux-musleabihf' }}
with:
version: 0.13.0
- name: Setup toolchain
run: ${{ matrix.settings.setup }}
if: ${{ matrix.settings.setup }}
shell: bash
- name: Setup node x86
if: matrix.settings.target == 'i686-pc-windows-msvc'
run: yarn config set supportedArchitectures.cpu "ia32"
shell: bash
- name: Install dependencies
run: yarn install
- name: Setup node x86
uses: actions/setup-node@v4
if: matrix.settings.target == 'i686-pc-windows-msvc'
with:
node-version: 20
cache: yarn
architecture: x86
- name: Build in docker
uses: addnab/docker-run-action@v3
if: ${{ matrix.settings.docker }}
with:
image: ${{ matrix.settings.docker }}
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'
run: ${{ matrix.settings.build }}
- name: Build
run: ${{ matrix.settings.build }}
if: ${{ !matrix.settings.docker }}
shell: bash
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: bindings-${{ matrix.settings.target }}
path: ${{ env.APP_NAME }}.*.node
if-no-files-found: error
test-macOS-windows-binding:
name: Test bindings on ${{ matrix.settings.target }} - node@${{ matrix.node }}
needs:
- build
strategy:
fail-fast: false
matrix:
settings:
- host: macos-latest
target: x86_64-apple-darwin
- host: windows-latest
target: x86_64-pc-windows-msvc
node:
- '20'
runs-on: ${{ matrix.settings.host }}
steps:
- uses: actions/checkout@v4
- name: Setup node
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
cache: yarn
architecture: x64
- name: Install dependencies
run: yarn install
- name: Download artifacts
uses: actions/download-artifact@v4
with:
name: bindings-${{ matrix.settings.target }}
path: .
- name: List packages
run: ls -R .
shell: bash
- name: Test bindings
run: yarn test
universal-macOS:
name: Build universal macOS binary
needs:
- build
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- name: Setup node
uses: actions/setup-node@v4
with:
node-version: 20
cache: yarn
- name: Install dependencies
run: yarn install
- name: Download macOS x64 artifact
uses: actions/download-artifact@v4
with:
name: bindings-x86_64-apple-darwin
path: artifacts
- name: Download macOS arm64 artifact
uses: actions/download-artifact@v4
with:
name: bindings-aarch64-apple-darwin
path: artifacts
- name: Combine binaries
run: yarn universal
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: bindings-universal-apple-darwin
path: ${{ env.APP_NAME }}.*.node
if-no-files-found: error
publish:
name: Publish
runs-on: ubuntu-latest
needs:
- test-macOS-windows-binding
- universal-macOS
steps:
- uses: actions/checkout@v4
- name: Setup node
uses: actions/setup-node@v4
with:
node-version: 20
cache: yarn
- name: Install dependencies
run: yarn install
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: artifacts
- name: Move artifacts
run: yarn artifacts
- name: List packages
run: ls -R ./npm
shell: bash
- name: Publish
run: |
npm config set provenance true
if git log -1 --pretty=%B | grep "^[0-9]\+\.[0-9]\+\.[0-9]\+$";
then
echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >> ~/.npmrc
npm publish --access public
elif git log -1 --pretty=%B | grep "^[0-9]\+\.[0-9]\+\.[0-9]\+";
then
echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >> ~/.npmrc
npm publish --tag next --access public
else
echo "Not a release, skipping publish"
fi
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
================================================
FILE: packages/gui/.gitignore
================================================
# Created by https://www.toptal.com/developers/gitignore/api/node
# Edit at https://www.toptal.com/developers/gitignore?templates=node
### Node ###
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
*.lcov
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# TypeScript v1 declaration files
typings/
# TypeScript cache
*.tsbuildinfo
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
.env.test
# parcel-bundler cache (https://parceljs.org/)
.cache
# Next.js build output
.next
# Nuxt.js build / generate output
.nuxt
dist
# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public
# vuepress build output
.vuepress/dist
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# TernJS port file
.tern-port
# Stores VSCode versions used for testing VSCode extensions
.vscode-test
# End of https://www.toptal.com/developers/gitignore/api/node
# Created by https://www.toptal.com/developers/gitignore/api/macos
# Edit at https://www.toptal.com/developers/gitignore?templates=macos
### macOS ###
# General
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
### macOS Patch ###
# iCloud generated files
*.icloud
# End of https://www.toptal.com/developers/gitignore/api/macos
# Created by https://www.toptal.com/developers/gitignore/api/windows
# Edit at https://www.toptal.com/developers/gitignore?templates=windows
### Windows ###
# Windows thumbnail cache files
Thumbs.db
Thumbs.db:encryptable
ehthumbs.db
ehthumbs_vista.db
# Dump file
*.stackdump
# Folder config file
[Dd]esktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msix
*.msm
*.msp
# Windows shortcuts
*.lnk
# End of https://www.toptal.com/developers/gitignore/api/windows
#Added by cargo
/target
Cargo.lock
.pnp.*
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/sdks
!.yarn/versions
*.node
src/ui/index.html
================================================
FILE: packages/gui/.npmignore
================================================
target
Cargo.lock
.cargo
.github
npm
.eslintrc
.prettierignore
rustfmt.toml
yarn.lock
*.node
.yarn
__test__
renovate.json
================================================
FILE: packages/gui/Cargo.toml
================================================
[package]
edition = "2021"
name = "create-uni_gui"
version = "0.0.0"
[lib]
crate-type = [ "cdylib" ]
[dependencies]
# Default enable napi4 feature, see https://nodejs.org/api/n-api.html#node-api-version-matrix
napi = { version = "2.12.2", default-features = false, features = [ "napi4" ] }
napi-derive = "2.12.2"
rfd = "0.15.1"
tao = "0.31.0"
webbrowser = "1.0.3"
wry = "0.47.2"
[build-dependencies]
napi-build = "2.0.1"
[profile.release]
lto = true
strip = "symbols"
================================================
FILE: packages/gui/bin/index.cjs
================================================
#!/usr/bin/env node
const { createWebview } = require('./../index.js')
createWebview()
================================================
FILE: packages/gui/build.rs
================================================
extern crate napi_build;
fn main() {
napi_build::setup();
}
================================================
FILE: packages/gui/bump.config.ts
================================================
// bump.config.ts
import { defineConfig } from 'bumpp'
export default defineConfig({
tag: false,
commit: 'v%s'
})
================================================
FILE: packages/gui/index.d.ts
================================================
/* tslint:disable */
/* eslint-disable */
/* auto-generated by NAPI-RS */
export declare function createWebview(): void
================================================
FILE: packages/gui/index.js
================================================
/* tslint:disable */
/* eslint-disable */
/* prettier-ignore */
/* auto-generated by NAPI-RS */
const { existsSync, readFileSync } = require('fs')
const { join } = require('path')
const { platform, arch } = process
let nativeBinding = null
let localFileExisted = false
let loadError = null
function isMusl() {
// For Node 10
if (!process.report || typeof process.report.getReport !== 'function') {
try {
const lddPath = require('child_process').execSync('which ldd').toString().trim()
return readFileSync(lddPath, 'utf8').includes('musl')
} catch (e) {
return true
}
} else {
const { glibcVersionRuntime } = process.report.getReport().header
return !glibcVersionRuntime
}
}
switch (platform) {
case 'android':
switch (arch) {
case 'arm64':
localFileExisted = existsSync(join(__dirname, 'gui.android-arm64.node'))
try {
if (localFileExisted) {
nativeBinding = require('./gui.android-arm64.node')
} else {
nativeBinding = require('@create-uni/gui-android-arm64')
}
} catch (e) {
loadError = e
}
break
case 'arm':
localFileExisted = existsSync(join(__dirname, 'gui.android-arm-eabi.node'))
try {
if (localFileExisted) {
nativeBinding = require('./gui.android-arm-eabi.node')
} else {
nativeBinding = require('@create-uni/gui-android-arm-eabi')
}
} catch (e) {
loadError = e
}
break
default:
throw new Error(`Unsupported architecture on Android ${arch}`)
}
break
case 'win32':
switch (arch) {
case 'x64':
localFileExisted = existsSync(
join(__dirname, 'gui.win32-x64-msvc.node')
)
try {
if (localFileExisted) {
nativeBinding = require('./gui.win32-x64-msvc.node')
} else {
nativeBinding = require('@create-uni/gui-win32-x64-msvc')
}
} catch (e) {
loadError = e
}
break
case 'ia32':
localFileExisted = existsSync(
join(__dirname, 'gui.win32-ia32-msvc.node')
)
try {
if (localFileExisted) {
nativeBinding = require('./gui.win32-ia32-msvc.node')
} else {
nativeBinding = require('@create-uni/gui-win32-ia32-msvc')
}
} catch (e) {
loadError = e
}
break
case 'arm64':
localFileExisted = existsSync(
join(__dirname, 'gui.win32-arm64-msvc.node')
)
try {
if (localFileExisted) {
nativeBinding = require('./gui.win32-arm64-msvc.node')
} else {
nativeBinding = require('@create-uni/gui-win32-arm64-msvc')
}
} catch (e) {
loadError = e
}
break
default:
throw new Error(`Unsupported architecture on Windows: ${arch}`)
}
break
case 'darwin':
localFileExisted = existsSync(join(__dirname, 'gui.darwin-universal.node'))
try {
if (localFileExisted) {
nativeBinding = require('./gui.darwin-universal.node')
} else {
nativeBinding = require('@create-uni/gui-darwin-universal')
}
break
} catch {}
switch (arch) {
case 'x64':
localFileExisted = existsSync(join(__dirname, 'gui.darwin-x64.node'))
try {
if (localFileExisted) {
nativeBinding = require('./gui.darwin-x64.node')
} else {
nativeBinding = require('@create-uni/gui-darwin-x64')
}
} catch (e) {
loadError = e
}
break
case 'arm64':
localFileExisted = existsSync(
join(__dirname, 'gui.darwin-arm64.node')
)
try {
if (localFileExisted) {
nativeBinding = require('./gui.darwin-arm64.node')
} else {
nativeBinding = require('@create-uni/gui-darwin-arm64')
}
} catch (e) {
loadError = e
}
break
default:
throw new Error(`Unsupported architecture on macOS: ${arch}`)
}
break
case 'freebsd':
if (arch !== 'x64') {
throw new Error(`Unsupported architecture on FreeBSD: ${arch}`)
}
localFileExisted = existsSync(join(__dirname, 'gui.freebsd-x64.node'))
try {
if (localFileExisted) {
nativeBinding = require('./gui.freebsd-x64.node')
} else {
nativeBinding = require('@create-uni/gui-freebsd-x64')
}
} catch (e) {
loadError = e
}
break
case 'linux':
switch (arch) {
case 'x64':
if (isMusl()) {
localFileExisted = existsSync(
join(__dirname, 'gui.linux-x64-musl.node')
)
try {
if (localFileExisted) {
nativeBinding = require('./gui.linux-x64-musl.node')
} else {
nativeBinding = require('@create-uni/gui-linux-x64-musl')
}
} catch (e) {
loadError = e
}
} else {
localFileExisted = existsSync(
join(__dirname, 'gui.linux-x64-gnu.node')
)
try {
if (localFileExisted) {
nativeBinding = require('./gui.linux-x64-gnu.node')
} else {
nativeBinding = require('@create-uni/gui-linux-x64-gnu')
}
} catch (e) {
loadError = e
}
}
break
case 'arm64':
if (isMusl()) {
localFileExisted = existsSync(
join(__dirname, 'gui.linux-arm64-musl.node')
)
try {
if (localFileExisted) {
nativeBinding = require('./gui.linux-arm64-musl.node')
} else {
nativeBinding = require('@create-uni/gui-linux-arm64-musl')
}
} catch (e) {
loadError = e
}
} else {
localFileExisted = existsSync(
join(__dirname, 'gui.linux-arm64-gnu.node')
)
try {
if (localFileExisted) {
nativeBinding = require('./gui.linux-arm64-gnu.node')
} else {
nativeBinding = require('@create-uni/gui-linux-arm64-gnu')
}
} catch (e) {
loadError = e
}
}
break
case 'arm':
if (isMusl()) {
localFileExisted = existsSync(
join(__dirname, 'gui.linux-arm-musleabihf.node')
)
try {
if (localFileExisted) {
nativeBinding = require('./gui.linux-arm-musleabihf.node')
} else {
nativeBinding = require('@create-uni/gui-linux-arm-musleabihf')
}
} catch (e) {
loadError = e
}
} else {
localFileExisted = existsSync(
join(__dirname, 'gui.linux-arm-gnueabihf.node')
)
try {
if (localFileExisted) {
nativeBinding = require('./gui.linux-arm-gnueabihf.node')
} else {
nativeBinding = require('@create-uni/gui-linux-arm-gnueabihf')
}
} catch (e) {
loadError = e
}
}
break
case 'riscv64':
if (isMusl()) {
localFileExisted = existsSync(
join(__dirname, 'gui.linux-riscv64-musl.node')
)
try {
if (localFileExisted) {
nativeBinding = require('./gui.linux-riscv64-musl.node')
} else {
nativeBinding = require('@create-uni/gui-linux-riscv64-musl')
}
} catch (e) {
loadError = e
}
} else {
localFileExisted = existsSync(
join(__dirname, 'gui.linux-riscv64-gnu.node')
)
try {
if (localFileExisted) {
nativeBinding = require('./gui.linux-riscv64-gnu.node')
} else {
nativeBinding = require('@create-uni/gui-linux-riscv64-gnu')
}
} catch (e) {
loadError = e
}
}
break
case 's390x':
localFileExisted = existsSync(
join(__dirname, 'gui.linux-s390x-gnu.node')
)
try {
if (localFileExisted) {
nativeBinding = require('./gui.linux-s390x-gnu.node')
} else {
nativeBinding = require('@create-uni/gui-linux-s390x-gnu')
}
} catch (e) {
loadError = e
}
break
default:
throw new Error(`Unsupported architecture on Linux: ${arch}`)
}
break
default:
throw new Error(`Unsupported OS: ${platform}, architecture: ${arch}`)
}
if (!nativeBinding) {
if (loadError) {
throw loadError
}
throw new Error(`Failed to load native binding`)
}
const { createWebview } = nativeBinding
module.exports.createWebview = createWebview
================================================
FILE: packages/gui/nodemon.json
================================================
{
"watch": ["src"],
"ext": "rs",
"exec": "pnpm run build:debug"
}
================================================
FILE: packages/gui/npm/darwin-arm64/README.md
================================================
# `@create-uni/gui-darwin-arm64`
This is the **aarch64-apple-darwin** binary for `@create-uni/gui`
================================================
FILE: packages/gui/npm/darwin-arm64/package.json
================================================
{
"name": "@create-uni/gui-darwin-arm64",
"version": "0.0.1-beta.1",
"os": [
"darwin"
],
"cpu": [
"arm64"
],
"license": "MIT",
"main": "gui.darwin-arm64.node",
"files": [
"gui.darwin-arm64.node"
],
"engines": {
"node": ">= 10"
},
"repository": "git@github.com:uni-helper/create-uni.git"
}
================================================
FILE: packages/gui/npm/darwin-x64/README.md
================================================
# `@create-uni/gui-darwin-x64`
This is the **x86_64-apple-darwin** binary for `@create-uni/gui`
================================================
FILE: packages/gui/npm/darwin-x64/package.json
================================================
{
"name": "@create-uni/gui-darwin-x64",
"version": "0.0.1-beta.1",
"os": [
"darwin"
],
"cpu": [
"x64"
],
"license": "MIT",
"main": "gui.darwin-x64.node",
"files": [
"gui.darwin-x64.node"
],
"engines": {
"node": ">= 10"
},
"repository": "git@github.com:uni-helper/create-uni.git"
}
================================================
FILE: packages/gui/npm/win32-arm64-msvc/README.md
================================================
# `@create-uni/gui-win32-arm64-msvc`
This is the **aarch64-pc-windows-msvc** binary for `@create-uni/gui`
================================================
FILE: packages/gui/npm/win32-arm64-msvc/package.json
================================================
{
"name": "@create-uni/gui-win32-arm64-msvc",
"version": "0.0.1-beta.1",
"os": [
"win32"
],
"cpu": [
"arm64"
],
"license": "MIT",
"main": "gui.win32-arm64-msvc.node",
"files": [
"gui.win32-arm64-msvc.node"
],
"engines": {
"node": ">= 10"
},
"repository": "git@github.com:uni-helper/create-uni.git"
}
================================================
FILE: packages/gui/npm/win32-ia32-msvc/README.md
================================================
# `@create-uni/gui-win32-ia32-msvc`
This is the **i686-pc-windows-msvc** binary for `@create-uni/gui`
================================================
FILE: packages/gui/npm/win32-ia32-msvc/package.json
================================================
{
"name": "@create-uni/gui-win32-ia32-msvc",
"version": "0.0.1-beta.1",
"os": [
"win32"
],
"cpu": [
"ia32"
],
"license": "MIT",
"main": "gui.win32-ia32-msvc.node",
"files": [
"gui.win32-ia32-msvc.node"
],
"engines": {
"node": ">= 10"
},
"repository": "git@github.com:uni-helper/create-uni.git"
}
================================================
FILE: packages/gui/npm/win32-x64-msvc/README.md
================================================
# `@create-uni/gui-win32-x64-msvc`
This is the **x86_64-pc-windows-msvc** binary for `@create-uni/gui`
================================================
FILE: packages/gui/npm/win32-x64-msvc/package.json
================================================
{
"name": "@create-uni/gui-win32-x64-msvc",
"version": "0.0.1-beta.1",
"os": [
"win32"
],
"cpu": [
"x64"
],
"license": "MIT",
"main": "gui.win32-x64-msvc.node",
"files": [
"gui.win32-x64-msvc.node"
],
"engines": {
"node": ">= 10"
},
"repository": "git@github.com:uni-helper/create-uni.git"
}
================================================
FILE: packages/gui/package.json
================================================
{
"name": "@create-uni/gui",
"version": "0.0.7",
"license": "MIT",
"main": "./bin/index.cjs",
"bin": {
"create-uni-gui": "./bin/index.cjs"
},
"files": [
"bin/index.cjs",
"index.js"
],
"napi": {
"name": "gui",
"triples": {
"defaults": false,
"additional": [
"aarch64-apple-darwin",
"aarch64-pc-windows-msvc",
"x86_64-apple-darwin",
"x86_64-pc-windows-msvc",
"i686-pc-windows-msvc"
]
}
},
"engines": {
"node": ">= 10"
},
"repository": {
"directory": "packages/gui",
"type": "git",
"url": "git+https://github.com/uni-helper/create-uni.git"
},
"scripts": {
"artifacts": "napi artifacts",
"build": "napi build --platform --release",
"build:debug": "napi build --platform",
"dev": "nodemon",
"prepublishOnly": "napi prepublish -t npm",
"test": "ava",
"release": "bumpp",
"universal": "napi universal",
"version": "napi version"
},
"devDependencies": {
"@napi-rs/cli": "^2.18.4"
}
}
================================================
FILE: packages/gui/rustfmt.toml
================================================
tab_spaces = 2
edition = "2021"
================================================
FILE: packages/gui/src/lib.rs
================================================
#![deny(clippy::all)]
#[macro_use]
extern crate napi_derive;
use napi::Result;
use tao::{
event::{Event, WindowEvent},
event_loop::{ControlFlow, EventLoopBuilder},
window::WindowBuilder,
};
use wry::{dpi::LogicalSize, http::Request, WebViewBuilder};
use rfd::FileDialog;
use std::env;
use std::path::PathBuf;
use webbrowser::{open_browser, Browser::Default};
enum UserEvent {
FilePath,
CloseWindow,
DragWindow,
}
#[napi]
pub fn create_webview() -> Result<()> {
let current_dir: PathBuf = env::current_dir().expect("Unable to get current working directory");
let input = match env::var("CREATE_UNI_GUI_INPUT") {
Ok(val) => val,
Err(_) => String::from("default_value"),
};
let current_dir_str = current_dir.to_str().unwrap_or("");
let escaped_current_dir_str = current_dir_str.replace("\\", "\\\\");
let final_string = format!(
"window.create_uni_current_dir=\"{}\";window.create_uni_data={}",
escaped_current_dir_str, input
);
const WINDOW_WIDTH: u32 = 375;
const WINDOW_HEIGHT: u32 = 667;
let event_loop = EventLoopBuilder::<UserEvent>::with_user_event().build();
let window = WindowBuilder::new()
.with_inner_size(LogicalSize {
width: WINDOW_WIDTH,
height: WINDOW_HEIGHT,
})
.with_title("Uni Creator")
.with_resizable(false)
.with_decorations(false)
.build(&event_loop)
.unwrap();
let proxy = event_loop.create_proxy();
let handler = move |req: Request<String>| {
let body = req.body();
let mut req = body.split(['|']);
match req.next().unwrap() {
"file_path" => {
let _ = proxy.send_event(UserEvent::FilePath);
}
"drag_window" => {
let _ = proxy.send_event(UserEvent::DragWindow);
}
"open" => {
let url = req.next().unwrap();
open_browser(Default, url).unwrap();
}
"close" => {
let _ = proxy.send_event(UserEvent::CloseWindow);
}
"install" => {
let message = req.next().unwrap();
println!("{}", message);
let _ = proxy.send_event(UserEvent::CloseWindow);
}
_ => {}
}
};
#[cfg(debug_assertions)]
let webview = WebViewBuilder::new()
.with_url("http://localhost:4006/")
.with_ipc_handler(handler)
.with_initialization_script(&final_string)
.build(&window)
.unwrap();
const HTML_CONTENT: &str = include_str!("ui/index.html");
#[cfg(not(debug_assertions))]
let webview = WebViewBuilder::new()
.with_html(HTML_CONTENT)
.with_ipc_handler(handler)
.with_initialization_script(&final_string)
.build(&window)
.expect("Failed to build WebView in release mode");
event_loop.run(move |event, _, control_flow| {
*control_flow = ControlFlow::Wait;
match event {
Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
}
| Event::UserEvent(UserEvent::CloseWindow) => *control_flow = ControlFlow::Exit,
Event::UserEvent(e) => match e {
UserEvent::FilePath => {
// Show file dialog to select a directory
if let Some(path) = FileDialog::new()
.set_title("Select a directory")
.set_directory(¤t_dir)
.pick_folder()
{
let script = format!(
r#"
window.dispatchEvent(
new CustomEvent('pathEvent', {{
detail: {{ path: '{}' }}
}})
);
"#,
path.to_str().unwrap_or("").replace("\\", "\\\\")
);
webview.evaluate_script(&script).unwrap();
}
}
UserEvent::DragWindow => window.drag_window().unwrap(),
UserEvent::CloseWindow => { /* handled above */ }
},
_ => (),
}
});
}
================================================
FILE: packages/info/bump.config.ts
================================================
// bump.config.ts
import { defineConfig } from 'bumpp'
export default defineConfig({
tag: 'info-v%s',
})
================================================
FILE: packages/info/package.json
================================================
{
"name": "@create-uni/info",
"type": "module",
"version": "0.1.9",
"packageManager": "pnpm@9.9.0",
"description": "快速检测你的uni-app项目",
"author": "FliPPeDround <flippedround@qq.com>",
"license": "MIT",
"funding": "https://afdian.com/a/flippedround",
"homepage": "https://github.com/uni-helper/create-uni#readme",
"repository": {
"directory": "packages/info",
"type": "git",
"url": "git+https://github.com/uni-helper/create-uni.git"
},
"bugs": "https://github.com/uni-helper/create-uni/issues",
"keywords": [
"uni",
"uni-app",
"create-uni",
"cli",
"vue",
"miniapp",
"create"
],
"sideEffects": false,
"bin": {
"create-uni-info": "./dist/outfile.cjs"
},
"files": [
"dist/outfile.cjs"
],
"scripts": {
"build": "tsup",
"dev": "tsup --watch",
"prepublishOnly": "nr build",
"release": "bumpp",
"typecheck": "tsc --noEmit"
},
"devDependencies": {
"@create-uni/shared": "workspace:*",
"@types/envinfo": "^7.8.4",
"@types/minimist": "^1.2.5",
"envinfo": "^7.14.0",
"kolorist": "^1.8.0",
"path-exists": "^5.0.0"
}
}
================================================
FILE: packages/info/src/constants/index.ts
================================================
export const uniDependenciesMap = {
'@uni-helper/uni-use': ['@vueuse/core'],
'@uni-helper/axios-adapter': ['axios'],
'@uni-helper/unocss-preset-uni': ['unocss'],
'@uni-helper/eslint-config': ['eslint'],
'@uni-helper/vite-plugin-uni-tailwind': ['tailwindcss'],
} as Record<string, string[]>
================================================
FILE: packages/info/src/index.ts
================================================
#!/usr/bin/env node
import type { UniPresetEnvInfo } from './types'
import process from 'node:process'
import { generateBanner, ora } from '@create-uni/shared'
import envinfo from 'envinfo'
import { gray, italic, link, red, yellow } from 'kolorist'
import { uniDependenciesMap } from './constants'
import { getBaseDependencies, getUniHelperDependencies } from './utils/dependencies'
import { getUniHelperExtensions, getVolarExtensions, getVSCodeExtensions, paserExtensionList } from './utils/extensions'
import { whichPm } from './utils/whichPm'
export async function getBaseEnvInfo() {
const loadingStopInfo = {
message: '',
code: 0,
}
const _envInfo = JSON.parse(await envinfo.run(
{
npmPackages: '**',
System: ['OS'],
Binaries: ['Node'],
IDEs: ['VSCode'],
},
{
json: true,
showNotFound: true,
},
)) as UniPresetEnvInfo
const os = _envInfo.System.OS
const node = _envInfo.Binaries.Node.version
const vscode = _envInfo.IDEs.VSCode?.version || null
const packageInfo = _envInfo.npmPackages
// 获取npm包信息
let uniHelperDependencies
let baseDependencies
if (packageInfo && Object.keys(packageInfo).includes('@dcloudio/uni-app')) {
uniHelperDependencies = getUniHelperDependencies(packageInfo)
baseDependencies = getBaseDependencies(packageInfo)
}
else {
loadingStopInfo.message = red('⛔ 当前目录未安装uni-app,请在uni-app项目根目录下执行, 以获取依赖信息!!!')
loadingStopInfo.code = 1
}
// 获取vscode扩展信息
let uniHelperExtensions
let volarExtensions
const extensions = getVSCodeExtensions()
if (vscode && extensions) {
uniHelperExtensions = paserExtensionList(getUniHelperExtensions(extensions))
volarExtensions = paserExtensionList(getVolarExtensions(extensions))[0] || null
}
else {
if (loadingStopInfo.code === 1) {
loadingStopInfo.message += `\n${yellow('⚠️ 未找到vscode, 无法获取插件信息, 请自行补充vscode插件信息')}`
}
else {
loadingStopInfo.message += `${yellow('⚠️ 未找到vscode, 无法获取插件信息, 请自行补充vscode插件信息')}`
loadingStopInfo.code = 1
}
}
const pm = await whichPm()
return {
os,
node,
vscode,
uniHelperExtensions,
baseDependencies,
volarExtensions,
packageInfo,
uniHelperDependencies,
packageManager: pm?.name,
loadingStopInfo,
}
}
export async function getUniAppInfo() {
console.log(generateBanner('@uni-create/info - 快速检测 uni-app 环境信息'))
console.log()
const loading = ora('正在获取环境信息...').start()
// 获取环境信息
const baseEnvInfo = await getBaseEnvInfo()
const errorDependencies = baseEnvInfo.uniHelperDependencies || []
const errorExtensions = baseEnvInfo.uniHelperExtensions || []
loading.succeed('获取环境信息完成')
if (baseEnvInfo.loadingStopInfo.code !== 0) {
console.log()
console.log(baseEnvInfo.loadingStopInfo.message)
}
const splitter = '----------------------------------------------'
console.log()
console.log(splitter)
console.log()
// 输出系统环境信息
const systemEnvInfo = {
os: baseEnvInfo.os,
node: baseEnvInfo.node,
packageManager: baseEnvInfo.packageManager,
vscode: baseEnvInfo?.vscode,
volar: baseEnvInfo?.volarExtensions?.version,
}
let baseEnvInfoStr = ''
for (const [key, value] of Object.entries(systemEnvInfo)) {
if (value)
baseEnvInfoStr += ` - ${key}: \`${value}\`\n`
}
console.log(italic('基础环境信息:'))
console.log(baseEnvInfoStr)
// 输出基础依赖信息
const baseDependenciesLength = Object.keys(baseEnvInfo?.baseDependencies || {}).length
if (baseDependenciesLength > 0) {
let baseDependenciesStr = ''
for (const [name, version] of Object.entries(baseEnvInfo.baseDependencies!))
baseDependenciesStr += ` - ${name}: \`${version}\`\n`
console.log(italic('基础依赖信息:'))
console.log(baseDependenciesStr)
}
// 输出uni-helper依赖信息
const uniHelperDependenciesLength = Object.keys(baseEnvInfo?.uniHelperDependencies || {}).length
if (uniHelperDependenciesLength > 0) {
let errorDependenciesStr = ''
for (const [key, value] of Object.entries(errorDependencies)) {
errorDependenciesStr += ` - ${key}: \`${value}\`\n`
if (uniDependenciesMap[key]) {
for (const uniDependency of uniDependenciesMap[key]) {
const packageInfo = baseEnvInfo.packageInfo?.[uniDependency]
if (packageInfo?.installed) {
errorDependenciesStr += ` - ${uniDependency}: \`${packageInfo.installed}\`\n`
}
else {
errorDependenciesStr += ` - ${uniDependency}: \`未安装\`\n`
}
}
}
}
console.log(italic('uni-helper依赖信息:'))
console.log(errorDependenciesStr)
}
// 输出uni-helper插件信息
if (errorExtensions.length > 0) {
let errorExtensionsStr = ''
for (const { name, version, bugs } of errorExtensions)
errorExtensionsStr += ` - ${link(name, bugs)}: \`${version}\`\n`
console.log(italic('uni-helper插件信息:'))
console.log(errorExtensionsStr)
}
console.log(splitter)
console.log()
console.log(
`${[
gray(italic('🎯 感谢使用uni-helper,请提供虚线内的信息以便我们排查问题')),
gray(italic(' 若还需提供其他信息,请自行修改补充')),
'',
'👉 uni-helper 官网: https://uni-helper.js.org/',
'👉 改进建议: https://github.com/uni-helper/create-uni/issues/new/choose',
].join('\n')}\n`,
)
process.exit(0)
}
getUniAppInfo()
================================================
FILE: packages/info/src/question/index.ts
================================================
import process from 'node:process'
import { isCancel, multiselect } from '@clack/prompts'
export default async function question(choices: string[], message: string) {
const result = await multiselect({
message,
options: choices.map(item => ({
value: item,
label: item,
})),
required: false,
})
if (isCancel(result)) {
process.exit(0)
}
return result
}
================================================
FILE: packages/info/src/types/index.d.ts
================================================
export interface UniPresetEnvInfo {
System: {
OS: string
}
Binaries: {
Node: {
version: string
path: string
}
}
IDEs: {
VSCode: {
version: string
path: string
}
WebStorm: {
version: string
path: string
}
}
npmPackages: {
[key: string]: {
installed: string
wanted: string
}
}
}
================================================
FILE: packages/info/src/utils/dependencies.ts
================================================
import type { UniPresetEnvInfo } from '../types'
export function getBaseDependencies(packageInfo: UniPresetEnvInfo['npmPackages']) {
const baseDependenciesName = ['vue', 'vite', '@dcloudio/uni-app']
const baseDependencies: Record<string, string> = {}
for (const name of baseDependenciesName) {
const version = packageInfo[name]?.installed
if (version)
baseDependencies[name] = version
}
return baseDependencies
}
export function getUniHelperDependencies(packageInfo: UniPresetEnvInfo['npmPackages']) {
const uniHelperDependencies: Record<string, string> = {}
for (const name in packageInfo) {
if (name.includes('@uni-helper'))
uniHelperDependencies[name] = packageInfo[name]?.installed || ''
}
return uniHelperDependencies
}
// export async function getErrorDependencies(
// argv: string,
// uniHelperDependencies: Record<string, string>,
// ) {
// if (!uniHelperDependencies)
// return {}
// let errorDependencies: Record<string, string> = {}
// if (argv === 'all') {
// errorDependencies = uniHelperDependencies
// }
// else {
// const uniHelperDependenciesName = Object.keys(uniHelperDependencies)
// const errorIndexList = await question(uniHelperDependenciesName, '请选择需要反馈的依赖')
// errorIndexList.forEach((item) => {
// errorDependencies[item] = uniHelperDependencies[item]
// })
// }
// return errorDependencies
// }
================================================
FILE: packages/info/src/utils/extensions.ts
================================================
import { execSync } from 'node:child_process'
export function getVSCodeExtensions() {
try {
const list = execSync(
`code --list-extensions --show-versions`,
{
encoding: 'utf-8',
stdio: [0, 'pipe', 'ignore'],
},
)
return list.split(/\r?\n/).filter(line => line.trim() !== '')
}
catch {
return null
}
}
export function getUniHelperExtensions(extensions: string[]) {
return extensions.filter(item => item.toLocaleLowerCase().includes('uni-helper.') || item.toLocaleLowerCase().includes('mrmaoddxxaa.create-uniapp-view'))
}
export function getVolarExtensions(extensions: string[]) {
return extensions.filter(item => item.toLocaleLowerCase().includes('vue.volar'))
}
export function paserExtensionList(list: string[]) {
return list.map((item) => {
const [name_, version] = item.split('@')
const [_, name] = name_.split('.')
const bugs = `https://github.com/uni-helper/${name}/issues`
return { name, version, bugs }
})
}
// export async function getErrorExtensions(
// argv: string,
// uniHelperExtensions: ReturnType<typeof paserExtensionList>,
// ) {
// if (!uniHelperExtensions)
// return []
// const choices = uniHelperExtensions.map(item => item.name)
// let errorExtensions: typeof uniHelperExtensions = []
// if (argv === 'all') {
// errorExtensions = uniHelperExtensions
// }
// else {
// const errorIndexList = await question(choices, '请选择需要反馈的vscode插件')
// errorIndexList.forEach((item) => {
// errorExtensions.push(uniHelperExtensions.find(i => i.name === item)!)
// })
// }
// return errorExtensions
// }
================================================
FILE: packages/info/src/utils/whichPm.ts
================================================
import { join } from 'node:path'
import process from 'node:process'
import { pathExists } from 'path-exists'
export async function whichPm() {
const pkgPath = process.cwd()
const modulesPath = join(pkgPath, 'node_modules')
const existsYarnFlagFile = await pathExists(join(modulesPath, '.yarn-integrity'))
if (existsYarnFlagFile)
return { name: 'yarn' }
const existsPnpmFlagFile = await pathExists(join(modulesPath, '.modules.yaml'))
if (existsPnpmFlagFile)
return { name: 'pnpm' }
if (await pathExists(join(pkgPath, 'bun.lockb')))
return { name: 'bun' }
const modulesExists = await pathExists(modulesPath)
return modulesExists ? { name: 'npm' } : null
}
================================================
FILE: packages/info/tsup.config.ts
================================================
import { defineConfig } from 'tsup'
export default ({ watch }: { watch: boolean }) => (
defineConfig({
entry: {
outfile: 'src/index.ts',
},
format: 'cjs',
platform: 'node',
target: 'node14',
minify: watch ? false : 'terser',
clean: true,
})
)
================================================
FILE: packages/mcp/README.md
================================================
# @create-uni/mcp
create-uni的MCP(Model Context Protocol)服务,为AI助手提供创建uni-app项目的能力。
```json
{
"mcpServers": {
"create-uni": {
"command": "npx",
"args": [
"@create-uni/mcp"
]
}
}
}
```
================================================
FILE: packages/mcp/bump.config.ts
================================================
// bump.config.ts
import { defineConfig } from 'bumpp'
export default defineConfig({
tag: 'mcp-v%s',
})
================================================
FILE: packages/mcp/package.json
================================================
{
"name": "@create-uni/mcp",
"type": "module",
"version": "0.1.14",
"packageManager": "pnpm@9.9.0",
"description": "create-uni的mcp服务",
"author": "FliPPeDround <flippedround@qq.com>",
"license": "MIT",
"funding": "https://afdian.com/a/flippedround",
"homepage": "https://github.com/uni-helper/create-uni#readme",
"repository": {
"directory": "packages/mcp",
"type": "git",
"url": "git+https://github.com/uni-helper/create-uni.git"
},
"bugs": "https://github.com/uni-helper/create-uni/issues",
"keywords": [
"uni",
"uni-app",
"create-uni",
"cli",
"vue",
"miniapp",
"create"
],
"sideEffects": false,
"bin": {
"create-uni-mcp": "./dist/outfile.cjs"
},
"files": [
"dist/outfile.cjs"
],
"scripts": {
"build": "tsup",
"dev": "tsup --watch",
"prepublishOnly": "nr build",
"inspect": "mcp-inspector",
"release": "bumpp",
"typecheck": "tsc --noEmit",
"test": "vitest"
},
"devDependencies": {
"@create-uni/config": "workspace:*",
"@create-uni/shared": "workspace:*",
"@modelcontextprotocol/inspector": "^0.16.6",
"@modelcontextprotocol/sdk": "^1.17.5",
"@types/cross-spawn": "^6.0.6",
"cross-spawn": "^7.0.6",
"zod": "3.25.68"
}
}
================================================
FILE: packages/mcp/src/handlers.ts
================================================
import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js'
import type { CreateCustomOptions, CreateWithTemplateOptions } from './types.js'
import { MODULES, PLUGINS, TEMPLATES, UI } from '@create-uni/config'
import { canSkipEmptying } from '@create-uni/shared'
import { sync } from 'cross-spawn'
import { flattenTemplateList } from './utils.js'
/**
* 构建命令行参数
*/
function buildCommandArgs(options: CreateCustomOptions & { templateType?: string }): string[] {
const args: string[] = []
// 项目名称
args.push(options.name)
// TypeScript支持
if (options.needsTypeScript) {
args.push('--ts')
}
// ESLint配置
if (options.needsEslint) {
args.push('-e')
}
// UI组件库
if (options.UIName) {
args.push('-u', options.UIName)
}
// 插件列表
if (options.pluginList?.length) {
options.pluginList.forEach((plugin) => {
args.push('-p', plugin)
})
}
// 模块列表
if (options.moduleList?.length) {
options.moduleList.forEach((module) => {
args.push('-m', module)
})
}
// 强制覆盖
if (options.force) {
args.push('-f')
}
// 模板类型(如果指定)
if (options.templateType) {
args.push('-t', options.templateType)
}
return args
}
/**
* 执行创建命令
*/
function executeCreateCommand(args: string[]): { success: boolean, error?: string } {
const [command, ...commandArgs] = ['npx', 'create-uni@latest', ...args]
const { error } = sync(command, commandArgs, { stdio: 'pipe' })
if (error) {
return { success: false, error: error.message }
}
return { success: true }
}
/**
* 检查目录是否可以创建项目
*/
function checkDirectory(name: string, force?: boolean): { canCreate: boolean, message?: string } {
if (!force) {
const canSkip = canSkipEmptying(name)
if (!canSkip) {
return {
canCreate: false,
message: `目标目录${name}非空,无法创建项目, 请使用 --force 强制覆盖`,
}
}
}
return { canCreate: true }
}
/**
* 使用预设模板创建项目
*/
export async function createWithTemplate(options: CreateWithTemplateOptions): Promise<CallToolResult> {
const { canCreate, message } = checkDirectory(options.name, options.force)
if (!canCreate) {
return {
content: [{
type: 'text',
text: message!,
}],
}
}
const args = buildCommandArgs({
name: options.name,
templateType: options.templateType,
force: options.force,
})
const result = executeCreateCommand(args)
if (!result.success) {
return {
content: [{
type: 'text',
text: `创建项目失败: ${result.error}`,
}],
}
}
const flattenedTemplates = flattenTemplateList(TEMPLATES)
const templateInfo = flattenedTemplates.find(t => t.value === options.templateType)?.description || options.templateType
return {
content: [{
type: 'text' as const,
text: `✅ 使用预设模板创建uni-app项目成功!
📁 项目路径: ${options.name}
🎯 模板类型: ${options.templateType}
📝 模板描述: ${templateInfo}
🚀 项目已创建完成,接下来可以:
1. cd ${options.name}
2. 安装依赖: pnpm install
3. 启动开发: pnpm dev
4. 重要:访问 https://uni-helper.js.org/ 查看更多文档信息`,
}],
}
}
/**
* 使用自定义模板创建项目
*/
export async function createCustom(options: CreateCustomOptions): Promise<CallToolResult> {
const { canCreate, message } = checkDirectory(options.name, options.force)
if (!canCreate) {
return {
content: [{
type: 'text',
text: message!,
}],
}
}
const args = buildCommandArgs(options)
const result = executeCreateCommand(args)
if (!result.success) {
return {
content: [{
type: 'text',
text: `创建项目失败: ${result.error}`,
}],
}
}
const features = []
if (options.needsTypeScript)
features.push('✅ TypeScript支持')
if (options.needsEslint)
features.push('✅ ESLint代码规范')
if (options.UIName) {
const uiInfo = UI.find(ui => ui.value === options.UIName)?.hint || options.UIName
features.push(`✅ UI组件库: ${uiInfo}`)
}
if (options.pluginList?.length) {
const pluginNames = options.pluginList.map((p) => {
const plugin = PLUGINS.find(plugin => plugin.value === p)
return plugin ? `${p} (${plugin.hint})` : p
})
features.push(`✅ 插件: ${pluginNames.join(', ')}`)
}
if (options.moduleList?.length) {
const moduleNames = options.moduleList.map((m) => {
const module = MODULES.find(mod => mod.value === m)
return module ? `${m} (${module.hint})` : m
})
features.push(`✅ 模块: ${moduleNames.join(', ')}`)
}
return {
content: [{
type: 'text',
text: `✅ 创建uni-app项目成功!
📁 项目路径: ${options.name}
${features.length ? `\n🎯 已选择的功能:\n${features.join('\n')}` : ''}
🚀 项目已创建完成,接下来可以:
1. cd ${options.name}
2. 安装依赖: pnpm install
3. 启动开发: pnpm dev
4. 重要:访问 https://uni-helper.js.org/ 查看更多文档信息`,
}],
}
}
================================================
FILE: packages/mcp/src/index.ts
================================================
#!/usr/bin/env node
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
import packageJson from './../package.json'
import { createCustom, createWithTemplate } from './handlers.js'
import { createCustomSchema, createWithTemplateSchema } from './schemas.js'
/**
* create-uni的MCP服务器
* 为AI助手提供创建uni-app项目的能力
*/
const server = new McpServer({
name: packageJson.name,
title: packageJson.description,
version: packageJson.version,
})
/**
* 使用预设模板创建uni-app项目
* 通过选择预设模板快速创建uni-app项目,无需自定义配置
*/
server.registerTool(
'create-with-template',
{
title: '使用预设模板创建uni-app项目',
description: '通过选择预设模板快速创建uni-app项目,无需自定义配置。提供多种预设模板,包括vitesse、wot-starter、零售模板等,适合不同场景的快速启动。',
inputSchema: createWithTemplateSchema.shape,
},
async (input) => {
return await createWithTemplate(input)
},
)
/**
* 使用自定义模板创建uni-app项目
* 通过自定义配置创建uni-app项目,可自由选择插件、模块、UI库等
*/
server.registerTool(
'create-custom',
{
title: '使用自定义模板创建uni-app项目',
description: '通过自定义配置创建uni-app项目,可自由选择TypeScript、ESLint、插件、模块、UI库等。适合需要精细化配置的项目需求,提供完整的定制化能力。',
inputSchema: createCustomSchema.shape,
},
async (input) => {
return createCustom(input)
},
)
// 启动服务器
const transport = new StdioServerTransport()
server.connect(transport)
================================================
FILE: packages/mcp/src/schemas.ts
================================================
import { MODULES, PLUGINS, TEMPLATES, UI } from '@create-uni/config'
import { z } from 'zod'
import { getConfigValuesAsEnum, getTemplateValuesAsEnum, promptBuilder, templatePromptBuilder } from './utils'
/**
* 基于core包中的数据定义Zod schema
* 为AI提供更好的理解和描述
*/
// 模板类型schema
export const templateTypeSchema = z.enum(getTemplateValuesAsEnum(TEMPLATES))
.describe(templatePromptBuilder(TEMPLATES, '预设模板类型, 每个模板都有不同的特点'))
// 插件类型schema
export const pluginListSchema = z.array(z.enum(getConfigValuesAsEnum(PLUGINS)))
.optional()
.default([])
.describe(promptBuilder(PLUGINS, '支持安装的插件列表, 每个插件提供特定功能'))
// 模块类型schema
export const moduleListSchema = z.array(z.enum(getConfigValuesAsEnum(MODULES)))
.optional()
.default([])
.describe(promptBuilder(MODULES, '支持安装的模块列表, 每个模块提供特定功能'))
// UI组件库类型schema
export const uiNameSchema = z.enum(getConfigValuesAsEnum(UI))
.optional()
.default(' ')
.describe(promptBuilder(UI, 'UI组件库名称, 选择合适的组件库加速开发'))
// 基础创建参数schema
export const baseCreateSchema = {
name: z.string().describe('项目路径名称(将作为文件夹名称)').default('.'),
force: z.boolean().optional().describe('是否强制覆盖已存在的目录, 默认为false').default(false),
}
// 预设模板创建schema
export const createWithTemplateSchema = z.object({
...baseCreateSchema,
templateType: templateTypeSchema,
})
// 自定义模板创建schema
export const createCustomSchema = z.object({
...baseCreateSchema,
needsTypeScript: z.boolean().optional().describe('是否需要TypeScript支持, 提供类型安全和更好的开发体验').default(false),
pluginList: pluginListSchema,
moduleList: moduleListSchema,
UIName: uiNameSchema,
needsEslint: z.boolean().optional().describe('是否需要ESLint配置, 统一代码风格和质量').default(false),
})
================================================
FILE: packages/mcp/src/types.ts
================================================
import type { MODULES, PLUGINS, UI } from '@create-uni/config/src'
/**
* 创建项目的基础选项
*/
export interface BaseCreateOptions {
name: string
force?: boolean
}
/**
* 使用模板创建选项
*/
export interface CreateWithTemplateOptions extends BaseCreateOptions {
templateType: string
}
/**
* 自定义创建选项
*/
export interface CreateCustomOptions extends BaseCreateOptions {
needsTypeScript?: boolean
pluginList?: typeof PLUGINS[number]['value'][]
moduleList?: typeof MODULES[number]['value'][]
UIName?: typeof UI[number]['value'] | ' '
needsEslint?: boolean
}
================================================
FILE: packages/mcp/src/utils.ts
================================================
import type { Options } from '@create-uni/config'
import type { BaseTemplateListWithUrl, TemplateList } from '@create-uni/config/src/type'
/**
* 从配置里获取全部的value作为枚举列表
* @template T - 具体的配置项类型,用于从常量中提取字面量类型
* @returns 返回与输入数组顺序对应的值数组,包含具体的字面量类型
*/
export function getConfigValuesAsEnum<T extends readonly Options[]>(config: T) {
return config.map(item => item.value || ' ') as {
[K in keyof T]: T[K] extends { value: infer V }
? V extends string
? V
: ' '
: ' '
}
}
/**
* AI提示词构建器
* 用于组装各种配置项的AI提示词描述
*/
export function promptBuilder(
config: readonly Options[],
prefix: string,
): string {
const descriptions = config.map((module) => {
const parts = module.value ? [`- ${module.value}: ${module.hint}`] : [`- " ": 不安装`]
return parts.join(' ')
})
return `${prefix}: \n${descriptions.join('\n')}`
}
/**
* 扁平化模板数据结构
* 将包含分组的模板数据展开为单层数组
*/
export function flattenTemplateList(templates: TemplateList[]): BaseTemplateListWithUrl[] {
const result: BaseTemplateListWithUrl[] = []
for (const template of templates) {
if ('list' in template && template.list) {
// 处理有子列表的分组模板
result.push(...template.list)
}
else if ('url' in template) {
// 处理单个模板(没有子列表)
result.push(template as BaseTemplateListWithUrl)
}
}
return result
}
/**
* 从模板配置中获取所有的value作为枚举列表
*/
export function getTemplateValuesAsEnum(templates: TemplateList[]): [string, ...string[]] {
const flattened = flattenTemplateList(templates)
return flattened.map(item => item.value) as [string, ...string[]]
}
/**
* 模板AI提示词构建器
* 用于组装模板选项的AI提示词描述
*/
export function templatePromptBuilder(
templates: TemplateList[],
prefix: string,
): string {
const flattened = flattenTemplateList(templates)
const descriptions = flattened.map((template) => {
return `- ${template.value}: ${template.description || '暂无描述'}`
})
return `${prefix}: \n${descriptions.join('\n')}`
}
================================================
FILE: packages/mcp/test/promptBuilder.test.ts
================================================
import { MODULES, UI } from '@create-uni/config'
import t
gitextract_q84dp_cp/ ├── .gitattributes ├── .github/ │ ├── FUNDING.yml │ └── workflows/ │ ├── core_release.yml │ ├── core_test.yml │ ├── core_test_template.yml │ ├── gui_release.yml │ ├── info_release.yml │ ├── info_test.yml │ ├── lint.yml │ ├── mcp_release.yml │ └── uni-app_update.yml ├── .gitignore ├── .vscode/ │ └── settings.json ├── LICENSE ├── README.md ├── eslint.config.js ├── package.json ├── packages/ │ ├── config/ │ │ ├── package.json │ │ └── src/ │ │ ├── index.ts │ │ ├── module.data.ts │ │ ├── plugin.data.ts │ │ ├── template.data.ts │ │ ├── type.d.ts │ │ └── ui.data.ts │ ├── core/ │ │ ├── .gitignore │ │ ├── bump.config.ts │ │ ├── package.json │ │ ├── src/ │ │ │ ├── command/ │ │ │ │ ├── actions/ │ │ │ │ │ ├── gui.ts │ │ │ │ │ └── info.ts │ │ │ │ ├── composeCommand.ts │ │ │ │ ├── index.ts │ │ │ │ └── runCommand.ts │ │ │ ├── constants/ │ │ │ │ └── index.ts │ │ │ ├── index.ts │ │ │ ├── question/ │ │ │ │ ├── choices.ts │ │ │ │ ├── file.ts │ │ │ │ ├── index.ts │ │ │ │ ├── module/ │ │ │ │ │ └── index.ts │ │ │ │ ├── name.ts │ │ │ │ ├── onCancel.ts │ │ │ │ ├── plugin/ │ │ │ │ │ └── index.ts │ │ │ │ ├── template/ │ │ │ │ │ └── index.ts │ │ │ │ ├── type.d.ts │ │ │ │ └── ui/ │ │ │ │ └── index.ts │ │ │ └── utils/ │ │ │ ├── clearFile.ts │ │ │ ├── cloneRepo.ts │ │ │ ├── deepMerge.ts │ │ │ ├── directoryTraverse.ts │ │ │ ├── getCommand.ts │ │ │ ├── getPkgManager.ts │ │ │ ├── index.ts │ │ │ ├── injectUtils.ts │ │ │ ├── jsonStringifyWithoutKeysQuotes.ts │ │ │ ├── printFinish.ts │ │ │ ├── renderTemplate.ts │ │ │ ├── setPackageName.ts │ │ │ ├── sortDependencies.ts │ │ │ ├── types.ts │ │ │ └── validateArgv.ts │ │ ├── template/ │ │ │ ├── UI/ │ │ │ │ ├── ano/ │ │ │ │ │ ├── package.json │ │ │ │ │ ├── src/ │ │ │ │ │ │ └── components/ │ │ │ │ │ │ └── InputEntry.vue │ │ │ │ │ ├── uno.config.js.data.mjs │ │ │ │ │ └── vite.config.js.data.mjs │ │ │ │ ├── nut/ │ │ │ │ │ ├── package.json │ │ │ │ │ ├── src/ │ │ │ │ │ │ ├── App.vue │ │ │ │ │ │ └── components/ │ │ │ │ │ │ └── InputEntry.vue │ │ │ │ │ └── vite.config.js.data.mjs │ │ │ │ ├── tdesign/ │ │ │ │ │ ├── package.json │ │ │ │ │ ├── src/ │ │ │ │ │ │ └── components/ │ │ │ │ │ │ └── InputEntry.vue │ │ │ │ │ └── vite.config.js.data.mjs │ │ │ │ ├── uni/ │ │ │ │ │ ├── package.json │ │ │ │ │ ├── src/ │ │ │ │ │ │ └── components/ │ │ │ │ │ │ └── InputEntry.vue │ │ │ │ │ └── vite.config.js.data.mjs │ │ │ │ ├── unocss/ │ │ │ │ │ └── src/ │ │ │ │ │ ├── components/ │ │ │ │ │ │ ├── AppFooter.vue │ │ │ │ │ │ ├── AppLogos.vue │ │ │ │ │ │ └── InputEntry.vue │ │ │ │ │ └── pages/ │ │ │ │ │ └── index.vue │ │ │ │ ├── uv/ │ │ │ │ │ ├── package.json │ │ │ │ │ ├── src/ │ │ │ │ │ │ ├── App.vue │ │ │ │ │ │ └── components/ │ │ │ │ │ │ └── InputEntry.vue │ │ │ │ │ └── vite.config.js.data.mjs │ │ │ │ ├── uview-pro/ │ │ │ │ │ ├── jsconfig.json │ │ │ │ │ ├── package.json │ │ │ │ │ ├── src/ │ │ │ │ │ │ ├── App.vue │ │ │ │ │ │ ├── components/ │ │ │ │ │ │ │ └── InputEntry.vue │ │ │ │ │ │ └── main.js.data.mjs │ │ │ │ │ └── vite.config.js.data.mjs │ │ │ │ ├── wot/ │ │ │ │ │ ├── .vscode/ │ │ │ │ │ │ └── extensions.json │ │ │ │ │ ├── jsconfig.json │ │ │ │ │ ├── package.json │ │ │ │ │ ├── src/ │ │ │ │ │ │ └── components/ │ │ │ │ │ │ └── InputEntry.vue │ │ │ │ │ └── vite.config.js.data.mjs │ │ │ │ └── wot2/ │ │ │ │ ├── .vscode/ │ │ │ │ │ └── extensions.json │ │ │ │ ├── jsconfig.json │ │ │ │ ├── package.json │ │ │ │ ├── src/ │ │ │ │ │ └── components/ │ │ │ │ │ └── InputEntry.vue │ │ │ │ └── vite.config.js.data.mjs │ │ │ ├── base/ │ │ │ │ ├── .vscode/ │ │ │ │ │ ├── extensions.json │ │ │ │ │ └── settings.json │ │ │ │ ├── _gitignore │ │ │ │ ├── _npmrc │ │ │ │ ├── index.html │ │ │ │ ├── jsconfig.json │ │ │ │ ├── package.json │ │ │ │ ├── src/ │ │ │ │ │ ├── App.vue │ │ │ │ │ ├── components/ │ │ │ │ │ │ ├── AppFooter.vue │ │ │ │ │ │ ├── AppLogos.vue │ │ │ │ │ │ └── InputEntry.vue │ │ │ │ │ ├── main.js.data.mjs │ │ │ │ │ ├── main.js.ejs │ │ │ │ │ ├── manifest.json │ │ │ │ │ ├── pages/ │ │ │ │ │ │ └── index.vue │ │ │ │ │ ├── pages.json │ │ │ │ │ ├── theme.json │ │ │ │ │ └── uni.scss │ │ │ │ ├── unh.config.js.data.mjs │ │ │ │ ├── unh.config.js.ejs │ │ │ │ ├── vite.config.js.data.mjs │ │ │ │ └── vite.config.js.ejs │ │ │ ├── config/ │ │ │ │ ├── lint/ │ │ │ │ │ ├── .vscode/ │ │ │ │ │ │ ├── extensions.json │ │ │ │ │ │ └── settings.json │ │ │ │ │ ├── eslint.config.js │ │ │ │ │ └── package.json │ │ │ │ └── typescript/ │ │ │ │ ├── .vscode/ │ │ │ │ │ └── extensions.json │ │ │ │ ├── jsconfig.json │ │ │ │ └── package.json │ │ │ ├── module/ │ │ │ │ ├── pinia/ │ │ │ │ │ ├── package.json │ │ │ │ │ └── src/ │ │ │ │ │ ├── main.js.data.mjs │ │ │ │ │ └── stores/ │ │ │ │ │ └── counter.js │ │ │ │ ├── uniEcharts/ │ │ │ │ │ ├── jsconfig.json │ │ │ │ │ ├── package.json │ │ │ │ │ └── vite.config.js.data.mjs │ │ │ │ ├── uniNetwork/ │ │ │ │ │ └── package.json │ │ │ │ ├── uniPromises/ │ │ │ │ │ ├── package.json │ │ │ │ │ ├── src/ │ │ │ │ │ │ └── main.js.data.mjs │ │ │ │ │ └── vite.config.js.data.mjs │ │ │ │ ├── uniUse/ │ │ │ │ │ ├── package.json │ │ │ │ │ ├── src/ │ │ │ │ │ │ └── main.js.data.mjs │ │ │ │ │ └── vite.config.js.data.mjs │ │ │ │ ├── unocss/ │ │ │ │ │ ├── .vscode/ │ │ │ │ │ │ └── extensions.json │ │ │ │ │ ├── package.json │ │ │ │ │ ├── src/ │ │ │ │ │ │ └── main.js.data.mjs │ │ │ │ │ ├── uno.config.js.data.mjs │ │ │ │ │ ├── uno.config.js.ejs │ │ │ │ │ └── vite.config.js.data.mjs │ │ │ │ ├── vitest/ │ │ │ │ │ ├── jsconfig.json │ │ │ │ │ ├── package.json │ │ │ │ │ ├── test/ │ │ │ │ │ │ └── index.test.js │ │ │ │ │ └── vitest.config.js │ │ │ │ └── zPaging/ │ │ │ │ ├── jsconfig.json │ │ │ │ ├── package.json │ │ │ │ └── vite.config.js.data.mjs │ │ │ └── plugin/ │ │ │ ├── componentPlaceholder/ │ │ │ │ ├── package.json │ │ │ │ └── vite.config.js.data.mjs │ │ │ ├── filePlatform/ │ │ │ │ ├── package.json │ │ │ │ └── vite.config.js.data.mjs │ │ │ ├── import/ │ │ │ │ ├── package.json │ │ │ │ └── vite.config.js.data.mjs │ │ │ ├── layouts/ │ │ │ │ ├── package.json │ │ │ │ └── vite.config.js.data.mjs │ │ │ ├── manifest/ │ │ │ │ ├── manifest.config.js │ │ │ │ ├── package.json │ │ │ │ ├── unh.config.js.data.mjs │ │ │ │ └── vite.config.js.data.mjs │ │ │ ├── pages/ │ │ │ │ ├── jsconfig.json │ │ │ │ ├── package.json │ │ │ │ ├── pages.config.js │ │ │ │ ├── unh.config.js.data.mjs │ │ │ │ └── vite.config.js.data.mjs │ │ │ └── root/ │ │ │ ├── package.json │ │ │ ├── src/ │ │ │ │ └── App.ku.vue │ │ │ └── vite.config.js.data.mjs │ │ ├── tsconfig.json │ │ └── tsup.config.ts │ ├── gui/ │ │ ├── .cargo/ │ │ │ └── config.toml │ │ ├── .github/ │ │ │ └── workflows/ │ │ │ └── CI.yml │ │ ├── .gitignore │ │ ├── .npmignore │ │ ├── Cargo.toml │ │ ├── bin/ │ │ │ └── index.cjs │ │ ├── build.rs │ │ ├── bump.config.ts │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── nodemon.json │ │ ├── npm/ │ │ │ ├── darwin-arm64/ │ │ │ │ ├── README.md │ │ │ │ └── package.json │ │ │ ├── darwin-x64/ │ │ │ │ ├── README.md │ │ │ │ └── package.json │ │ │ ├── win32-arm64-msvc/ │ │ │ │ ├── README.md │ │ │ │ └── package.json │ │ │ ├── win32-ia32-msvc/ │ │ │ │ ├── README.md │ │ │ │ └── package.json │ │ │ └── win32-x64-msvc/ │ │ │ ├── README.md │ │ │ └── package.json │ │ ├── package.json │ │ ├── rustfmt.toml │ │ └── src/ │ │ └── lib.rs │ ├── info/ │ │ ├── bump.config.ts │ │ ├── package.json │ │ ├── src/ │ │ │ ├── constants/ │ │ │ │ └── index.ts │ │ │ ├── index.ts │ │ │ ├── question/ │ │ │ │ └── index.ts │ │ │ ├── types/ │ │ │ │ └── index.d.ts │ │ │ └── utils/ │ │ │ ├── dependencies.ts │ │ │ ├── extensions.ts │ │ │ └── whichPm.ts │ │ └── tsup.config.ts │ ├── mcp/ │ │ ├── README.md │ │ ├── bump.config.ts │ │ ├── package.json │ │ ├── src/ │ │ │ ├── handlers.ts │ │ │ ├── index.ts │ │ │ ├── schemas.ts │ │ │ ├── types.ts │ │ │ └── utils.ts │ │ ├── test/ │ │ │ └── promptBuilder.test.ts │ │ ├── tsconfig.json │ │ └── tsup.config.ts │ ├── shared/ │ │ ├── package.json │ │ └── src/ │ │ ├── canSkipEmptying.ts │ │ ├── generateBanner.ts │ │ ├── index.ts │ │ └── ora.ts │ └── ui/ │ ├── .gitignore │ ├── components.json │ ├── index.html │ ├── package.json │ ├── postcss.config.js │ ├── src/ │ │ ├── components/ │ │ │ ├── UICheck.tsx │ │ │ ├── footer/ │ │ │ │ └── index.tsx │ │ │ ├── header/ │ │ │ │ └── index.tsx │ │ │ ├── icons/ │ │ │ │ ├── demo.tsx │ │ │ │ ├── eslint.tsx │ │ │ │ ├── gitee.tsx │ │ │ │ ├── github.tsx │ │ │ │ ├── guide.tsx │ │ │ │ ├── rename.tsx │ │ │ │ ├── template.tsx │ │ │ │ ├── typeScript.tsx │ │ │ │ └── vitepress.tsx │ │ │ ├── optionCheck.tsx │ │ │ ├── templateCheck.tsx │ │ │ └── ui/ │ │ │ ├── badge.tsx │ │ │ ├── button.tsx │ │ │ ├── checkbox.tsx │ │ │ ├── context-menu.tsx │ │ │ ├── drawer.tsx │ │ │ ├── input.tsx │ │ │ ├── label.tsx │ │ │ ├── radio-group.tsx │ │ │ └── select.tsx │ │ ├── constants/ │ │ │ └── USER_EVENT.ts │ │ ├── index.tsx │ │ ├── lib/ │ │ │ └── utils.ts │ │ ├── page/ │ │ │ └── index.tsx │ │ ├── style.css │ │ └── types/ │ │ └── gloabal.d.ts │ ├── tailwind.config.js │ ├── tsconfig.json │ └── vite.config.ts ├── pnpm-workspace.yaml ├── scripts/ │ ├── dev.cjs │ └── link.cjs ├── tsconfig.json └── turbo.json
SYMBOL INDEX (160 symbols across 98 files)
FILE: packages/config/src/type.d.ts
type Options (line 1) | interface Options {
type GithubGitee (line 10) | interface GithubGitee {
type AtLeastOne (line 15) | type AtLeastOne<T, U = { [K in keyof T]: Pick<T, K> }> = Partial<T> & U[...
type BaseTemplateListCommon (line 17) | interface BaseTemplateListCommon {
type BaseTemplateListWithUrl (line 46) | interface BaseTemplateListWithUrl extends BaseTemplateListCommon {
type BaseTemplateListWithList (line 56) | interface BaseTemplateListWithList extends BaseTemplateListCommon {
type BaseTemplateList (line 65) | type BaseTemplateList = BaseTemplateListWithUrl | BaseTemplateListWithList
type TemplateList (line 67) | type TemplateList = BaseTemplateList
type CustomTempValue (line 69) | interface CustomTempValue {
type UnCustomTempValue (line 73) | interface UnCustomTempValue {
type TemplateValue (line 79) | type TemplateValue = UnCustomTempValue | CustomTempValue
FILE: packages/core/src/command/actions/gui.ts
function actionGuiCLI (line 6) | function actionGuiCLI() {
FILE: packages/core/src/command/actions/info.ts
function actionInfoCLI (line 4) | function actionInfoCLI() {
FILE: packages/core/src/command/composeCommand.ts
function composeCommand (line 4) | function composeCommand(
FILE: packages/core/src/command/index.ts
function commandAction (line 20) | function commandAction(argv: any) {
FILE: packages/core/src/command/runCommand.ts
function runCommand (line 4) | function runCommand(
FILE: packages/core/src/index.ts
function init (line 42) | async function init() {
FILE: packages/core/src/question/choices.ts
function needsTypeScript (line 3) | function needsTypeScript() {
function needsEslint (line 12) | function needsEslint() {
FILE: packages/core/src/question/index.ts
type Answers (line 12) | interface Answers {
function question (line 23) | async function question(): Promise<Answers> {
FILE: packages/core/src/question/onCancel.ts
function printCancel (line 6) | function printCancel() {
FILE: packages/core/src/question/type.d.ts
type Options (line 1) | interface Options {
FILE: packages/core/src/utils/clearFile.ts
function clearDirectory (line 4) | function clearDirectory(directoryPath: string): void {
FILE: packages/core/src/utils/cloneRepo.ts
function removeGitFolder (line 10) | async function removeGitFolder(localPath: string): Promise<void> {
function cloneRepo (line 15) | async function cloneRepo(gitUrls: string[], localPath: string): Promise<...
function getRepoUrlList (line 49) | function getRepoUrlList(url: UnCustomTempValue['url']) {
function dowloadTemplate (line 55) | async function dowloadTemplate(data: UnCustomTempValue, name: string, ro...
FILE: packages/core/src/utils/deepMerge.ts
function deepMerge (line 9) | function deepMerge(target: any, obj: any) {
FILE: packages/core/src/utils/directoryTraverse.ts
type DirectoryTraverse (line 4) | type DirectoryTraverse = (dir: string, dirCallback: (dir: string) => voi...
FILE: packages/core/src/utils/getCommand.ts
function getCommand (line 1) | function getCommand(packageManager: string, scriptName: string, args?: s...
FILE: packages/core/src/utils/getPkgManager.ts
function getPkgManager (line 3) | function getPkgManager() {
function pkgFromUserAgent (line 8) | function pkgFromUserAgent(userAgent: string | undefined) {
FILE: packages/core/src/utils/injectUtils.ts
function addResolver (line 4) | function addResolver(plugin: PluginData, resolver: string) {
function mergeExtraConfig (line 22) | function mergeExtraConfig(oldConfig: Record<string, any> | null, config:...
FILE: packages/core/src/utils/jsonStringifyWithoutKeysQuotes.ts
function jsonStringifyWithoutKeysQuotes (line 1) | function jsonStringifyWithoutKeysQuotes(obj: object) {
FILE: packages/core/src/utils/printFinish.ts
function printFinish (line 8) | function printFinish(
FILE: packages/core/src/utils/renderTemplate.ts
type Callback (line 18) | type Callback = (dataStore: Record<string, any>) => void
function renderTemplate (line 20) | function renderTemplate(src: string, dest: string, callbacks: Callback[]) {
FILE: packages/core/src/utils/setPackageName.ts
function replaceNameContent (line 4) | function replaceNameContent(filePath: string, projectName: string) {
function replaceProjectName (line 12) | function replaceProjectName(root: string, name: string) {
FILE: packages/core/src/utils/sortDependencies.ts
type PackageJson (line 1) | interface PackageJson {
function sortDependencies (line 9) | function sortDependencies(packageJson: PackageJson): PackageJson {
FILE: packages/core/src/utils/types.ts
type PluginData (line 1) | interface PluginData {
FILE: packages/core/src/utils/validateArgv.ts
type ArgvBase (line 9) | type ArgvBase = string | null
type ArgvList (line 10) | type ArgvList = ArgvBase | string[]
function validateTemplateType (line 12) | function validateTemplateType(argvTemplate: ArgvBase): TemplateValue {
function validateUIName (line 40) | function validateUIName(argvUIName: ArgvBase) {
function validatePlugins (line 51) | function validatePlugins(argvPlugins: ArgvList): [] {
function validateModules (line 63) | function validateModules(argvModules: ArgvList): [] {
FILE: packages/core/template/UI/ano/uno.config.js.data.mjs
function getData (line 1) | function getData({ oldData }) {
FILE: packages/core/template/UI/ano/vite.config.js.data.mjs
function getData (line 1) | function getData({ oldData, utils }) {
FILE: packages/core/template/UI/nut/vite.config.js.data.mjs
function getData (line 1) | function getData({ oldData, utils }) {
FILE: packages/core/template/UI/tdesign/vite.config.js.data.mjs
function getData (line 1) | function getData({ oldData, utils }) {
FILE: packages/core/template/UI/uni/vite.config.js.data.mjs
function getData (line 1) | function getData({ oldData, utils }) {
FILE: packages/core/template/UI/uv/vite.config.js.data.mjs
function getData (line 1) | function getData({ oldData, utils }) {
FILE: packages/core/template/UI/uview-pro/src/main.js.data.mjs
function getData (line 1) | function getData({ oldData }) {
FILE: packages/core/template/UI/uview-pro/vite.config.js.data.mjs
function getData (line 1) | function getData({ oldData, utils }) {
FILE: packages/core/template/UI/wot/vite.config.js.data.mjs
function getData (line 1) | function getData({ oldData, utils }) {
FILE: packages/core/template/UI/wot2/vite.config.js.data.mjs
function getData (line 1) | function getData({ oldData, utils }) {
FILE: packages/core/template/base/src/main.js.data.mjs
function getData (line 1) | function getData() {
FILE: packages/core/template/base/unh.config.js.data.mjs
function getData (line 1) | function getData() {
FILE: packages/core/template/base/vite.config.js.data.mjs
function getData (line 1) | function getData() {
FILE: packages/core/template/module/pinia/src/main.js.data.mjs
function getData (line 1) | function getData({ oldData }) {
FILE: packages/core/template/module/pinia/src/stores/counter.js
function increment (line 6) | function increment() {
FILE: packages/core/template/module/uniEcharts/vite.config.js.data.mjs
function getData (line 1) | function getData({ oldData, utils }) {
FILE: packages/core/template/module/uniPromises/src/main.js.data.mjs
function getData (line 1) | function getData({ oldData }) {
FILE: packages/core/template/module/uniPromises/vite.config.js.data.mjs
function getData (line 1) | function getData({ oldData, utils }) {
FILE: packages/core/template/module/uniUse/src/main.js.data.mjs
function getData (line 1) | function getData({ oldData }) {
FILE: packages/core/template/module/uniUse/vite.config.js.data.mjs
function getData (line 1) | function getData({ oldData, utils }) {
FILE: packages/core/template/module/unocss/src/main.js.data.mjs
function getData (line 1) | function getData({ oldData }) {
FILE: packages/core/template/module/unocss/uno.config.js.data.mjs
function getData (line 1) | function getData() {
FILE: packages/core/template/module/unocss/vite.config.js.data.mjs
function getData (line 1) | function getData({ oldData }) {
FILE: packages/core/template/module/zPaging/vite.config.js.data.mjs
function getData (line 1) | function getData({ oldData, utils }) {
FILE: packages/core/template/plugin/componentPlaceholder/vite.config.js.data.mjs
function getData (line 1) | function getData({ oldData }) {
FILE: packages/core/template/plugin/filePlatform/vite.config.js.data.mjs
function getData (line 1) | function getData({ oldData }) {
FILE: packages/core/template/plugin/import/vite.config.js.data.mjs
function getData (line 1) | function getData({ oldData }) {
FILE: packages/core/template/plugin/layouts/vite.config.js.data.mjs
function getData (line 1) | function getData({ oldData }) {
FILE: packages/core/template/plugin/manifest/unh.config.js.data.mjs
function getData (line 1) | function getData({ oldData }) {
FILE: packages/core/template/plugin/manifest/vite.config.js.data.mjs
function getData (line 1) | function getData({ oldData }) {
FILE: packages/core/template/plugin/pages/unh.config.js.data.mjs
function getData (line 1) | function getData({ oldData }) {
FILE: packages/core/template/plugin/pages/vite.config.js.data.mjs
function getData (line 1) | function getData({ oldData }) {
FILE: packages/core/template/plugin/root/vite.config.js.data.mjs
function getData (line 1) | function getData({ oldData }) {
FILE: packages/gui/build.rs
function main (line 3) | fn main() {
FILE: packages/gui/index.js
function isMusl (line 16) | function isMusl() {
FILE: packages/gui/src/lib.rs
type UserEvent (line 20) | enum UserEvent {
function create_webview (line 27) | pub fn create_webview() -> Result<()> {
FILE: packages/info/src/index.ts
function getBaseEnvInfo (line 13) | async function getBaseEnvInfo() {
function getUniAppInfo (line 82) | async function getUniAppInfo() {
FILE: packages/info/src/question/index.ts
function question (line 4) | async function question(choices: string[], message: string) {
FILE: packages/info/src/types/index.d.ts
type UniPresetEnvInfo (line 1) | interface UniPresetEnvInfo {
FILE: packages/info/src/utils/dependencies.ts
function getBaseDependencies (line 3) | function getBaseDependencies(packageInfo: UniPresetEnvInfo['npmPackages'...
function getUniHelperDependencies (line 14) | function getUniHelperDependencies(packageInfo: UniPresetEnvInfo['npmPack...
FILE: packages/info/src/utils/extensions.ts
function getVSCodeExtensions (line 3) | function getVSCodeExtensions() {
function getUniHelperExtensions (line 19) | function getUniHelperExtensions(extensions: string[]) {
function getVolarExtensions (line 23) | function getVolarExtensions(extensions: string[]) {
function paserExtensionList (line 27) | function paserExtensionList(list: string[]) {
FILE: packages/info/src/utils/whichPm.ts
function whichPm (line 5) | async function whichPm() {
FILE: packages/mcp/src/handlers.ts
function buildCommandArgs (line 11) | function buildCommandArgs(options: CreateCustomOptions & { templateType?...
function executeCreateCommand (line 62) | function executeCreateCommand(args: string[]): { success: boolean, error...
function checkDirectory (line 77) | function checkDirectory(name: string, force?: boolean): { canCreate: boo...
function createWithTemplate (line 94) | async function createWithTemplate(options: CreateWithTemplateOptions): P...
function createCustom (line 147) | async function createCustom(options: CreateCustomOptions): Promise<CallT...
FILE: packages/mcp/src/types.ts
type BaseCreateOptions (line 6) | interface BaseCreateOptions {
type CreateWithTemplateOptions (line 14) | interface CreateWithTemplateOptions extends BaseCreateOptions {
type CreateCustomOptions (line 21) | interface CreateCustomOptions extends BaseCreateOptions {
FILE: packages/mcp/src/utils.ts
function getConfigValuesAsEnum (line 9) | function getConfigValuesAsEnum<T extends readonly Options[]>(config: T) {
function promptBuilder (line 23) | function promptBuilder(
function flattenTemplateList (line 40) | function flattenTemplateList(templates: TemplateList[]): BaseTemplateLis...
function getTemplateValuesAsEnum (line 60) | function getTemplateValuesAsEnum(templates: TemplateList[]): [string, .....
function templatePromptBuilder (line 69) | function templatePromptBuilder(
FILE: packages/shared/src/canSkipEmptying.ts
function canSkipEmptying (line 3) | function canSkipEmptying(dir: string) {
FILE: packages/shared/src/generateBanner.ts
function generateBanner (line 4) | function generateBanner(text: string) {
FILE: packages/shared/src/ora.ts
class Ora (line 4) | class Ora {
method constructor (line 11) | constructor(message: string) {
method setFinishMessage (line 16) | private setFinishMessage(newMessage: string): string {
method start (line 20) | start(): Ora {
method fail (line 30) | fail(message: string): void {
method succeed (line 37) | succeed(message: string): void {
method finish (line 44) | finish(): void {
function ora (line 52) | function ora(message: string) {
FILE: packages/ui/src/components/UICheck.tsx
type TemplateItemProps (line 17) | interface TemplateItemProps {
function UIItem (line 21) | function UIItem({ item }: TemplateItemProps) {
type OptionCheckProps (line 59) | interface OptionCheckProps {
function UICheck (line 64) | function UICheck({ value, options, onChange }: OptionCheckProps) {
FILE: packages/ui/src/components/footer/index.tsx
function Footer (line 6) | function Footer() {
FILE: packages/ui/src/components/header/index.tsx
function Header (line 3) | function Header() {
FILE: packages/ui/src/components/icons/demo.tsx
function Demo (line 3) | function Demo(props: SVGProps<SVGSVGElement>) {
FILE: packages/ui/src/components/icons/eslint.tsx
function Eslint (line 3) | function Eslint(props: SVGProps<SVGSVGElement>) {
FILE: packages/ui/src/components/icons/gitee.tsx
function Gitee (line 3) | function Gitee(props: SVGProps<SVGSVGElement>) {
FILE: packages/ui/src/components/icons/github.tsx
function Github (line 3) | function Github(props: SVGProps<SVGSVGElement>) {
FILE: packages/ui/src/components/icons/guide.tsx
function Guide (line 3) | function Guide(props: SVGProps<SVGSVGElement>) {
FILE: packages/ui/src/components/icons/rename.tsx
function Rename (line 3) | function Rename(props: SVGProps<SVGSVGElement>) {
FILE: packages/ui/src/components/icons/template.tsx
function Template (line 3) | function Template(props: SVGProps<SVGSVGElement>) {
FILE: packages/ui/src/components/icons/typeScript.tsx
function Typescript (line 3) | function Typescript(props: SVGProps<SVGSVGElement>) {
FILE: packages/ui/src/components/icons/vitepress.tsx
function Vitepress (line 3) | function Vitepress(props: SVGProps<SVGSVGElement>) {
FILE: packages/ui/src/components/optionCheck.tsx
type OptionCheckProps (line 8) | interface OptionCheckProps {
function OptionCheck (line 14) | function OptionCheck({ checkList, options, onChange }: OptionCheckProps) {
FILE: packages/ui/src/components/templateCheck.tsx
type TemplateItemProps (line 23) | interface TemplateItemProps {
function TemplateItem (line 27) | function TemplateItem({ item }: TemplateItemProps) {
function TemplateCheck (line 98) | function TemplateCheck({ useTemplate, onChange }: { useTemplate: string,...
FILE: packages/ui/src/components/ui/badge.tsx
type BadgeProps (line 26) | interface BadgeProps
function Badge (line 30) | function Badge({ className, variant, ...props }: BadgeProps) {
FILE: packages/ui/src/components/ui/button.tsx
type ButtonProps (line 37) | interface ButtonProps
FILE: packages/ui/src/components/ui/context-menu.tsx
function ContextMenuShortcut (line 166) | function ContextMenuShortcut({
FILE: packages/ui/src/components/ui/drawer.tsx
function Drawer (line 6) | function Drawer({
function DrawerHeader (line 58) | function DrawerHeader({
function DrawerFooter (line 71) | function DrawerFooter({
FILE: packages/ui/src/components/ui/select.tsx
type SelectItemProps (line 120) | interface SelectItemProps extends React.ComponentPropsWithoutRef<typeof ...
FILE: packages/ui/src/constants/USER_EVENT.ts
type USER_EVENT (line 1) | enum USER_EVENT {
FILE: packages/ui/src/index.tsx
function App (line 15) | function App() {
FILE: packages/ui/src/lib/utils.ts
function cn (line 4) | function cn(...inputs: ClassValue[]) {
FILE: packages/ui/src/page/index.tsx
function CLIInterface (line 41) | function CLIInterface() {
FILE: packages/ui/src/types/gloabal.d.ts
type Window (line 6) | interface Window {
type PathEventDetail (line 19) | interface PathEventDetail {
type PathEvent (line 23) | interface PathEvent extends CustomEvent<PathEventDetail> {}
type WindowEventMap (line 25) | interface WindowEventMap {
FILE: scripts/dev.cjs
function checkFileExists (line 25) | function checkFileExists(filePath) {
function waitForFile (line 34) | async function waitForFile(filePath) {
function main (line 43) | async function main() {
Condensed preview — 266 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (277K chars).
[
{
"path": ".gitattributes",
"chars": 44,
"preview": "packages/core/template/** linguist-vendored\n"
},
{
"path": ".github/FUNDING.yml",
"chars": 158,
"preview": "custom:\n - 'https://afdian.com/a/flippedround'\n - 'https://afdian.com/a/kejun'\n - 'https://github.com/ModyQyW/sponsor"
},
{
"path": ".github/workflows/core_release.yml",
"chars": 610,
"preview": "name: create-uni release CI\n\non:\n push:\n tags:\n - 'core-v*'\n\njobs:\n release:\n name: Release\n runs-on: ub"
},
{
"path": ".github/workflows/core_test.yml",
"chars": 3529,
"preview": "name: create-uni Test CI\n\non:\n push:\n branches:\n - main\n tags-ignore:\n - '**'\n paths:\n - 'packa"
},
{
"path": ".github/workflows/core_test_template.yml",
"chars": 2606,
"preview": "name: create-uni Test Template CI\n\non:\n push:\n branches:\n - main\n tags-ignore:\n - '**'\n paths:\n "
},
{
"path": ".github/workflows/gui_release.yml",
"chars": 4326,
"preview": "name: create-uni/gui CI\nenv:\n DEBUG: napi:*\n APP_NAME: create-uni/gui\n MACOSX_DEPLOYMENT_TARGET: '10.13'\n CARGO_INCR"
},
{
"path": ".github/workflows/info_release.yml",
"chars": 615,
"preview": "name: create-uni/info release CI\n\non:\n push:\n tags:\n - 'info-v*'\n\njobs:\n release:\n name: Release\n runs-o"
},
{
"path": ".github/workflows/info_test.yml",
"chars": 944,
"preview": "name: create-uni/info Test CI\n\non:\n push:\n branches:\n - main\n tags-ignore:\n - '**'\n paths:\n - '"
},
{
"path": ".github/workflows/lint.yml",
"chars": 612,
"preview": "name: Lint\n\non:\n push:\n branches:\n - main\n tags-ignore:\n - '**'\n pull_request:\n branches:\n - m"
},
{
"path": ".github/workflows/mcp_release.yml",
"chars": 612,
"preview": "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:"
},
{
"path": ".github/workflows/uni-app_update.yml",
"chars": 1030,
"preview": "name: update\n\non:\n schedule:\n - cron: '0 1 * * 1'\n\njobs:\n update-dependencies:\n runs-on: ubuntu-latest\n steps"
},
{
"path": ".gitignore",
"chars": 1207,
"preview": "# Created by .ignore support plugin (hsz.mobi)\n### Node template\n# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-e"
},
{
"path": ".vscode/settings.json",
"chars": 596,
"preview": "{\n \"cSpell.words\": [\n \"bumpp\",\n \"dcloudio\",\n \"esno\",\n \"execa\",\n \"gitee\",\n \"kolorist\",\n \"outro\",\n "
},
{
"path": "LICENSE",
"chars": 2257,
"preview": "MIT License\n\nCopyright (c) 2022 FliPPeDround <https://github.com/FliPPeDround>\n\nPermission is hereby granted, free of ch"
},
{
"path": "README.md",
"chars": 5472,
"preview": "<img src='./blink.svg' />\n<a href=\"https://github.com/uni-helper/create-uni/stargazers\"><img src=\"https://img.shields.io"
},
{
"path": "eslint.config.js",
"chars": 216,
"preview": "import uni from '@uni-helper/eslint-config'\n\nexport default uni({\n rules: {\n 'no-console': 'warn',\n },\n ignores: ["
},
{
"path": "package.json",
"chars": 2219,
"preview": "{\n \"name\": \"@create-uni/monorepo\",\n \"type\": \"module\",\n \"private\": true,\n \"packageManager\": \"pnpm@9.9.0\",\n \"descript"
},
{
"path": "packages/config/package.json",
"chars": 800,
"preview": "{\n \"name\": \"@create-uni/config\",\n \"type\": \"module\",\n \"version\": \"0.0.1\",\n \"private\": true,\n \"packageManager\": \"pnpm"
},
{
"path": "packages/config/src/index.ts",
"chars": 374,
"preview": "import type { BaseTemplateListWithList, Options, TemplateList, TemplateValue } from './type'\nimport MODULES from './modu"
},
{
"path": "packages/config/src/module.data.ts",
"chars": 1863,
"preview": "import type { Options } from './type'\nimport { trueColor as rgb } from 'kolorist'\n\nexport default [\n {\n label: rgb(2"
},
{
"path": "packages/config/src/plugin.data.ts",
"chars": 1733,
"preview": "import type { Options } from './type'\nimport { trueColor as rgb } from 'kolorist'\n\nexport default [\n {\n label: rgb(2"
},
{
"path": "packages/config/src/template.data.ts",
"chars": 3024,
"preview": "import type { TemplateList } from './type'\nimport { green, lightMagenta, trueColor as rgb } from 'kolorist'\n\nexport defa"
},
{
"path": "packages/config/src/type.d.ts",
"chars": 1499,
"preview": "export interface Options {\n label: string\n hint: string\n value: string | null\n name: string\n github?: string\n webs"
},
{
"path": "packages/config/src/ui.data.ts",
"chars": 1960,
"preview": "import type { Options } from './type'\nimport { green, trueColor as rgb } from 'kolorist'\n\nexport default [\n {\n label"
},
{
"path": "packages/core/.gitignore",
"chars": 1197,
"preview": "# Created by .ignore support plugin (hsz.mobi)\n### Node template\n# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-e"
},
{
"path": "packages/core/bump.config.ts",
"chars": 108,
"preview": "// bump.config.ts\nimport { defineConfig } from 'bumpp'\n\nexport default defineConfig({\n tag: 'core-v%s',\n})\n"
},
{
"path": "packages/core/package.json",
"chars": 1387,
"preview": "{\n \"name\": \"create-uni\",\n \"type\": \"module\",\n \"version\": \"2.15.0\",\n \"packageManager\": \"pnpm@9.9.0\",\n \"description\": "
},
{
"path": "packages/core/src/command/actions/gui.ts",
"chars": 1401,
"preview": "import process from 'node:process'\nimport { MODULES, PLUGINS, TEMPLATES, UI } from '@create-uni/config'\nimport { sync } "
},
{
"path": "packages/core/src/command/actions/info.ts",
"chars": 631,
"preview": "import { sync } from 'cross-spawn'\nimport { composeCommand } from '../composeCommand'\n\nexport function actionInfoCLI() {"
},
{
"path": "packages/core/src/command/composeCommand.ts",
"chars": 518,
"preview": "import process from 'node:process'\nimport { pkgFromUserAgent } from '@/utils'\n\nexport function composeCommand(\n command"
},
{
"path": "packages/core/src/command/index.ts",
"chars": 554,
"preview": "import process from 'node:process'\nimport { helpMessage } from '@/constants'\nimport { actionGuiCLI } from './actions/gui"
},
{
"path": "packages/core/src/command/runCommand.ts",
"chars": 484,
"preview": "import type { StdioOptions } from 'node:child_process'\nimport { sync } from 'cross-spawn'\n\nexport function runCommand(\n "
},
{
"path": "packages/core/src/constants/index.ts",
"chars": 352,
"preview": "export const helpMessage = `\\\n使用: create-uni [PROJECT_NAME] [OPTION]...\n\\n\n使用CLI创建uni-app项目。\n如果没有参数,则进入交互模式。\n\\n\n选项:\n -t"
},
{
"path": "packages/core/src/index.ts",
"chars": 7436,
"preview": "#!/usr/bin/env node\n\nimport type { UnCustomTempValue } from '@create-uni/config/src/type'\nimport type { Answers } from '"
},
{
"path": "packages/core/src/question/choices.ts",
"chars": 349,
"preview": "import { confirm } from '@clack/prompts'\n\nexport function needsTypeScript() {\n return confirm({\n message: '是否使用 Type"
},
{
"path": "packages/core/src/question/file.ts",
"chars": 577,
"preview": "import { confirm, isCancel } from '@clack/prompts'\nimport { canSkipEmptying } from '@create-uni/shared'\nimport { printCa"
},
{
"path": "packages/core/src/question/index.ts",
"chars": 1398,
"preview": "import type { TemplateValue } from './template/type'\nimport { group } from '@clack/prompts'\nimport { needsEslint, needsT"
},
{
"path": "packages/core/src/question/module/index.ts",
"chars": 313,
"preview": "import type { MultiSelectOptions } from '@clack/prompts'\nimport { multiselect } from '@clack/prompts'\nimport { MODULES }"
},
{
"path": "packages/core/src/question/name.ts",
"chars": 209,
"preview": "import { text } from '@clack/prompts'\n\nexport default () => (\n text({\n message: '请输入项目名称:',\n placeholder: 'uni-ap"
},
{
"path": "packages/core/src/question/onCancel.ts",
"chars": 192,
"preview": "import process from 'node:process'\nimport { cancel } from '@clack/prompts'\n\nexport const cancelMesssage = '操作已取消'\n\nexpor"
},
{
"path": "packages/core/src/question/plugin/index.ts",
"chars": 318,
"preview": "import type { MultiSelectOptions } from '@clack/prompts'\nimport { multiselect } from '@clack/prompts'\nimport { PLUGINS }"
},
{
"path": "packages/core/src/question/template/index.ts",
"chars": 1709,
"preview": "import type { BaseTemplateListWithList, TemplateValue } from '@create-uni/config'\nimport process from 'node:process'\nimp"
},
{
"path": "packages/core/src/question/type.d.ts",
"chars": 135,
"preview": "export interface Options {\n label: string\n hint: string\n value: string | null\n name: string\n github?: string\n webs"
},
{
"path": "packages/core/src/question/ui/index.ts",
"chars": 264,
"preview": "import type { SelectOptions } from '@clack/prompts'\nimport { select } from '@clack/prompts'\nimport { UI } from '@create-"
},
{
"path": "packages/core/src/utils/clearFile.ts",
"chars": 474,
"preview": "import * as fs from 'node:fs'\nimport * as path from 'node:path'\n\nexport function clearDirectory(directoryPath: string): "
},
{
"path": "packages/core/src/utils/cloneRepo.ts",
"chars": 1878,
"preview": "import type { spinner } from '@clack/prompts'\nimport type { UnCustomTempValue } from '@create-uni/config/src/type'\nimpor"
},
{
"path": "packages/core/src/utils/deepMerge.ts",
"chars": 731,
"preview": "const isObject = (val: any) => val && typeof val === 'object'\nconst mergeArrayWithDedupe = (a: any, b: any) => Array.fro"
},
{
"path": "packages/core/src/utils/directoryTraverse.ts",
"chars": 1061,
"preview": "import * as fs from 'node:fs'\nimport * as path from 'node:path'\n\ntype DirectoryTraverse = (dir: string, dirCallback: (di"
},
{
"path": "packages/core/src/utils/getCommand.ts",
"chars": 457,
"preview": "export function getCommand(packageManager: string, scriptName: string, args?: string) {\n if (scriptName === 'install')\n"
},
{
"path": "packages/core/src/utils/getPkgManager.ts",
"chars": 450,
"preview": "import process from 'node:process'\n\nexport function getPkgManager() {\n const pkgInfo = pkgFromUserAgent(process.env.npm"
},
{
"path": "packages/core/src/utils/index.ts",
"chars": 269,
"preview": "export * from './clearFile'\nexport * from './cloneRepo'\nexport * from './directoryTraverse'\nexport * from './getPkgManag"
},
{
"path": "packages/core/src/utils/injectUtils.ts",
"chars": 754,
"preview": "import type { PluginData } from './types'\nimport { deepMerge } from './deepMerge'\n\nfunction addResolver(plugin: PluginDa"
},
{
"path": "packages/core/src/utils/jsonStringifyWithoutKeysQuotes.ts",
"chars": 183,
"preview": "export function jsonStringifyWithoutKeysQuotes(obj: object) {\n const jsonString = JSON.stringify(obj, null, 2).slice(1,"
},
{
"path": "packages/core/src/utils/printFinish.ts",
"chars": 949,
"preview": "import type { spinner } from '@clack/prompts'\nimport type { getPkgManager } from './getPkgManager'\nimport { relative } f"
},
{
"path": "packages/core/src/utils/renderTemplate.ts",
"chars": 2998,
"preview": "import * as fs from 'node:fs'\nimport * as path from 'node:path'\nimport { pathToFileURL } from 'node:url'\n\nimport { deepM"
},
{
"path": "packages/core/src/utils/setPackageName.ts",
"chars": 597,
"preview": "import { existsSync, readFileSync, writeFileSync } from 'node:fs'\nimport { join } from 'node:path'\n\nfunction replaceName"
},
{
"path": "packages/core/src/utils/sortDependencies.ts",
"chars": 774,
"preview": "interface PackageJson {\n dependencies?: Record<string, string>\n devDependencies?: Record<string, string>\n peerDepende"
},
{
"path": "packages/core/src/utils/types.ts",
"chars": 115,
"preview": "export interface PluginData {\n id: string\n importer?: string\n dynamicImporter?: string\n initializer?: string\n}\n"
},
{
"path": "packages/core/src/utils/validateArgv.ts",
"chars": 2136,
"preview": "import type { TemplateValue } from './../question/template/type'\n\nimport process from 'node:process'\nimport { outro } fr"
},
{
"path": "packages/core/template/UI/ano/package.json",
"chars": 117,
"preview": "{\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",
"chars": 582,
"preview": "<script setup>\nimport { ref } from 'vue'\n\nconst name = ref('')\nconst notify = ref()\n\nfunction handleClick() {\n notify.v"
},
{
"path": "packages/core/template/UI/ano/uno.config.js.data.mjs",
"chars": 323,
"preview": "export default function getData({ oldData }) {\n const anoUIConfig = {\n id: 'ano',\n importer: `import { presetAno "
},
{
"path": "packages/core/template/UI/ano/vite.config.js.data.mjs",
"chars": 423,
"preview": "export default function getData({ oldData, utils }) {\n const autoImportAnoUiPlugin = {\n id: 'ano-ui',\n importer: "
},
{
"path": "packages/core/template/UI/nut/package.json",
"chars": 58,
"preview": "{\n \"dependencies\": {\n \"nutui-uniapp\": \"^1.11.2\"\n }\n}\n"
},
{
"path": "packages/core/template/UI/nut/src/App.vue",
"chars": 162,
"preview": "<script setup>\nimport { onLaunch } from '@dcloudio/uni-app'\n\nonLaunch(() => {})\n</script>\n\n<style lang=\"scss\">\n@import \""
},
{
"path": "packages/core/template/UI/nut/src/components/InputEntry.vue",
"chars": 660,
"preview": "<script setup>\nimport { ref } from 'vue'\n\nconst name = ref('')\nconst popupVisible = ref(false)\n\nfunction handleClick() {"
},
{
"path": "packages/core/template/UI/nut/vite.config.js.data.mjs",
"chars": 665,
"preview": "export default function getData({ oldData, utils }) {\n const autoImportNutUiPlugin = {\n id: 'nutui-uniapp',\n impo"
},
{
"path": "packages/core/template/UI/tdesign/package.json",
"chars": 109,
"preview": "{\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",
"chars": 962,
"preview": "<script setup lang=\"ts\">\nimport { ref } from 'vue'\n\nconst name = ref('')\nconst visible = ref(false)\n\nfunction handleClic"
},
{
"path": "packages/core/template/UI/tdesign/vite.config.js.data.mjs",
"chars": 458,
"preview": "export default function getData({ oldData, utils }) {\n const autoImportTDesignUniPlugin = {\n id: 'tdesign-uni',\n "
},
{
"path": "packages/core/template/UI/uni/package.json",
"chars": 62,
"preview": "{\n \"dependencies\": {\n \"@dcloudio/uni-ui\": \"^1.5.12\"\n }\n}\n"
},
{
"path": "packages/core/template/UI/uni/src/components/InputEntry.vue",
"chars": 714,
"preview": "<script setup>\nimport { ref } from 'vue'\n\nconst name = ref('')\nconst popup = ref()\n\nfunction handleClick() {\n popup.val"
},
{
"path": "packages/core/template/UI/uni/vite.config.js.data.mjs",
"chars": 740,
"preview": "export default function getData({ oldData, utils }) {\n const excludeMap = {\n 'root': 'UniKuAppRoot',\n 'uni-echart"
},
{
"path": "packages/core/template/UI/unocss/src/components/AppFooter.vue",
"chars": 402,
"preview": "<script setup>\nfunction handleClickGithub() {\n if (window?.open) {\n window.open('https://github.com/uni-helper/creat"
},
{
"path": "packages/core/template/UI/unocss/src/components/AppLogos.vue",
"chars": 716,
"preview": "<template>\n <view inline-flex cursor-default text-2xl font-300>\n <view\n flex\n flex-col\n items-center\n"
},
{
"path": "packages/core/template/UI/unocss/src/components/InputEntry.vue",
"chars": 587,
"preview": "<script setup>\nimport { ref } from 'vue'\n\nconst name = ref('')\nconst show = ref(false)\n\nfunction handleClick() {\n show."
},
{
"path": "packages/core/template/UI/unocss/src/pages/index.vue",
"chars": 299,
"preview": "<script setup>\nimport AppFooter from '@/components/AppFooter.vue'\nimport AppLogos from '@/components/AppLogos.vue'\nimpor"
},
{
"path": "packages/core/template/UI/uv/package.json",
"chars": 61,
"preview": "{\n \"dependencies\": {\n \"@climblee/uv-ui\": \"^1.1.20\"\n }\n}\n"
},
{
"path": "packages/core/template/UI/uv/src/App.vue",
"chars": 158,
"preview": "<script setup>\nimport { onLaunch } from '@dcloudio/uni-app'\n\nonLaunch(() => {})\n</script>\n\n<style lang=\"scss\">\n@import '"
},
{
"path": "packages/core/template/UI/uv/src/components/InputEntry.vue",
"chars": 721,
"preview": "<script setup>\nimport { ref } from 'vue'\n\nconst name = ref('')\n\nconst popup = ref()\nfunction handleClick() {\n popup.val"
},
{
"path": "packages/core/template/UI/uv/vite.config.js.data.mjs",
"chars": 418,
"preview": "export default function getData({ oldData, utils }) {\n const autoImportUvUiPlugin = {\n id: 'uv-ui',\n importer: `i"
},
{
"path": "packages/core/template/UI/uview-pro/jsconfig.json",
"chars": 76,
"preview": "{\n \"compilerOptions\": {\n \"types\": [\n \"uview-pro/types\"\n ]\n }\n}\n"
},
{
"path": "packages/core/template/UI/uview-pro/package.json",
"chars": 55,
"preview": "{\n \"dependencies\": {\n \"uview-pro\": \"^0.5.18\"\n }\n}\n"
},
{
"path": "packages/core/template/UI/uview-pro/src/App.vue",
"chars": 152,
"preview": "<script setup>\nimport { onLaunch } from '@dcloudio/uni-app'\n\nonLaunch(() => {})\n</script>\n\n<style lang=\"scss\">\n@import \""
},
{
"path": "packages/core/template/UI/uview-pro/src/components/InputEntry.vue",
"chars": 813,
"preview": "<script setup>\nimport { ref } from 'vue'\n\nconst name = ref('')\nconst popupShow = ref(false)\n\nfunction handleClick() {\n "
},
{
"path": "packages/core/template/UI/uview-pro/src/main.js.data.mjs",
"chars": 329,
"preview": "export default function getData({ oldData }) {\n const uViewProEntries = {\n id: 'uview-pro',\n importer: 'import uV"
},
{
"path": "packages/core/template/UI/uview-pro/vite.config.js.data.mjs",
"chars": 706,
"preview": "export default function getData({ oldData, utils }) {\n const autoImportUviewProPlugin = {\n id: 'uview-pro',\n impo"
},
{
"path": "packages/core/template/UI/wot/.vscode/extensions.json",
"chars": 64,
"preview": "{\n \"recommendations\": [\n \"wot-ui.wot-ui-intellisense\"\n ]\n}\n"
},
{
"path": "packages/core/template/UI/wot/jsconfig.json",
"chars": 87,
"preview": "{\n \"compilerOptions\": {\n \"types\": [\n \"wot-design-uni/global.d.ts\"\n ]\n }\n}\n"
},
{
"path": "packages/core/template/UI/wot/package.json",
"chars": 60,
"preview": "{\n \"dependencies\": {\n \"wot-design-uni\": \"^1.14.0\"\n }\n}\n"
},
{
"path": "packages/core/template/UI/wot/src/components/InputEntry.vue",
"chars": 627,
"preview": "<script setup>\nimport { ref } from 'vue'\n\nconst name = ref('')\nconst popupShow = ref(false)\n\nfunction handleClick() {\n "
},
{
"path": "packages/core/template/UI/wot/vite.config.js.data.mjs",
"chars": 442,
"preview": "export default function getData({ oldData, utils }) {\n const autoImportWotDesignUiPlugin = {\n id: 'wot-design-ui',\n "
},
{
"path": "packages/core/template/UI/wot2/.vscode/extensions.json",
"chars": 64,
"preview": "{\n \"recommendations\": [\n \"wot-ui.wot-ui-intellisense\"\n ]\n}\n"
},
{
"path": "packages/core/template/UI/wot2/jsconfig.json",
"chars": 83,
"preview": "{\n \"compilerOptions\": {\n \"types\": [\n \"@wot-ui/ui/global.d.ts\"\n ]\n }\n}\n"
},
{
"path": "packages/core/template/UI/wot2/package.json",
"chars": 105,
"preview": "{\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",
"chars": 627,
"preview": "<script setup>\nimport { ref } from 'vue'\n\nconst name = ref('')\nconst popupShow = ref(false)\n\nfunction handleClick() {\n "
},
{
"path": "packages/core/template/UI/wot2/vite.config.js.data.mjs",
"chars": 427,
"preview": "export default function getData({ oldData, utils }) {\n const autoImportWotUiPlugin = {\n id: 'wot-ui',\n importer: "
},
{
"path": "packages/core/template/base/.vscode/extensions.json",
"chars": 328,
"preview": "{\n \"recommendations\": [\n \"vue.volar\",\n \"mrmaoddxxaa.create-uniapp-view\",\n \"uni-helper.uni-helper-vscode\",\n "
},
{
"path": "packages/core/template/base/.vscode/settings.json",
"chars": 90,
"preview": "{\n \"files.associations\": {\n \"pages.json\": \"jsonc\",\n \"manifest.json\": \"jsonc\"\n }\n}\n"
},
{
"path": "packages/core/template/base/_gitignore",
"chars": 209,
"preview": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\npnpm-debug.log*\nlerna-debug.log*\n\nnode_modules\n.DS_Stor"
},
{
"path": "packages/core/template/base/_npmrc",
"chars": 77,
"preview": "strict-peer-dependencies=false\nauto-install-peers=true\nshamefully-hoist=true\n"
},
{
"path": "packages/core/template/base/index.html",
"chars": 695,
"preview": "<!DOCTYPE html>\n<html>\n <head>\n <meta charset=\"UTF-8\" />\n <link rel=\"icon\" href=\"static/logo.svg\">\n <script>\n "
},
{
"path": "packages/core/template/base/jsconfig.json",
"chars": 341,
"preview": "{\n \"compilerOptions\": {\n \"baseUrl\": \".\",\n \"paths\": {\n \"@/*\": [\"./src/*\"]\n },\n \"types\": [\n \"vite/c"
},
{
"path": "packages/core/template/base/package.json",
"chars": 1740,
"preview": "{\n \"name\": \"uni-app\",\n \"type\": \"module\",\n \"version\": \"0.1.0\",\n \"private\": true,\n \"scripts\": {\n \"dev\": \"unh dev\","
},
{
"path": "packages/core/template/base/src/App.vue",
"chars": 107,
"preview": "<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",
"chars": 596,
"preview": "<script setup>\nfunction handleClickGithub() {\n if (window?.open) {\n window.open('https://github.com/uni-helper/creat"
},
{
"path": "packages/core/template/base/src/components/AppLogos.vue",
"chars": 1137,
"preview": "<script setup>\n</script>\n\n<template>\n <view class=\"container\">\n <view class=\"uni-helper-logo\">\n <image class=\"u"
},
{
"path": "packages/core/template/base/src/components/InputEntry.vue",
"chars": 839,
"preview": "<script setup>\nimport { ref } from 'vue'\n\nconst name = ref('')\nconst show = ref(false)\n\nfunction handleClick() {\n show."
},
{
"path": "packages/core/template/base/src/main.js.data.mjs",
"chars": 216,
"preview": "export default function getData() {\n return {\n entries: [{\n id: 'vue',\n importer: `import { createSSRApp }"
},
{
"path": "packages/core/template/base/src/main.js.ejs",
"chars": 375,
"preview": "<%_ for (const { importer } of entries) { _%>\n<%- importer %>\n<%_ } _%>\nimport App from './App.vue'\n\nexport function cre"
},
{
"path": "packages/core/template/base/src/manifest.json",
"chars": 2225,
"preview": "{\n \"name\": \"\",\n \"appid\": \"\",\n \"description\": \"\",\n \"versionName\": \"1.0.0\",\n \"versionCode\": \"100\",\n \"transformPx\": f"
},
{
"path": "packages/core/template/base/src/pages/index.vue",
"chars": 389,
"preview": "<script setup>\nimport AppFooter from '@/components/AppFooter.vue'\nimport AppLogos from '@/components/AppLogos.vue'\nimpor"
},
{
"path": "packages/core/template/base/src/pages.json",
"chars": 463,
"preview": "{\n \"pages\": [\n {\n \"path\": \"pages/index\",\n \"type\": \"home\"\n }\n ],\n \"globalStyle\": {\n \"backgroundColo"
},
{
"path": "packages/core/template/base/src/theme.json",
"chars": 629,
"preview": "{\n \"light\": {\n \"bgColor\": \"#fcfcfc\",\n \"bgColorBottom\": \"#fcfcfc\",\n \"bgColorTop\": \"#ff6b00\",\n \"bgTxtStyle\": "
},
{
"path": "packages/core/template/base/src/uni.scss",
"chars": 1631,
"preview": "/**\n * 这里是uni-app内置的常用样式变量\n *\n * uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量\n * 如果你是插件开发者,建议你使用scss预"
},
{
"path": "packages/core/template/base/unh.config.js.data.mjs",
"chars": 123,
"preview": "export default function getData() {\n return {\n autoGenerate: {\n pages: false,\n manifest: false,\n },\n }"
},
{
"path": "packages/core/template/base/unh.config.js.ejs",
"chars": 539,
"preview": "import { defineConfig } from '@uni-helper/unh'\n\n/**\n * unh 配置文件\n * 更多配置请参考:https://uni-helper.js.org/unh/\n */\nexport def"
},
{
"path": "packages/core/template/base/vite.config.js.data.mjs",
"chars": 269,
"preview": "export default function getData() {\n return {\n plugins: [{\n id: 'uni',\n importer: `import Uni from '@uni-h"
},
{
"path": "packages/core/template/base/vite.config.js.ejs",
"chars": 1121,
"preview": "import { fileURLToPath, URL } from 'node:url'\n\nimport { defineConfig } from 'vite'\n<%_ for (const { importer } of plugin"
},
{
"path": "packages/core/template/config/lint/.vscode/extensions.json",
"chars": 60,
"preview": "{\n \"recommendations\": [\n \"dbaeumer.vscode-eslint\"\n ]\n}\n"
},
{
"path": "packages/core/template/config/lint/.vscode/settings.json",
"chars": 525,
"preview": "{\n \"editor.codeActionsOnSave\": {\n \"source.fixAll.eslint\": \"explicit\",\n \"source.organizeImports\": \"never\"\n },\n \""
},
{
"path": "packages/core/template/config/lint/eslint.config.js",
"chars": 78,
"preview": "import uniHelper from '@uni-helper/eslint-config'\n\nexport default uniHelper()\n"
},
{
"path": "packages/core/template/config/lint/package.json",
"chars": 175,
"preview": "{\n \"scripts\": {\n \"lint\": \"eslint .\",\n \"lint:fix\": \"eslint . --fix\"\n },\n \"devDependencies\": {\n \"@uni-helper/e"
},
{
"path": "packages/core/template/config/typescript/.vscode/extensions.json",
"chars": 106,
"preview": "{\n \"recommendations\": [\n \"yoavbls.pretty-ts-errors\",\n \"johnsoncodehk.vscode-tsconfig-helper\"\n ]\n}\n"
},
{
"path": "packages/core/template/config/typescript/jsconfig.json",
"chars": 510,
"preview": "{\n \"compilerOptions\": {\n \"lib\": [\"DOM\", \"DOM.Iterable\", \"ESNext\"],\n \"module\": \"ESNext\",\n \"moduleResolution\": \""
},
{
"path": "packages/core/template/config/typescript/package.json",
"chars": 200,
"preview": "{\n \"scripts\": {\n \"type-check\": \"vue-tsc --noEmit\"\n },\n \"devDependencies\": {\n \"@types/node\": \"^25.6.0\",\n \"@vu"
},
{
"path": "packages/core/template/module/pinia/package.json",
"chars": 49,
"preview": "{\n \"dependencies\": {\n \"pinia\": \"2.2.4\"\n }\n}\n"
},
{
"path": "packages/core/template/module/pinia/src/main.js.data.mjs",
"chars": 352,
"preview": "export default function getData({ oldData }) {\n const piniaEntries = {\n id: 'pinia',\n importer: 'import * as Pini"
},
{
"path": "packages/core/template/module/pinia/src/stores/counter.js",
"chars": 228,
"preview": "import { defineStore } from 'pinia'\nimport { ref } from 'vue'\n\nexport const useCounterStore = defineStore('counter', () "
},
{
"path": "packages/core/template/module/uniEcharts/jsconfig.json",
"chars": 79,
"preview": "{\n \"compilerOptions\": {\n \"types\": [\n \"uni-echarts/global\"\n ]\n }\n}\n"
},
{
"path": "packages/core/template/module/uniEcharts/package.json",
"chars": 81,
"preview": "{\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",
"chars": 922,
"preview": "export default function getData({ oldData, utils }) {\n const uniEchartsPlugin = {\n id: 'uni-echarts',\n importer: "
},
{
"path": "packages/core/template/module/uniNetwork/package.json",
"chars": 69,
"preview": "{\n \"dependencies\": {\n \"@uni-helper/uni-network\": \"^0.23.1\"\n }\n}\n"
},
{
"path": "packages/core/template/module/uniPromises/package.json",
"chars": 69,
"preview": "{\n \"dependencies\": {\n \"@uni-helper/uni-promises\": \"^0.2.1\"\n }\n}\n"
},
{
"path": "packages/core/template/module/uniPromises/src/main.js.data.mjs",
"chars": 342,
"preview": "export default function getData({ oldData }) {\n const uniPromisesEntry = {\n id: 'uniPromises',\n }\n return {\n .."
},
{
"path": "packages/core/template/module/uniPromises/vite.config.js.data.mjs",
"chars": 333,
"preview": "export default function getData({ oldData, utils }) {\n const promisesExtraConfig = {\n build: {\n target: 'es6',\n"
},
{
"path": "packages/core/template/module/uniUse/package.json",
"chars": 96,
"preview": "{\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",
"chars": 332,
"preview": "export default function getData({ oldData }) {\n const uniUseEntry = {\n id: 'uniUse',\n }\n return {\n ...oldData,\n"
},
{
"path": "packages/core/template/module/uniUse/vite.config.js.data.mjs",
"chars": 396,
"preview": "export default function getData({ oldData, utils }) {\n const uniUseExtraConfig = {\n build: {\n target: 'es6',\n "
},
{
"path": "packages/core/template/module/unocss/.vscode/extensions.json",
"chars": 50,
"preview": "{\n \"recommendations\": [\n \"antfu.unocss\"\n ]\n}\n"
},
{
"path": "packages/core/template/module/unocss/package.json",
"chars": 303,
"preview": "{\n \"devDependencies\": {\n \"@iconify-json/carbon\": \"^1.2.20\",\n \"@uni-helper/unocss-preset-uni\": \"^0.2.11\",\n \"uno"
},
{
"path": "packages/core/template/module/unocss/src/main.js.data.mjs",
"chars": 272,
"preview": "export default function getData({ oldData }) {\n const unocssEntry = {\n id: 'unocss',\n importer: 'import \\'uno.css"
},
{
"path": "packages/core/template/module/unocss/uno.config.js.data.mjs",
"chars": 207,
"preview": "export default function getData() {\n return {\n config: [{\n id: 'unocss',\n importer: `import { presetUni } "
},
{
"path": "packages/core/template/module/unocss/uno.config.js.ejs",
"chars": 652,
"preview": "import {\n defineConfig,\n presetIcons,\n transformerDirectives,\n transformerVariantGroup,\n} from 'unocss'\n\n<%_ for (co"
},
{
"path": "packages/core/template/module/unocss/vite.config.js.data.mjs",
"chars": 322,
"preview": "export default function getData({ oldData }) {\n const UnoCSSPlugin = {\n id: 'UnoCSS',\n importer: `import UnoCSS f"
},
{
"path": "packages/core/template/module/vitest/jsconfig.json",
"chars": 92,
"preview": "{\n \"compilerOptions\": {\n \"types\": [\n \"vitest-environment-uniapp/types\"\n ]\n }\n}\n"
},
{
"path": "packages/core/template/module/vitest/package.json",
"chars": 138,
"preview": "{\n \"scripts\": {\n \"test\": \"vitest\"\n },\n \"devDependencies\": {\n \"vitest\": \"^4.1.5\",\n \"vitest-environment-uniapp"
},
{
"path": "packages/core/template/module/vitest/test/index.test.js",
"chars": 401,
"preview": "import { beforeAll, describe, expect, it } from 'vitest'\n\ndescribe('test title', () => {\n let page: Page\n beforeAll(as"
},
{
"path": "packages/core/template/module/vitest/vitest.config.js",
"chars": 260,
"preview": "import { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n test: {\n environment: 'uniapp',\n env"
},
{
"path": "packages/core/template/module/zPaging/jsconfig.json",
"chars": 75,
"preview": "{\n \"compilerOptions\": {\n \"types\": [\n \"z-paging/types\"\n ]\n }\n}\n"
},
{
"path": "packages/core/template/module/zPaging/package.json",
"chars": 53,
"preview": "{\n \"dependencies\": {\n \"z-paging\": \"^2.8.8\"\n }\n}\n"
},
{
"path": "packages/core/template/module/zPaging/vite.config.js.data.mjs",
"chars": 449,
"preview": "export default function getData({ oldData, utils }) {\n const autoImportZPagingPlugin = {\n id: 'z-paging-auto-import'"
},
{
"path": "packages/core/template/plugin/componentPlaceholder/package.json",
"chars": 92,
"preview": "{\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",
"chars": 495,
"preview": "export default function getData({ oldData }) {\n const componentPlaceholderPlugin = {\n id: 'componentPlaceholder',\n "
},
{
"path": "packages/core/template/plugin/filePlatform/package.json",
"chars": 84,
"preview": "{\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",
"chars": 421,
"preview": "export default function getData({ oldData }) {\n const platformPlugin = {\n id: 'platform',\n importer: `import UniP"
},
{
"path": "packages/core/template/plugin/import/package.json",
"chars": 87,
"preview": "{\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",
"chars": 473,
"preview": "export default function getData({ oldData }) {\n const autoImportPlugin = {\n id: 'autoImport',\n importer: `import "
},
{
"path": "packages/core/template/plugin/layouts/package.json",
"chars": 84,
"preview": "{\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",
"chars": 414,
"preview": "export default function getData({ oldData }) {\n const layoutsPlugin = {\n id: 'layouts',\n importer: `import UniLay"
},
{
"path": "packages/core/template/plugin/manifest/manifest.config.js",
"chars": 2414,
"preview": "import { defineManifestConfig } from '@uni-helper/vite-plugin-uni-manifest'\n\nexport default defineManifestConfig({\n 'na"
},
{
"path": "packages/core/template/plugin/manifest/package.json",
"chars": 85,
"preview": "{\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",
"chars": 144,
"preview": "export default function getData({ oldData }) {\n return {\n autoGenerate: {\n ...oldData.autoGenerate,\n manif"
},
{
"path": "packages/core/template/plugin/manifest/vite.config.js.data.mjs",
"chars": 421,
"preview": "export default function getData({ oldData }) {\n const manifestPlugin = {\n id: 'manifest',\n importer: `import UniM"
},
{
"path": "packages/core/template/plugin/pages/jsconfig.json",
"chars": 94,
"preview": "{\n \"compilerOptions\": {\n \"types\": [\n \"@uni-helper/vite-plugin-uni-pages\"\n ]\n }\n}\n"
},
{
"path": "packages/core/template/plugin/pages/package.json",
"chars": 82,
"preview": "{\n \"devDependencies\": {\n \"@uni-helper/vite-plugin-uni-pages\": \"^0.3.24\"\n }\n}\n"
},
{
"path": "packages/core/template/plugin/pages/pages.config.js",
"chars": 477,
"preview": "import { defineUniPages } from '@uni-helper/vite-plugin-uni-pages'\n\nexport default defineUniPages({\n pages: [],\n globa"
},
{
"path": "packages/core/template/plugin/pages/unh.config.js.data.mjs",
"chars": 141,
"preview": "export default function getData({ oldData }) {\n return {\n autoGenerate: {\n ...oldData.autoGenerate,\n pages"
},
{
"path": "packages/core/template/plugin/pages/vite.config.js.data.mjs",
"chars": 400,
"preview": "export default function getData({ oldData }) {\n const pagesPlugin = {\n id: 'pages',\n importer: `import UniPages f"
},
{
"path": "packages/core/template/plugin/root/package.json",
"chars": 60,
"preview": "{\n \"devDependencies\": {\n \"@uni-ku/root\": \"^1.4.1\"\n }\n}\n"
},
{
"path": "packages/core/template/plugin/root/src/App.ku.vue",
"chars": 795,
"preview": "<script setup>\nfunction handleClickGithub() {\n if (window?.open) {\n window.open('https://github.com/uni-ku/root')\n "
},
{
"path": "packages/core/template/plugin/root/vite.config.js.data.mjs",
"chars": 357,
"preview": "export default function getData({ oldData }) {\n const rootPlugin = {\n id: 'root',\n importer: `import UniRoot from"
},
{
"path": "packages/core/tsconfig.json",
"chars": 389,
"preview": "{\n \"compilerOptions\": {\n \"target\": \"es2018\",\n \"lib\": [\"esnext\"],\n \"baseUrl\": \".\",\n \"module\": \"esnext\",\n "
},
{
"path": "packages/core/tsup.config.ts",
"chars": 421,
"preview": "import { defineConfig } from 'tsup'\nimport PreprocessorDirectives from 'unplugin-preprocessor-directives/esbuild'\n\nexpor"
},
{
"path": "packages/gui/.cargo/config.toml",
"chars": 87,
"preview": "[target.x86_64-pc-windows-msvc]\nrustflags = [\n \"-C\",\n \"target-feature=+crt-static\"\n]\n"
},
{
"path": "packages/gui/.github/workflows/CI.yml",
"chars": 6866,
"preview": "name: CI\nenv:\n DEBUG: napi:*\n APP_NAME: gui\n MACOSX_DEPLOYMENT_TARGET: '10.13'\npermissions:\n contents: write\n id-to"
},
{
"path": "packages/gui/.gitignore",
"chars": 3235,
"preview": "# Created by https://www.toptal.com/developers/gitignore/api/node\n# Edit at https://www.toptal.com/developers/gitignore?"
},
{
"path": "packages/gui/.npmignore",
"chars": 122,
"preview": "target\nCargo.lock\n.cargo\n.github\nnpm\n.eslintrc\n.prettierignore\nrustfmt.toml\nyarn.lock\n*.node\n.yarn\n__test__\nrenovate.jso"
},
{
"path": "packages/gui/Cargo.toml",
"chars": 472,
"preview": "[package]\nedition = \"2021\"\nname = \"create-uni_gui\"\nversion = \"0.0.0\"\n\n[lib]\ncrate-type = [ \"cdylib\" ]\n\n[dependencies]\n# "
},
{
"path": "packages/gui/bin/index.cjs",
"chars": 89,
"preview": "#!/usr/bin/env node\n\nconst { createWebview } = require('./../index.js')\n\ncreateWebview()\n"
},
{
"path": "packages/gui/build.rs",
"chars": 63,
"preview": "extern crate napi_build;\n\nfn main() {\n napi_build::setup();\n}\n"
},
{
"path": "packages/gui/bump.config.ts",
"chars": 119,
"preview": "// 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",
"chars": 122,
"preview": "/* tslint:disable */\n/* eslint-disable */\n\n/* auto-generated by NAPI-RS */\n\nexport declare function createWebview(): voi"
},
{
"path": "packages/gui/index.js",
"chars": 9071,
"preview": "/* tslint:disable */\n/* eslint-disable */\n/* prettier-ignore */\n\n/* auto-generated by NAPI-RS */\n\nconst { existsSync, re"
},
{
"path": "packages/gui/nodemon.json",
"chars": 72,
"preview": "{\n \"watch\": [\"src\"],\n \"ext\": \"rs\",\n \"exec\": \"pnpm run build:debug\"\n}\n"
},
{
"path": "packages/gui/npm/darwin-arm64/README.md",
"chars": 100,
"preview": "# `@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",
"chars": 331,
"preview": "{\n \"name\": \"@create-uni/gui-darwin-arm64\",\n \"version\": \"0.0.1-beta.1\",\n \"os\": [\n \"darwin\"\n ],\n \"cpu\": [\n \"arm"
},
{
"path": "packages/gui/npm/darwin-x64/README.md",
"chars": 97,
"preview": "# `@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",
"chars": 323,
"preview": "{\n \"name\": \"@create-uni/gui-darwin-x64\",\n \"version\": \"0.0.1-beta.1\",\n \"os\": [\n \"darwin\"\n ],\n \"cpu\": [\n \"x64\"\n"
},
{
"path": "packages/gui/npm/win32-arm64-msvc/README.md",
"chars": 107,
"preview": "# `@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",
"chars": 342,
"preview": "{\n \"name\": \"@create-uni/gui-win32-arm64-msvc\",\n \"version\": \"0.0.1-beta.1\",\n \"os\": [\n \"win32\"\n ],\n \"cpu\": [\n \""
},
{
"path": "packages/gui/npm/win32-ia32-msvc/README.md",
"chars": 103,
"preview": "# `@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",
"chars": 338,
"preview": "{\n \"name\": \"@create-uni/gui-win32-ia32-msvc\",\n \"version\": \"0.0.1-beta.1\",\n \"os\": [\n \"win32\"\n ],\n \"cpu\": [\n \"i"
},
{
"path": "packages/gui/npm/win32-x64-msvc/README.md",
"chars": 104,
"preview": "# `@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",
"chars": 334,
"preview": "{\n \"name\": \"@create-uni/gui-win32-x64-msvc\",\n \"version\": \"0.0.1-beta.1\",\n \"os\": [\n \"win32\"\n ],\n \"cpu\": [\n \"x6"
},
{
"path": "packages/gui/package.json",
"chars": 1050,
"preview": "{\n \"name\": \"@create-uni/gui\",\n \"version\": \"0.0.7\",\n \"license\": \"MIT\",\n \"main\": \"./bin/index.cjs\",\n \"bin\": {\n \"cr"
},
{
"path": "packages/gui/rustfmt.toml",
"chars": 32,
"preview": "tab_spaces = 2\nedition = \"2021\"\n"
},
{
"path": "packages/gui/src/lib.rs",
"chars": 3790,
"preview": "#![deny(clippy::all)]\n\n#[macro_use]\nextern crate napi_derive;\n\nuse napi::Result;\n\nuse tao::{\n event::{Event, WindowEven"
},
{
"path": "packages/info/bump.config.ts",
"chars": 108,
"preview": "// bump.config.ts\nimport { defineConfig } from 'bumpp'\n\nexport default defineConfig({\n tag: 'info-v%s',\n})\n"
},
{
"path": "packages/info/package.json",
"chars": 1141,
"preview": "{\n \"name\": \"@create-uni/info\",\n \"type\": \"module\",\n \"version\": \"0.1.9\",\n \"packageManager\": \"pnpm@9.9.0\",\n \"descripti"
}
]
// ... and 66 more files (download for full content)
About this extraction
This page contains the full source code of the uni-helper/create-uni GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 266 files (233.2 KB), approximately 77.6k tokens, and a symbol index with 160 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.