@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.
- package/bin/index.js +2 -0
- package/dist/index.js +1034 -0
- package/package.json +31 -0
- package/template/base/.editorconfig +8 -0
- package/template/base/.gitattributes +1 -0
- package/template/base/.prettierrc.json +7 -0
- package/template/base/.vscode/extensions.json +3 -0
- package/template/base/index.html +14 -0
- package/template/base/package.json +32 -0
- package/template/base/public/favicon.ico +0 -0
- package/template/base/src/App.vue +26 -0
- package/template/base/src/layouts/DefaultLayout.vue +11 -0
- package/template/base/src/main.ts +14 -0
- package/template/base/src/pages/about/index.vue +43 -0
- package/template/base/src/pages/home/index.vue +38 -0
- package/template/base/src/stores/counter.ts +12 -0
- package/template/base/types/env.d.ts.ejs +12 -0
- package/template/base/unocss.config.ts +21 -0
- package/template/base/vite.config.ts.ejs +42 -0
- package/template/eslint/eslint.config.ts +8 -0
- package/template/eslint/package.json +12 -0
- package/template/git-hooks/package.json +17 -0
- package/template/git-hooks/scripts/verify-commit.js +29 -0
- package/template/router/default/package.json +6 -0
- package/template/router/default/src/router/index.ts +19 -0
- package/template/router/unplugin/package.json +9 -0
- package/template/router/unplugin/src/router/index.ts +13 -0
- package/template/tsconfig/tsconfig.app.json +20 -0
- package/template/tsconfig/tsconfig.node.json +19 -0
- package/template/vitest/.vscode/extensions.json +3 -0
- package/template/vitest/package.json +14 -0
- package/template/vitest/src/components/__tests__/HelloWorld.spec.js +11 -0
- package/template/vitest/tsconfig.vitest.json +11 -0
- 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 @@
|
|
|
1
|
+
* text=auto eol=lf
|
|
@@ -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,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,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,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,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,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,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
|
+
)
|