@doyuli/create-vue 0.0.1-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/bin/index.js +2 -0
  2. package/dist/index.js +1034 -0
  3. package/package.json +31 -0
  4. package/template/base/.editorconfig +8 -0
  5. package/template/base/.gitattributes +1 -0
  6. package/template/base/.prettierrc.json +7 -0
  7. package/template/base/.vscode/extensions.json +3 -0
  8. package/template/base/index.html +14 -0
  9. package/template/base/package.json +32 -0
  10. package/template/base/public/favicon.ico +0 -0
  11. package/template/base/src/App.vue +26 -0
  12. package/template/base/src/layouts/DefaultLayout.vue +11 -0
  13. package/template/base/src/main.ts +14 -0
  14. package/template/base/src/pages/about/index.vue +43 -0
  15. package/template/base/src/pages/home/index.vue +38 -0
  16. package/template/base/src/stores/counter.ts +12 -0
  17. package/template/base/types/env.d.ts.ejs +12 -0
  18. package/template/base/unocss.config.ts +21 -0
  19. package/template/base/vite.config.ts.ejs +42 -0
  20. package/template/eslint/eslint.config.ts +8 -0
  21. package/template/eslint/package.json +12 -0
  22. package/template/git-hooks/package.json +17 -0
  23. package/template/git-hooks/scripts/verify-commit.js +29 -0
  24. package/template/router/default/package.json +6 -0
  25. package/template/router/default/src/router/index.ts +19 -0
  26. package/template/router/unplugin/package.json +9 -0
  27. package/template/router/unplugin/src/router/index.ts +13 -0
  28. package/template/tsconfig/tsconfig.app.json +20 -0
  29. package/template/tsconfig/tsconfig.node.json +19 -0
  30. package/template/vitest/.vscode/extensions.json +3 -0
  31. package/template/vitest/package.json +14 -0
  32. package/template/vitest/src/components/__tests__/HelloWorld.spec.js +11 -0
  33. package/template/vitest/tsconfig.vitest.json +11 -0
  34. package/template/vitest/vitest.config.js +14 -0
package/package.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "@doyuli/create-vue",
3
+ "type": "module",
4
+ "version": "0.0.1-beta.1",
5
+ "description": "@doyuli/create-vue",
6
+ "sideEffects": false,
7
+ "main": "dist/index.js",
8
+ "bin": {
9
+ "create-vue": "bin/index.js"
10
+ },
11
+ "files": [
12
+ "bin",
13
+ "dist",
14
+ "template"
15
+ ],
16
+ "publishConfig": {
17
+ "access": "public"
18
+ },
19
+ "engines": {
20
+ "node": "^20.19.0 || >=22.12.0"
21
+ },
22
+ "dependencies": {
23
+ "@clack/prompts": "^0.11.0",
24
+ "picocolors": "^1.1.1",
25
+ "@doyuli/kits-core": "^0.0.1-beta.1"
26
+ },
27
+ "scripts": {
28
+ "dev": "tsdown --watch",
29
+ "build": "tsdown"
30
+ }
31
+ }
@@ -0,0 +1,8 @@
1
+ [*.{js,jsx,mjs,cjs,ts,tsx,mts,cts,vue,css,scss,sass,less,styl}]
2
+ charset = utf-8
3
+ indent_size = 2
4
+ indent_style = space
5
+ insert_final_newline = true
6
+ trim_trailing_whitespace = true
7
+ end_of_line = lf
8
+ max_line_length = 100
@@ -0,0 +1 @@
1
+ * text=auto eol=lf
@@ -0,0 +1,7 @@
1
+ {
2
+ "semi": false,
3
+ "singleQuote": true,
4
+ "htmlWhitespaceSensitivity": "ignore",
5
+ "trailingComma": "all",
6
+ "arrowParens": "avoid"
7
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "recommendations": ["Vue.volar", "vitest.explorer", "dbaeumer.vscode-eslint"]
3
+ }
@@ -0,0 +1,14 @@
1
+ <!doctype html>
2
+ <html lang="">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <link rel="icon" href="/favicon.ico" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <title>%VITE_APP_TITLE%</title>
8
+ </head>
9
+
10
+ <body>
11
+ <div id="app"></div>
12
+ <script type="module" src="/src/main.ts"></script>
13
+ </body>
14
+ </html>
@@ -0,0 +1,32 @@
1
+ {
2
+ "type": "module",
3
+ "private": true,
4
+ "engines": {
5
+ "node": "^20.19.0 || >=22.12.0"
6
+ },
7
+ "scripts": {
8
+ "dev": "vite",
9
+ "build": "vite build",
10
+ "preview": "vite preview",
11
+ "type-check": "vue-tsc --build"
12
+ },
13
+ "dependencies": {
14
+ "@unocss/reset": "^66.5.1",
15
+ "@vueuse/core": "^13.9.0",
16
+ "pinia": "^3.0.3",
17
+ "vue": "^3.5.18"
18
+ },
19
+ "devDependencies": {
20
+ "@tsconfig/node22": "^22.0.2",
21
+ "@types/node": "^22.16.5",
22
+ "@vitejs/plugin-vue": "^6.0.1",
23
+ "@vue/tsconfig": "^0.7.0",
24
+ "prettier": "3.6.2",
25
+ "typescript": "~5.8.0",
26
+ "unocss": "^66.5.1",
27
+ "unplugin-auto-import": "^20.1.0",
28
+ "vite": "^7.0.6",
29
+ "vite-plugin-vue-devtools": "^8.0.0",
30
+ "vue-tsc": "^3.0.4"
31
+ }
32
+ }
Binary file
@@ -0,0 +1,26 @@
1
+ <script setup lang="ts">
2
+ import { useTitle } from '@vueuse/core'
3
+ import DefaultLayout from '@/layouts/DefaultLayout.vue'
4
+
5
+ const route = useRoute()
6
+
7
+ const layouts: Record<string, any> = {
8
+ DefaultLayout,
9
+ }
10
+ const layout = computed(() => layouts[route.meta.layout as string] || DefaultLayout)
11
+
12
+ const appTitle = import.meta.env.VITE_APP_TITLE
13
+ const title = useTitle(appTitle)
14
+
15
+ watchEffect(() => {
16
+ title.value = route.meta.title ? `${route.meta.title} - ${appTitle}` : appTitle
17
+ })
18
+ </script>
19
+
20
+ <template>
21
+ <component :is="layout">
22
+ <RouterView />
23
+ </component>
24
+ </template>
25
+
26
+ <style scoped></style>
@@ -0,0 +1,11 @@
1
+ <script setup lang="ts"></script>
2
+
3
+ <template>
4
+ <div>
5
+ <main>
6
+ <slot />
7
+ </main>
8
+ </div>
9
+ </template>
10
+
11
+ <style scoped></style>
@@ -0,0 +1,14 @@
1
+ import { createPinia } from 'pinia'
2
+ import { createApp } from 'vue'
3
+ import App from './App.vue'
4
+
5
+ import router from './router'
6
+ import 'virtual:uno.css'
7
+ import '@unocss/reset/tailwind-compat.css'
8
+
9
+ const app = createApp(App)
10
+
11
+ app.use(createPinia())
12
+ app.use(router)
13
+
14
+ app.mount('#app')
@@ -0,0 +1,43 @@
1
+ <script setup lang="ts">
2
+ definePage({
3
+ meta: {
4
+ title: '关于',
5
+ },
6
+ })
7
+ </script>
8
+
9
+ <template>
10
+ <div class="min-h-screen bg-gray-50 flex flex-col items-center px-6 py-12">
11
+ <h1 class="text-4xl font-bold text-gray-900 mb-6">
12
+ About This Template
13
+ </h1>
14
+ <div class="max-w-2xl w-full space-y-6">
15
+ <p class="text-gray-700 leading-relaxed">
16
+ 这是一个自用 Vue 3 开发模板,旨在快速搭建项目。
17
+ 集成了 <span class="font-semibold">Vite、Vue Router、Pinia、UnoCSS、VueUse</span>。
18
+ </p>
19
+
20
+ <div class="bg-white p-6 rounded-xl shadow space-y-3">
21
+ <h2 class="text-2xl font-semibold text-gray-900">
22
+ Features
23
+ </h2>
24
+ <ul class="list-disc list-inside text-gray-700 space-y-1">
25
+ <li>TypeScript 支持</li>
26
+ <li>动态 Layout</li>
27
+ <li>动态 Document Title</li>
28
+ <li>ESLint + Prettier 规范</li>
29
+ <li>Git Hooks + lint-staged</li>
30
+ </ul>
31
+ </div>
32
+
33
+ <router-link
34
+ to="/"
35
+ class="inline-block mt-4 px-6 py-3 rounded-lg bg-indigo-600 text-white font-medium shadow hover:bg-indigo-700 transition"
36
+ >
37
+ Back to Home
38
+ </router-link>
39
+ </div>
40
+ </div>
41
+ </template>
42
+
43
+ <style scoped></style>
@@ -0,0 +1,38 @@
1
+ <script setup lang="ts">
2
+ definePage({
3
+ path: '/',
4
+ meta: {
5
+ title: '首页',
6
+ },
7
+ })
8
+ </script>
9
+
10
+ <template>
11
+ <div class="min-h-screen flex flex-col items-center justify-center bg-gray-50 px-6">
12
+ <div class="text-center space-y-4">
13
+ <h1 class="text-5xl font-extrabold text-gray-900">
14
+ Vue Template
15
+ </h1>
16
+ <p class="text-gray-600 max-w-lg mx-auto">
17
+ 自用 Vue 3 开发模板,集成 Vite、Pinia、Vue Router、UnoCSS 等常用工具。
18
+ </p>
19
+ <div class="flex flex-wrap gap-4 justify-center mt-4">
20
+ <router-link
21
+ to="/about"
22
+ class="px-6 py-3 rounded-lg bg-indigo-600 text-white font-medium shadow hover:bg-indigo-700 transition"
23
+ >
24
+ About Page
25
+ </router-link>
26
+ <a
27
+ href="https://github.com/"
28
+ target="_blank"
29
+ class="px-6 py-3 rounded-lg bg-gray-100 text-gray-800 font-medium shadow hover:bg-gray-200 transition"
30
+ >
31
+ GitHub
32
+ </a>
33
+ </div>
34
+ </div>
35
+ </div>
36
+ </template>
37
+
38
+ <style scoped></style>
@@ -0,0 +1,12 @@
1
+ import { defineStore } from 'pinia'
2
+ import { computed, ref } from 'vue'
3
+
4
+ export const useCounterStore = defineStore('counter', () => {
5
+ const count = ref(0)
6
+ const doubleCount = computed(() => count.value * 2)
7
+ function increment() {
8
+ count.value++
9
+ }
10
+
11
+ return { count, doubleCount, increment }
12
+ })
@@ -0,0 +1,12 @@
1
+ /// <reference types="vite/client" />
2
+ <%_ if (needsAutoRouter) { -%>
3
+ /// <reference types="unplugin-vue-router/client" />
4
+ <%_ } -%>
5
+
6
+ interface ImportMetaEnv {
7
+ readonly VITE_APP_TITLE: string
8
+ }
9
+
10
+ interface ImportMeta {
11
+ readonly env: ImportMetaEnv
12
+ }
@@ -0,0 +1,21 @@
1
+ import {
2
+ defineConfig,
3
+ presetAttributify,
4
+ presetIcons,
5
+ presetUno,
6
+ } from 'unocss'
7
+
8
+ export default defineConfig({
9
+ presets: [
10
+ presetUno(),
11
+ presetAttributify(),
12
+ presetIcons({
13
+ scale: 1.2,
14
+ warn: true,
15
+ extraProperties: {
16
+ 'display': 'inline-block',
17
+ 'vertical-align': 'middle',
18
+ },
19
+ }),
20
+ ],
21
+ })
@@ -0,0 +1,42 @@
1
+ import { fileURLToPath, URL } from 'node:url'
2
+
3
+ import vue from '@vitejs/plugin-vue'
4
+ import UnoCSS from 'unocss/vite'
5
+ import AutoImport from 'unplugin-auto-import/vite'
6
+ <%_ if (needsAutoRouter) { -%>
7
+ import { VueRouterAutoImports } from 'unplugin-vue-router'
8
+ import VueRouter from 'unplugin-vue-router/vite'
9
+ <%_ } -%>
10
+ import { defineConfig } from 'vite'
11
+ import vueDevTools from 'vite-plugin-vue-devtools'
12
+
13
+ // https://vite.dev/config/
14
+ export default defineConfig({
15
+ plugins: [
16
+ <%_ if (needsAutoRouter) { -%>
17
+ VueRouter({
18
+ dts: 'types/typed-router.d.ts',
19
+ }),
20
+ // ⚠️ Vue must be placed after VueRouter()
21
+ <%_ } -%>
22
+ vue(),
23
+ AutoImport({
24
+ imports: [
25
+ 'vue',
26
+ <%_ if (needsAutoRouter) { -%>
27
+ VueRouterAutoImports,
28
+ <%_ } else { -%>
29
+ 'vue-router',
30
+ <%_ } -%>
31
+ ],
32
+ dts: 'types/auto-imports.d.ts',
33
+ }),
34
+ UnoCSS(),
35
+ vueDevTools(),
36
+ ],
37
+ resolve: {
38
+ alias: {
39
+ '@': fileURLToPath(new URL('./src', import.meta.url)),
40
+ },
41
+ },
42
+ })
@@ -0,0 +1,8 @@
1
+ import antfu from '@antfu/eslint-config'
2
+
3
+ export default antfu(
4
+ {
5
+ formatters: true,
6
+ ignores: ['README.md'],
7
+ },
8
+ )
@@ -0,0 +1,12 @@
1
+ {
2
+ "scripts": {
3
+ "lint": "eslint",
4
+ "lint:fix": "eslint --fix"
5
+ },
6
+ "devDependencies": {
7
+ "@antfu/eslint-config": "^5.3.0",
8
+ "eslint": "^9.31.0",
9
+ "eslint-plugin-format": "^1.0.1",
10
+ "eslint-plugin-vue": "~10.3.0"
11
+ }
12
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "scripts": {
3
+ "postinstall": "simple-git-hooks"
4
+ },
5
+ "devDependencies": {
6
+ "picocolors": "^1.1.1",
7
+ "lint-staged": "^16.1.6",
8
+ "simple-git-hooks": "^2.13.1"
9
+ },
10
+ "simple-git-hooks": {
11
+ "pre-commit": "pnpm lint-staged",
12
+ "commit-msg": "node scripts/verify-commit.js"
13
+ },
14
+ "lint-staged": {
15
+ "*": "eslint --fix"
16
+ }
17
+ }
@@ -0,0 +1,29 @@
1
+ // @ts-check
2
+
3
+ import { readFileSync } from 'node:fs'
4
+ import path from 'node:path'
5
+ import process from 'node:process'
6
+ import pico from 'picocolors'
7
+
8
+ const msgPath = path.resolve('.git/COMMIT_EDITMSG')
9
+ const msg = readFileSync(msgPath, 'utf-8').trim()
10
+
11
+ // eslint-disable-next-line regexp/no-unused-capturing-group
12
+ const commitRE = /^(revert: )?(feat|fix|docs|dx|style|refactor|perf|test|workflow|build|ci|chore|types|wip|release)(\(.+\))?: .{1,50}/
13
+
14
+ if (!commitRE.test(msg)) {
15
+ console.log()
16
+ console.error(
17
+ ` ${pico.white(pico.bgRed(' ERROR '))} ${pico.red(
18
+ `invalid commit message format.`,
19
+ )}\n\n${pico.red(
20
+ ` Proper commit message format is required for automated changelog generation. Examples:\n\n`,
21
+ )} ${pico.green(`feat(compiler): add 'comments' option`)}\n`
22
+ + ` ${pico.green(
23
+ `fix(v-model): handle events on blur (close #28)`,
24
+ )}\n\n${pico.red(
25
+ ` See https://github.com/vuejs/core/blob/main/.github/commit-convention.md for more details.\n`,
26
+ )}`,
27
+ )
28
+ process.exit(1)
29
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "dependencies": {
3
+ "vue": "^3.5.18",
4
+ "vue-router": "^4.5.1"
5
+ }
6
+ }
@@ -0,0 +1,19 @@
1
+ import { createRouter, createWebHistory } from 'vue-router'
2
+
3
+ const router = createRouter({
4
+ history: createWebHistory(import.meta.env.BASE_URL),
5
+ routes: [
6
+ {
7
+ path: '/',
8
+ name: 'home',
9
+ component: () => import('../pages/home/index.vue'),
10
+ },
11
+ {
12
+ path: '/about',
13
+ name: 'about',
14
+ component: () => import('../pages/about/index.vue'),
15
+ },
16
+ ],
17
+ })
18
+
19
+ export default router
@@ -0,0 +1,9 @@
1
+ {
2
+ "dependencies": {
3
+ "vue": "^3.5.18",
4
+ "vue-router": "^4.5.1"
5
+ },
6
+ "devDependencies": {
7
+ "unplugin-vue-router": "^0.15.0"
8
+ }
9
+ }
@@ -0,0 +1,13 @@
1
+ import { createRouter, createWebHistory } from 'vue-router'
2
+ import { handleHotUpdate, routes } from 'vue-router/auto-routes'
3
+
4
+ const router = createRouter({
5
+ history: createWebHistory(import.meta.env.BASE_URL),
6
+ routes,
7
+ })
8
+
9
+ if (import.meta.hot) {
10
+ handleHotUpdate(router)
11
+ }
12
+
13
+ export default router
@@ -0,0 +1,20 @@
1
+ {
2
+ "extends": "@vue/tsconfig/tsconfig.dom.json",
3
+ "compilerOptions": {
4
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
5
+ "target": "esnext",
6
+ "lib": ["esnext", "dom"],
7
+ "moduleResolution": "Bundler",
8
+ "paths": {
9
+ "@/*": ["./src/*"]
10
+ }
11
+ },
12
+ "include": [
13
+ "types/env.d.ts",
14
+ "types/auto-imports.d.ts",
15
+ "types/typed-router.d.ts",
16
+ "src/**/*",
17
+ "src/**/*.vue"
18
+ ],
19
+ "exclude": ["src/**/__tests__/*"]
20
+ }
@@ -0,0 +1,19 @@
1
+ {
2
+ "extends": "@tsconfig/node22/tsconfig.json",
3
+ "compilerOptions": {
4
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
5
+
6
+ "module": "ESNext",
7
+ "moduleResolution": "Bundler",
8
+ "types": ["node"],
9
+ "noEmit": true
10
+ },
11
+ "include": [
12
+ "vite.config.*",
13
+ "vitest.config.*",
14
+ "cypress.config.*",
15
+ "nightwatch.conf.*",
16
+ "playwright.config.*",
17
+ "eslint.config.*"
18
+ ]
19
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "recommendations": ["vitest.explorer"]
3
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "scripts": {
3
+ "test:unit": "vitest"
4
+ },
5
+ "dependencies": {
6
+ "vue": "^3.5.21"
7
+ },
8
+ "devDependencies": {
9
+ "@types/jsdom": "^21.1.7",
10
+ "@vue/test-utils": "^2.4.6",
11
+ "jsdom": "^26.1.0",
12
+ "vitest": "^3.2.4"
13
+ }
14
+ }
@@ -0,0 +1,11 @@
1
+ import { describe, it, expect } from 'vitest'
2
+
3
+ import { mount } from '@vue/test-utils'
4
+ import HelloWorld from '../HelloWorld.vue'
5
+
6
+ describe('HelloWorld', () => {
7
+ it('renders properly', () => {
8
+ const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } })
9
+ expect(wrapper.text()).toContain('Hello Vitest')
10
+ })
11
+ })
@@ -0,0 +1,11 @@
1
+ {
2
+ "extends": "./tsconfig.app.json",
3
+ "include": ["src/**/__tests__/*", "env.d.ts"],
4
+ "exclude": [],
5
+ "compilerOptions": {
6
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.vitest.tsbuildinfo",
7
+
8
+ "lib": [],
9
+ "types": ["node", "jsdom"]
10
+ }
11
+ }
@@ -0,0 +1,14 @@
1
+ import { fileURLToPath } from 'node:url'
2
+ import { mergeConfig, defineConfig, configDefaults } from 'vitest/config'
3
+ import viteConfig from './vite.config'
4
+
5
+ export default mergeConfig(
6
+ viteConfig,
7
+ defineConfig({
8
+ test: {
9
+ environment: 'jsdom',
10
+ exclude: [...configDefaults.exclude, 'e2e/**'],
11
+ root: fileURLToPath(new URL('./', import.meta.url)),
12
+ },
13
+ }),
14
+ )