create-banana 1.0.0
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/.github/workflows/publish.yml +37 -0
- package/.husky/pre-commit +4 -0
- package/.prettierignore +3 -0
- package/.prettierrc +7 -0
- package/LICENSE +21 -0
- package/bin/index.js +30 -0
- package/eslint.config.mjs +27 -0
- package/package.json +50 -0
- package/readme.md +1 -0
- package/template/Eslint/.eslintignore +36 -0
- package/template/Eslint/eslintConfig/eslint.config.js.ejs +39 -0
- package/template/Eslint/eslintConfig/index.js +19 -0
- package/template/Eslint/package.json +15 -0
- package/template/Prettier/.prettierignore +7 -0
- package/template/Prettier/.prettierrc +14 -0
- package/template/Prettier/package.json +10 -0
- package/template/base/.vscode/extensions.json +3 -0
- package/template/base/README.md +38 -0
- package/template/base/index.html +13 -0
- package/template/base/jsconfig.json +8 -0
- package/template/base/package.json +22 -0
- package/template/base/public/favicon.ico +0 -0
- package/template/base/src/App.vue +47 -0
- package/template/base/src/assets/base.css +86 -0
- package/template/base/src/assets/logo.svg +1 -0
- package/template/base/src/assets/main.css +35 -0
- package/template/base/src/components/HelloWorld.vue +44 -0
- package/template/base/src/components/TheWelcome.vue +95 -0
- package/template/base/src/components/WelcomeItem.vue +87 -0
- package/template/base/src/components/icons/IconCommunity.vue +7 -0
- package/template/base/src/components/icons/IconDocumentation.vue +7 -0
- package/template/base/src/components/icons/IconEcosystem.vue +7 -0
- package/template/base/src/components/icons/IconSupport.vue +7 -0
- package/template/base/src/components/icons/IconTooling.vue +19 -0
- package/template/base/src/main.js +6 -0
- package/template/base/vite.config.js +15 -0
- package/template/pinia/stores/counter.js +18 -0
- package/utils/URL.js +15 -0
- package/utils/figletPrint.js +20 -0
- package/utils/pathExists.js +37 -0
- package/utils/rainbow.js +26 -0
- package/utils/template/Eslint.js +40 -0
- package/utils/template/base.js +25 -0
- package/utils/template/prettier.js +39 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
name: Publish to npm
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- 'v*'
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
build:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
steps:
|
|
12
|
+
- name: Checkout code
|
|
13
|
+
uses: actions/checkout@v4
|
|
14
|
+
|
|
15
|
+
- name: Install pnpm
|
|
16
|
+
uses: pnpm/action-setup@v3
|
|
17
|
+
with:
|
|
18
|
+
version: 9.12.1 # 或者使用 'latest',建议固定一个主版本
|
|
19
|
+
|
|
20
|
+
- name: Setup Node.js
|
|
21
|
+
uses: actions/setup-node@v4
|
|
22
|
+
with:
|
|
23
|
+
node-version: '20'
|
|
24
|
+
registry-url: 'https://registry.npmjs.org'
|
|
25
|
+
cache: 'pnpm' # 开启缓存,加快后续构建速度
|
|
26
|
+
|
|
27
|
+
- name: Install dependencies
|
|
28
|
+
# 使用 pnpm --frozen-lockfile 代替 npm ci
|
|
29
|
+
run: pnpm install --frozen-lockfile
|
|
30
|
+
|
|
31
|
+
# - name: Build project (if needed)
|
|
32
|
+
# run: pnpm run build --if-present
|
|
33
|
+
|
|
34
|
+
- name: Publish to npm
|
|
35
|
+
run: pnpm publish --no-git-checks
|
|
36
|
+
env:
|
|
37
|
+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
package/.prettierignore
ADDED
package/.prettierrc
ADDED
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 TMname1
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/bin/index.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import printString from '../utils/figletPrint.js'
|
|
3
|
+
import rainbowGradient from '../utils/rainbow.js'
|
|
4
|
+
import { input } from '@inquirer/prompts'
|
|
5
|
+
import createBaseProject from '../utils/template/base.js'
|
|
6
|
+
import { checkbox } from '@inquirer/prompts'
|
|
7
|
+
import addEslint from '../utils/template/eslint.js'
|
|
8
|
+
import addPrettier from '../utils/template/prettier.js'
|
|
9
|
+
import addEslintConfig from '../template/eslint/eslintConfig/index.js'
|
|
10
|
+
|
|
11
|
+
// print BANANA in rainbow colors
|
|
12
|
+
console.log(rainbowGradient(await printString('BANANA')))
|
|
13
|
+
|
|
14
|
+
const projectName = await input({ message: 'Enter your project name:', required: true })
|
|
15
|
+
|
|
16
|
+
const feats = await checkbox({
|
|
17
|
+
message: 'Please select the features to include:',
|
|
18
|
+
choices: [
|
|
19
|
+
{ name: 'Eslint', value: 'eslint' },
|
|
20
|
+
{ name: 'Prettier', value: 'prettier' },
|
|
21
|
+
],
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
const useEslint = feats.includes('eslint')
|
|
25
|
+
const usePrettier = feats.includes('prettier')
|
|
26
|
+
|
|
27
|
+
await createBaseProject(projectName)
|
|
28
|
+
await addEslint(projectName, useEslint)
|
|
29
|
+
await addPrettier(projectName, useEslint, usePrettier)
|
|
30
|
+
await addEslintConfig(projectName, usePrettier, useEslint)
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import js from '@eslint/js'
|
|
2
|
+
import globals from 'globals'
|
|
3
|
+
import json from '@eslint/json'
|
|
4
|
+
import { defineConfig } from 'eslint/config'
|
|
5
|
+
import prettierPlugin from 'eslint-plugin-prettier'
|
|
6
|
+
|
|
7
|
+
export default defineConfig([
|
|
8
|
+
{
|
|
9
|
+
files: ['**/*.{js,mjs,cjs}'],
|
|
10
|
+
plugins: { js, prettier: prettierPlugin },
|
|
11
|
+
extends: ['js/recommended'],
|
|
12
|
+
languageOptions: { globals: globals.node },
|
|
13
|
+
rules: {
|
|
14
|
+
'prettier/prettier': [
|
|
15
|
+
'warn',
|
|
16
|
+
{
|
|
17
|
+
$schema: 'https://json.schemastore.org/prettierrc',
|
|
18
|
+
semi: false,
|
|
19
|
+
singleQuote: true,
|
|
20
|
+
printWidth: 100,
|
|
21
|
+
endOfLine: 'auto',
|
|
22
|
+
},
|
|
23
|
+
],
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
{ files: ['**/*.json'], plugins: { json }, language: 'json/json', extends: ['json/recommended'] },
|
|
27
|
+
])
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "create-banana",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "TMname1's CLI tool to create customized templates",
|
|
6
|
+
"main": "index.js",
|
|
7
|
+
"bin": "./bin/index.js",
|
|
8
|
+
"lint-staged": {
|
|
9
|
+
"*": [
|
|
10
|
+
"eslint . --fix",
|
|
11
|
+
"prettier --write ."
|
|
12
|
+
]
|
|
13
|
+
},
|
|
14
|
+
"keywords": [
|
|
15
|
+
"CLI",
|
|
16
|
+
"template",
|
|
17
|
+
"generator"
|
|
18
|
+
],
|
|
19
|
+
"author": "TMname1",
|
|
20
|
+
"license": "ISC",
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"@inquirer/prompts": "^8.1.0",
|
|
23
|
+
"chalk": "^5.6.2",
|
|
24
|
+
"ejs": "^3.1.10",
|
|
25
|
+
"figlet": "^1.9.4",
|
|
26
|
+
"fs-extra": "^11.3.3"
|
|
27
|
+
},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"@eslint/js": "^9.39.2",
|
|
30
|
+
"@eslint/json": "^0.14.0",
|
|
31
|
+
"cz-conventional-changelog": "^3.3.0",
|
|
32
|
+
"eslint": "^9.39.2",
|
|
33
|
+
"eslint-plugin-prettier": "^5.5.4",
|
|
34
|
+
"globals": "^16.5.0",
|
|
35
|
+
"husky": "^8.0.0",
|
|
36
|
+
"lint-staged": "^16.2.7",
|
|
37
|
+
"prettier": "3.7.4"
|
|
38
|
+
},
|
|
39
|
+
"config": {
|
|
40
|
+
"commitizen": {
|
|
41
|
+
"path": "./node_modules/cz-conventional-changelog"
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
"scripts": {
|
|
45
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
|
46
|
+
"commit": "cz",
|
|
47
|
+
"format": "prettier --write .",
|
|
48
|
+
"lint-staged": "lint-staged"
|
|
49
|
+
}
|
|
50
|
+
}
|
package/readme.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
我的vue脚手架,目前的功能有eslint,prettier
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# 依赖包
|
|
2
|
+
node_modules/
|
|
3
|
+
|
|
4
|
+
# 构建产物 (Build Outputs)
|
|
5
|
+
dist/
|
|
6
|
+
build/
|
|
7
|
+
out/
|
|
8
|
+
.next/
|
|
9
|
+
.nuxt/
|
|
10
|
+
|
|
11
|
+
# 测试覆盖率报告
|
|
12
|
+
coverage/
|
|
13
|
+
|
|
14
|
+
# 静态资源 (通常不检查图片、字体或视频)
|
|
15
|
+
public/
|
|
16
|
+
assets/
|
|
17
|
+
|
|
18
|
+
# 配置文件
|
|
19
|
+
.cache/
|
|
20
|
+
.temp/
|
|
21
|
+
.tmp/
|
|
22
|
+
|
|
23
|
+
# 库文件或压缩后的文件
|
|
24
|
+
*.min.js
|
|
25
|
+
*.bundle.js
|
|
26
|
+
|
|
27
|
+
# 锁文件 (虽然通常是 json/yaml,但最好排除)
|
|
28
|
+
package-lock.json
|
|
29
|
+
yarn.lock
|
|
30
|
+
pnpm-lock.yaml
|
|
31
|
+
|
|
32
|
+
# 本地环境变量文件
|
|
33
|
+
.env*
|
|
34
|
+
|
|
35
|
+
# 流程图或文档生成工具产物
|
|
36
|
+
docs/.vitepress/dist
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import js from '@eslint/js'
|
|
2
|
+
import globals from 'globals'
|
|
3
|
+
import pluginVue from 'eslint-plugin-vue'
|
|
4
|
+
import json from '@eslint/json'
|
|
5
|
+
import markdown from '@eslint/markdown'
|
|
6
|
+
import css from '@eslint/css'
|
|
7
|
+
import { defineConfig } from 'eslint/config'
|
|
8
|
+
<% if(usePrettier) { %>import prettierConfig from "eslint-config-prettier";<% } %>
|
|
9
|
+
|
|
10
|
+
export default defineConfig([
|
|
11
|
+
{
|
|
12
|
+
files: ['**/*.{js,mjs,cjs,vue}'],
|
|
13
|
+
plugins: { js },
|
|
14
|
+
extends: ['js/recommended'],
|
|
15
|
+
languageOptions: { globals: { ...globals.browser, ...globals.node } },
|
|
16
|
+
},
|
|
17
|
+
pluginVue.configs['flat/essential'],
|
|
18
|
+
{ files: ['**/*.json'], plugins: { json }, language: 'json/json', extends: ['json/recommended'] },
|
|
19
|
+
{
|
|
20
|
+
files: ['**/*.jsonc'],
|
|
21
|
+
plugins: { json },
|
|
22
|
+
language: 'json/jsonc',
|
|
23
|
+
extends: ['json/recommended'],
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
files: ['**/*.json5'],
|
|
27
|
+
plugins: { json },
|
|
28
|
+
language: 'json/json5',
|
|
29
|
+
extends: ['json/recommended'],
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
files: ['**/*.md'],
|
|
33
|
+
plugins: { markdown },
|
|
34
|
+
language: 'markdown/gfm',
|
|
35
|
+
extends: ['markdown/recommended'],
|
|
36
|
+
},
|
|
37
|
+
{ files: ['**/*.css'], plugins: { css }, language: 'css/css', extends: ['css/recommended'] },
|
|
38
|
+
<% if(usePrettier) { %>prettierConfig,<% } %>
|
|
39
|
+
])
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// 渲染eslint.config.js文件
|
|
2
|
+
// 通过模板匹配prettier的选择情况
|
|
3
|
+
import ejs from 'ejs'
|
|
4
|
+
import { relativePath } from '../../../utils/URL.js'
|
|
5
|
+
import fs from 'fs-extra'
|
|
6
|
+
import path from 'path'
|
|
7
|
+
|
|
8
|
+
const addEslintConfig = async (projectName, usePrettier, flag) => {
|
|
9
|
+
if (!flag) return
|
|
10
|
+
await fs.writeFile(
|
|
11
|
+
path.join(process.cwd(), projectName, 'eslint.config.js'),
|
|
12
|
+
ejs.render(
|
|
13
|
+
await fs.readFile(relativePath(import.meta.url, './eslint.config.js.ejs'), 'utf-8'),
|
|
14
|
+
{ usePrettier },
|
|
15
|
+
),
|
|
16
|
+
)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export default addEslintConfig
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"scripts": {
|
|
3
|
+
"lint": "eslint .",
|
|
4
|
+
"lint:fix": "eslint . --fix"
|
|
5
|
+
},
|
|
6
|
+
"devDependencies": {
|
|
7
|
+
"@eslint/css": "^0.14.1",
|
|
8
|
+
"@eslint/js": "^9.39.2",
|
|
9
|
+
"@eslint/json": "^0.14.0",
|
|
10
|
+
"@eslint/markdown": "^7.5.1",
|
|
11
|
+
"eslint": "^9.39.2",
|
|
12
|
+
"eslint-plugin-vue": "^10.6.2",
|
|
13
|
+
"globals": "^16.5.0"
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"printWidth": 80,
|
|
3
|
+
"tabWidth": 2,
|
|
4
|
+
"useTabs": false,
|
|
5
|
+
"semi": true,
|
|
6
|
+
"singleQuote": true,
|
|
7
|
+
"quoteProps": "as-needed",
|
|
8
|
+
"jsxSingleQuote": false,
|
|
9
|
+
"trailingComma": "es5",
|
|
10
|
+
"bracketSpacing": true,
|
|
11
|
+
"bracketSameLine": false,
|
|
12
|
+
"arrowParens": "always",
|
|
13
|
+
"endOfLine": "lf"
|
|
14
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# create-tm
|
|
2
|
+
|
|
3
|
+
This template should help get you started developing with Vue 3 in Vite.
|
|
4
|
+
|
|
5
|
+
## Recommended IDE Setup
|
|
6
|
+
|
|
7
|
+
[VS Code](https://code.visualstudio.com/) + [Vue (Official)](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur).
|
|
8
|
+
|
|
9
|
+
## Recommended Browser Setup
|
|
10
|
+
|
|
11
|
+
- Chromium-based browsers (Chrome, Edge, Brave, etc.):
|
|
12
|
+
- [Vue.js devtools](https://chromewebstore.google.com/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd)
|
|
13
|
+
- [Turn on Custom Object Formatter in Chrome DevTools](http://bit.ly/object-formatters)
|
|
14
|
+
- Firefox:
|
|
15
|
+
- [Vue.js devtools](https://addons.mozilla.org/en-US/firefox/addon/vue-js-devtools/)
|
|
16
|
+
- [Turn on Custom Object Formatter in Firefox DevTools](https://fxdx.dev/firefox-devtools-custom-object-formatters/)
|
|
17
|
+
|
|
18
|
+
## Customize configuration
|
|
19
|
+
|
|
20
|
+
See [Vite Configuration Reference](https://vite.dev/config/).
|
|
21
|
+
|
|
22
|
+
## Project Setup
|
|
23
|
+
|
|
24
|
+
```sh
|
|
25
|
+
pnpm install
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### Compile and Hot-Reload for Development
|
|
29
|
+
|
|
30
|
+
```sh
|
|
31
|
+
pnpm dev
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Compile and Minify for Production
|
|
35
|
+
|
|
36
|
+
```sh
|
|
37
|
+
pnpm build
|
|
38
|
+
```
|
|
@@ -0,0 +1,13 @@
|
|
|
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>
|
|
8
|
+
</head>
|
|
9
|
+
<body>
|
|
10
|
+
<div id="app"></div>
|
|
11
|
+
<script type="module" src="/src/main.js"></script>
|
|
12
|
+
</body>
|
|
13
|
+
</html>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "create-tm",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"engines": {
|
|
7
|
+
"node": "^20.19.0 || >=22.12.0"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"dev": "vite",
|
|
11
|
+
"build": "vite build",
|
|
12
|
+
"preview": "vite preview"
|
|
13
|
+
},
|
|
14
|
+
"dependencies": {
|
|
15
|
+
"vue": "^3.5.25"
|
|
16
|
+
},
|
|
17
|
+
"devDependencies": {
|
|
18
|
+
"@vitejs/plugin-vue": "^6.0.2",
|
|
19
|
+
"vite": "^7.2.4",
|
|
20
|
+
"vite-plugin-vue-devtools": "^8.0.5"
|
|
21
|
+
}
|
|
22
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import HelloWorld from './components/HelloWorld.vue'
|
|
3
|
+
import TheWelcome from './components/TheWelcome.vue'
|
|
4
|
+
</script>
|
|
5
|
+
|
|
6
|
+
<template>
|
|
7
|
+
<header>
|
|
8
|
+
<img alt="Vue logo" class="logo" src="./assets/logo.svg" width="125" height="125" />
|
|
9
|
+
|
|
10
|
+
<div class="wrapper">
|
|
11
|
+
<HelloWorld msg="You did it!" />
|
|
12
|
+
</div>
|
|
13
|
+
</header>
|
|
14
|
+
|
|
15
|
+
<main>
|
|
16
|
+
<TheWelcome />
|
|
17
|
+
</main>
|
|
18
|
+
</template>
|
|
19
|
+
|
|
20
|
+
<style scoped>
|
|
21
|
+
header {
|
|
22
|
+
line-height: 1.5;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.logo {
|
|
26
|
+
display: block;
|
|
27
|
+
margin: 0 auto 2rem;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
@media (min-width: 1024px) {
|
|
31
|
+
header {
|
|
32
|
+
display: flex;
|
|
33
|
+
place-items: center;
|
|
34
|
+
padding-right: calc(var(--section-gap) / 2);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.logo {
|
|
38
|
+
margin: 0 2rem 0 0;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
header .wrapper {
|
|
42
|
+
display: flex;
|
|
43
|
+
place-items: flex-start;
|
|
44
|
+
flex-wrap: wrap;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
</style>
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/* color palette from <https://github.com/vuejs/theme> */
|
|
2
|
+
:root {
|
|
3
|
+
--vt-c-white: #ffffff;
|
|
4
|
+
--vt-c-white-soft: #f8f8f8;
|
|
5
|
+
--vt-c-white-mute: #f2f2f2;
|
|
6
|
+
|
|
7
|
+
--vt-c-black: #181818;
|
|
8
|
+
--vt-c-black-soft: #222222;
|
|
9
|
+
--vt-c-black-mute: #282828;
|
|
10
|
+
|
|
11
|
+
--vt-c-indigo: #2c3e50;
|
|
12
|
+
|
|
13
|
+
--vt-c-divider-light-1: rgba(60, 60, 60, 0.29);
|
|
14
|
+
--vt-c-divider-light-2: rgba(60, 60, 60, 0.12);
|
|
15
|
+
--vt-c-divider-dark-1: rgba(84, 84, 84, 0.65);
|
|
16
|
+
--vt-c-divider-dark-2: rgba(84, 84, 84, 0.48);
|
|
17
|
+
|
|
18
|
+
--vt-c-text-light-1: var(--vt-c-indigo);
|
|
19
|
+
--vt-c-text-light-2: rgba(60, 60, 60, 0.66);
|
|
20
|
+
--vt-c-text-dark-1: var(--vt-c-white);
|
|
21
|
+
--vt-c-text-dark-2: rgba(235, 235, 235, 0.64);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/* semantic color variables for this project */
|
|
25
|
+
:root {
|
|
26
|
+
--color-background: var(--vt-c-white);
|
|
27
|
+
--color-background-soft: var(--vt-c-white-soft);
|
|
28
|
+
--color-background-mute: var(--vt-c-white-mute);
|
|
29
|
+
|
|
30
|
+
--color-border: var(--vt-c-divider-light-2);
|
|
31
|
+
--color-border-hover: var(--vt-c-divider-light-1);
|
|
32
|
+
|
|
33
|
+
--color-heading: var(--vt-c-text-light-1);
|
|
34
|
+
--color-text: var(--vt-c-text-light-1);
|
|
35
|
+
|
|
36
|
+
--section-gap: 160px;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
@media (prefers-color-scheme: dark) {
|
|
40
|
+
:root {
|
|
41
|
+
--color-background: var(--vt-c-black);
|
|
42
|
+
--color-background-soft: var(--vt-c-black-soft);
|
|
43
|
+
--color-background-mute: var(--vt-c-black-mute);
|
|
44
|
+
|
|
45
|
+
--color-border: var(--vt-c-divider-dark-2);
|
|
46
|
+
--color-border-hover: var(--vt-c-divider-dark-1);
|
|
47
|
+
|
|
48
|
+
--color-heading: var(--vt-c-text-dark-1);
|
|
49
|
+
--color-text: var(--vt-c-text-dark-2);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
*,
|
|
54
|
+
*::before,
|
|
55
|
+
*::after {
|
|
56
|
+
box-sizing: border-box;
|
|
57
|
+
margin: 0;
|
|
58
|
+
font-weight: normal;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
body {
|
|
62
|
+
min-height: 100vh;
|
|
63
|
+
color: var(--color-text);
|
|
64
|
+
background: var(--color-background);
|
|
65
|
+
transition:
|
|
66
|
+
color 0.5s,
|
|
67
|
+
background-color 0.5s;
|
|
68
|
+
line-height: 1.6;
|
|
69
|
+
font-family:
|
|
70
|
+
Inter,
|
|
71
|
+
-apple-system,
|
|
72
|
+
BlinkMacSystemFont,
|
|
73
|
+
'Segoe UI',
|
|
74
|
+
Roboto,
|
|
75
|
+
Oxygen,
|
|
76
|
+
Ubuntu,
|
|
77
|
+
Cantarell,
|
|
78
|
+
'Fira Sans',
|
|
79
|
+
'Droid Sans',
|
|
80
|
+
'Helvetica Neue',
|
|
81
|
+
sans-serif;
|
|
82
|
+
font-size: 15px;
|
|
83
|
+
text-rendering: optimizeLegibility;
|
|
84
|
+
-webkit-font-smoothing: antialiased;
|
|
85
|
+
-moz-osx-font-smoothing: grayscale;
|
|
86
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 261.76 226.69"><path d="M161.096.001l-30.225 52.351L100.647.001H-.005l130.877 226.688L261.749.001z" fill="#41b883"/><path d="M161.096.001l-30.225 52.351L100.647.001H52.346l78.526 136.01L209.398.001z" fill="#34495e"/></svg>
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
@import './base.css';
|
|
2
|
+
|
|
3
|
+
#app {
|
|
4
|
+
max-width: 1280px;
|
|
5
|
+
margin: 0 auto;
|
|
6
|
+
padding: 2rem;
|
|
7
|
+
font-weight: normal;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
a,
|
|
11
|
+
.green {
|
|
12
|
+
text-decoration: none;
|
|
13
|
+
color: hsla(160, 100%, 37%, 1);
|
|
14
|
+
transition: 0.4s;
|
|
15
|
+
padding: 3px;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
@media (hover: hover) {
|
|
19
|
+
a:hover {
|
|
20
|
+
background-color: hsla(160, 100%, 37%, 0.2);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
@media (min-width: 1024px) {
|
|
25
|
+
body {
|
|
26
|
+
display: flex;
|
|
27
|
+
place-items: center;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
#app {
|
|
31
|
+
display: grid;
|
|
32
|
+
grid-template-columns: 1fr 1fr;
|
|
33
|
+
padding: 0 2rem;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
defineProps({
|
|
3
|
+
msg: {
|
|
4
|
+
type: String,
|
|
5
|
+
required: true,
|
|
6
|
+
},
|
|
7
|
+
})
|
|
8
|
+
</script>
|
|
9
|
+
|
|
10
|
+
<template>
|
|
11
|
+
<div class="greetings">
|
|
12
|
+
<h1 class="green">{{ msg }}</h1>
|
|
13
|
+
<h3>
|
|
14
|
+
You’ve successfully created a project with
|
|
15
|
+
<a href="https://vite.dev/" target="_blank" rel="noopener">Vite</a> +
|
|
16
|
+
<a href="https://vuejs.org/" target="_blank" rel="noopener">Vue 3</a>.
|
|
17
|
+
</h3>
|
|
18
|
+
</div>
|
|
19
|
+
</template>
|
|
20
|
+
|
|
21
|
+
<style scoped>
|
|
22
|
+
h1 {
|
|
23
|
+
font-weight: 500;
|
|
24
|
+
font-size: 2.6rem;
|
|
25
|
+
position: relative;
|
|
26
|
+
top: -10px;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
h3 {
|
|
30
|
+
font-size: 1.2rem;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.greetings h1,
|
|
34
|
+
.greetings h3 {
|
|
35
|
+
text-align: center;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
@media (min-width: 1024px) {
|
|
39
|
+
.greetings h1,
|
|
40
|
+
.greetings h3 {
|
|
41
|
+
text-align: left;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
</style>
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import WelcomeItem from './WelcomeItem.vue'
|
|
3
|
+
import DocumentationIcon from './icons/IconDocumentation.vue'
|
|
4
|
+
import ToolingIcon from './icons/IconTooling.vue'
|
|
5
|
+
import EcosystemIcon from './icons/IconEcosystem.vue'
|
|
6
|
+
import CommunityIcon from './icons/IconCommunity.vue'
|
|
7
|
+
import SupportIcon from './icons/IconSupport.vue'
|
|
8
|
+
|
|
9
|
+
const openReadmeInEditor = () => fetch('/__open-in-editor?file=README.md')
|
|
10
|
+
</script>
|
|
11
|
+
|
|
12
|
+
<template>
|
|
13
|
+
<WelcomeItem>
|
|
14
|
+
<template #icon>
|
|
15
|
+
<DocumentationIcon />
|
|
16
|
+
</template>
|
|
17
|
+
<template #heading>Documentation</template>
|
|
18
|
+
|
|
19
|
+
Vue’s
|
|
20
|
+
<a href="https://vuejs.org/" target="_blank" rel="noopener">official documentation</a>
|
|
21
|
+
provides you with all information you need to get started.
|
|
22
|
+
</WelcomeItem>
|
|
23
|
+
|
|
24
|
+
<WelcomeItem>
|
|
25
|
+
<template #icon>
|
|
26
|
+
<ToolingIcon />
|
|
27
|
+
</template>
|
|
28
|
+
<template #heading>Tooling</template>
|
|
29
|
+
|
|
30
|
+
This project is served and bundled with
|
|
31
|
+
<a href="https://vite.dev/guide/features.html" target="_blank" rel="noopener">Vite</a>. The
|
|
32
|
+
recommended IDE setup is
|
|
33
|
+
<a href="https://code.visualstudio.com/" target="_blank" rel="noopener">VSCode</a>
|
|
34
|
+
+
|
|
35
|
+
<a href="https://github.com/vuejs/language-tools" target="_blank" rel="noopener"
|
|
36
|
+
>Vue - Official</a
|
|
37
|
+
>. If you need to test your components and web pages, check out
|
|
38
|
+
<a href="https://vitest.dev/" target="_blank" rel="noopener">Vitest</a>
|
|
39
|
+
and
|
|
40
|
+
<a href="https://www.cypress.io/" target="_blank" rel="noopener">Cypress</a>
|
|
41
|
+
/
|
|
42
|
+
<a href="https://playwright.dev/" target="_blank" rel="noopener">Playwright</a>.
|
|
43
|
+
|
|
44
|
+
<br />
|
|
45
|
+
|
|
46
|
+
More instructions are available in
|
|
47
|
+
<a href="javascript:void(0)" @click="openReadmeInEditor"><code>README.md</code></a
|
|
48
|
+
>.
|
|
49
|
+
</WelcomeItem>
|
|
50
|
+
|
|
51
|
+
<WelcomeItem>
|
|
52
|
+
<template #icon>
|
|
53
|
+
<EcosystemIcon />
|
|
54
|
+
</template>
|
|
55
|
+
<template #heading>Ecosystem</template>
|
|
56
|
+
|
|
57
|
+
Get official tools and libraries for your project:
|
|
58
|
+
<a href="https://pinia.vuejs.org/" target="_blank" rel="noopener">Pinia</a>,
|
|
59
|
+
<a href="https://router.vuejs.org/" target="_blank" rel="noopener">Vue Router</a>,
|
|
60
|
+
<a href="https://test-utils.vuejs.org/" target="_blank" rel="noopener">Vue Test Utils</a>, and
|
|
61
|
+
<a href="https://github.com/vuejs/devtools" target="_blank" rel="noopener">Vue Dev Tools</a>. If
|
|
62
|
+
you need more resources, we suggest paying
|
|
63
|
+
<a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">Awesome Vue</a>
|
|
64
|
+
a visit.
|
|
65
|
+
</WelcomeItem>
|
|
66
|
+
|
|
67
|
+
<WelcomeItem>
|
|
68
|
+
<template #icon>
|
|
69
|
+
<CommunityIcon />
|
|
70
|
+
</template>
|
|
71
|
+
<template #heading>Community</template>
|
|
72
|
+
|
|
73
|
+
Got stuck? Ask your question on
|
|
74
|
+
<a href="https://chat.vuejs.org" target="_blank" rel="noopener">Vue Land</a>
|
|
75
|
+
(our official Discord server), or
|
|
76
|
+
<a href="https://stackoverflow.com/questions/tagged/vue.js" target="_blank" rel="noopener"
|
|
77
|
+
>StackOverflow</a
|
|
78
|
+
>. You should also follow the official
|
|
79
|
+
<a href="https://bsky.app/profile/vuejs.org" target="_blank" rel="noopener">@vuejs.org</a>
|
|
80
|
+
Bluesky account or the
|
|
81
|
+
<a href="https://x.com/vuejs" target="_blank" rel="noopener">@vuejs</a>
|
|
82
|
+
X account for latest news in the Vue world.
|
|
83
|
+
</WelcomeItem>
|
|
84
|
+
|
|
85
|
+
<WelcomeItem>
|
|
86
|
+
<template #icon>
|
|
87
|
+
<SupportIcon />
|
|
88
|
+
</template>
|
|
89
|
+
<template #heading>Support Vue</template>
|
|
90
|
+
|
|
91
|
+
As an independent project, Vue relies on community backing for its sustainability. You can help
|
|
92
|
+
us by
|
|
93
|
+
<a href="https://vuejs.org/sponsor/" target="_blank" rel="noopener">becoming a sponsor</a>.
|
|
94
|
+
</WelcomeItem>
|
|
95
|
+
</template>
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="item">
|
|
3
|
+
<i>
|
|
4
|
+
<slot name="icon"></slot>
|
|
5
|
+
</i>
|
|
6
|
+
<div class="details">
|
|
7
|
+
<h3>
|
|
8
|
+
<slot name="heading"></slot>
|
|
9
|
+
</h3>
|
|
10
|
+
<slot></slot>
|
|
11
|
+
</div>
|
|
12
|
+
</div>
|
|
13
|
+
</template>
|
|
14
|
+
|
|
15
|
+
<style scoped>
|
|
16
|
+
.item {
|
|
17
|
+
margin-top: 2rem;
|
|
18
|
+
display: flex;
|
|
19
|
+
position: relative;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.details {
|
|
23
|
+
flex: 1;
|
|
24
|
+
margin-left: 1rem;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
i {
|
|
28
|
+
display: flex;
|
|
29
|
+
place-items: center;
|
|
30
|
+
place-content: center;
|
|
31
|
+
width: 32px;
|
|
32
|
+
height: 32px;
|
|
33
|
+
|
|
34
|
+
color: var(--color-text);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
h3 {
|
|
38
|
+
font-size: 1.2rem;
|
|
39
|
+
font-weight: 500;
|
|
40
|
+
margin-bottom: 0.4rem;
|
|
41
|
+
color: var(--color-heading);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
@media (min-width: 1024px) {
|
|
45
|
+
.item {
|
|
46
|
+
margin-top: 0;
|
|
47
|
+
padding: 0.4rem 0 1rem calc(var(--section-gap) / 2);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
i {
|
|
51
|
+
top: calc(50% - 25px);
|
|
52
|
+
left: -26px;
|
|
53
|
+
position: absolute;
|
|
54
|
+
border: 1px solid var(--color-border);
|
|
55
|
+
background: var(--color-background);
|
|
56
|
+
border-radius: 8px;
|
|
57
|
+
width: 50px;
|
|
58
|
+
height: 50px;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.item:before {
|
|
62
|
+
content: ' ';
|
|
63
|
+
border-left: 1px solid var(--color-border);
|
|
64
|
+
position: absolute;
|
|
65
|
+
left: 0;
|
|
66
|
+
bottom: calc(50% + 25px);
|
|
67
|
+
height: calc(50% - 25px);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.item:after {
|
|
71
|
+
content: ' ';
|
|
72
|
+
border-left: 1px solid var(--color-border);
|
|
73
|
+
position: absolute;
|
|
74
|
+
left: 0;
|
|
75
|
+
top: calc(50% + 25px);
|
|
76
|
+
height: calc(50% - 25px);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.item:first-of-type:before {
|
|
80
|
+
display: none;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.item:last-of-type:after {
|
|
84
|
+
display: none;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
</style>
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor">
|
|
3
|
+
<path
|
|
4
|
+
d="M15 4a1 1 0 1 0 0 2V4zm0 11v-1a1 1 0 0 0-1 1h1zm0 4l-.707.707A1 1 0 0 0 16 19h-1zm-4-4l.707-.707A1 1 0 0 0 11 14v1zm-4.707-1.293a1 1 0 0 0-1.414 1.414l1.414-1.414zm-.707.707l-.707-.707.707.707zM9 11v-1a1 1 0 0 0-.707.293L9 11zm-4 0h1a1 1 0 0 0-1-1v1zm0 4H4a1 1 0 0 0 1.707.707L5 15zm10-9h2V4h-2v2zm2 0a1 1 0 0 1 1 1h2a3 3 0 0 0-3-3v2zm1 1v6h2V7h-2zm0 6a1 1 0 0 1-1 1v2a3 3 0 0 0 3-3h-2zm-1 1h-2v2h2v-2zm-3 1v4h2v-4h-2zm1.707 3.293l-4-4-1.414 1.414 4 4 1.414-1.414zM11 14H7v2h4v-2zm-4 0c-.276 0-.525-.111-.707-.293l-1.414 1.414C5.42 15.663 6.172 16 7 16v-2zm-.707 1.121l3.414-3.414-1.414-1.414-3.414 3.414 1.414 1.414zM9 12h4v-2H9v2zm4 0a3 3 0 0 0 3-3h-2a1 1 0 0 1-1 1v2zm3-3V3h-2v6h2zm0-6a3 3 0 0 0-3-3v2a1 1 0 0 1 1 1h2zm-3-3H3v2h10V0zM3 0a3 3 0 0 0-3 3h2a1 1 0 0 1 1-1V0zM0 3v6h2V3H0zm0 6a3 3 0 0 0 3 3v-2a1 1 0 0 1-1-1H0zm3 3h2v-2H3v2zm1-1v4h2v-4H4zm1.707 4.707l.586-.586-1.414-1.414-.586.586 1.414 1.414z"
|
|
5
|
+
/>
|
|
6
|
+
</svg>
|
|
7
|
+
</template>
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="17" fill="currentColor">
|
|
3
|
+
<path
|
|
4
|
+
d="M11 2.253a1 1 0 1 0-2 0h2zm-2 13a1 1 0 1 0 2 0H9zm.447-12.167a1 1 0 1 0 1.107-1.666L9.447 3.086zM1 2.253L.447 1.42A1 1 0 0 0 0 2.253h1zm0 13H0a1 1 0 0 0 1.553.833L1 15.253zm8.447.833a1 1 0 1 0 1.107-1.666l-1.107 1.666zm0-14.666a1 1 0 1 0 1.107 1.666L9.447 1.42zM19 2.253h1a1 1 0 0 0-.447-.833L19 2.253zm0 13l-.553.833A1 1 0 0 0 20 15.253h-1zm-9.553-.833a1 1 0 1 0 1.107 1.666L9.447 14.42zM9 2.253v13h2v-13H9zm1.553-.833C9.203.523 7.42 0 5.5 0v2c1.572 0 2.961.431 3.947 1.086l1.107-1.666zM5.5 0C3.58 0 1.797.523.447 1.42l1.107 1.666C2.539 2.431 3.928 2 5.5 2V0zM0 2.253v13h2v-13H0zm1.553 13.833C2.539 15.431 3.928 15 5.5 15v-2c-1.92 0-3.703.523-5.053 1.42l1.107 1.666zM5.5 15c1.572 0 2.961.431 3.947 1.086l1.107-1.666C9.203 13.523 7.42 13 5.5 13v2zm5.053-11.914C11.539 2.431 12.928 2 14.5 2V0c-1.92 0-3.703.523-5.053 1.42l1.107 1.666zM14.5 2c1.573 0 2.961.431 3.947 1.086l1.107-1.666C18.203.523 16.421 0 14.5 0v2zm3.5.253v13h2v-13h-2zm1.553 12.167C18.203 13.523 16.421 13 14.5 13v2c1.573 0 2.961.431 3.947 1.086l1.107-1.666zM14.5 13c-1.92 0-3.703.523-5.053 1.42l1.107 1.666C11.539 15.431 12.928 15 14.5 15v-2z"
|
|
5
|
+
/>
|
|
6
|
+
</svg>
|
|
7
|
+
</template>
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="20" fill="currentColor">
|
|
3
|
+
<path
|
|
4
|
+
d="M11.447 8.894a1 1 0 1 0-.894-1.789l.894 1.789zm-2.894-.789a1 1 0 1 0 .894 1.789l-.894-1.789zm0 1.789a1 1 0 1 0 .894-1.789l-.894 1.789zM7.447 7.106a1 1 0 1 0-.894 1.789l.894-1.789zM10 9a1 1 0 1 0-2 0h2zm-2 2.5a1 1 0 1 0 2 0H8zm9.447-5.606a1 1 0 1 0-.894-1.789l.894 1.789zm-2.894-.789a1 1 0 1 0 .894 1.789l-.894-1.789zm2 .789a1 1 0 1 0 .894-1.789l-.894 1.789zm-1.106-2.789a1 1 0 1 0-.894 1.789l.894-1.789zM18 5a1 1 0 1 0-2 0h2zm-2 2.5a1 1 0 1 0 2 0h-2zm-5.447-4.606a1 1 0 1 0 .894-1.789l-.894 1.789zM9 1l.447-.894a1 1 0 0 0-.894 0L9 1zm-2.447.106a1 1 0 1 0 .894 1.789l-.894-1.789zm-6 3a1 1 0 1 0 .894 1.789L.553 4.106zm2.894.789a1 1 0 1 0-.894-1.789l.894 1.789zm-2-.789a1 1 0 1 0-.894 1.789l.894-1.789zm1.106 2.789a1 1 0 1 0 .894-1.789l-.894 1.789zM2 5a1 1 0 1 0-2 0h2zM0 7.5a1 1 0 1 0 2 0H0zm8.553 12.394a1 1 0 1 0 .894-1.789l-.894 1.789zm-1.106-2.789a1 1 0 1 0-.894 1.789l.894-1.789zm1.106 1a1 1 0 1 0 .894 1.789l-.894-1.789zm2.894.789a1 1 0 1 0-.894-1.789l.894 1.789zM8 19a1 1 0 1 0 2 0H8zm2-2.5a1 1 0 1 0-2 0h2zm-7.447.394a1 1 0 1 0 .894-1.789l-.894 1.789zM1 15H0a1 1 0 0 0 .553.894L1 15zm1-2.5a1 1 0 1 0-2 0h2zm12.553 2.606a1 1 0 1 0 .894 1.789l-.894-1.789zM17 15l.447.894A1 1 0 0 0 18 15h-1zm1-2.5a1 1 0 1 0-2 0h2zm-7.447-5.394l-2 1 .894 1.789 2-1-.894-1.789zm-1.106 1l-2-1-.894 1.789 2 1 .894-1.789zM8 9v2.5h2V9H8zm8.553-4.894l-2 1 .894 1.789 2-1-.894-1.789zm.894 0l-2-1-.894 1.789 2 1 .894-1.789zM16 5v2.5h2V5h-2zm-4.553-3.894l-2-1-.894 1.789 2 1 .894-1.789zm-2.894-1l-2 1 .894 1.789 2-1L8.553.106zM1.447 5.894l2-1-.894-1.789-2 1 .894 1.789zm-.894 0l2 1 .894-1.789-2-1-.894 1.789zM0 5v2.5h2V5H0zm9.447 13.106l-2-1-.894 1.789 2 1 .894-1.789zm0 1.789l2-1-.894-1.789-2 1 .894 1.789zM10 19v-2.5H8V19h2zm-6.553-3.894l-2-1-.894 1.789 2 1 .894-1.789zM2 15v-2.5H0V15h2zm13.447 1.894l2-1-.894-1.789-2 1 .894 1.789zM18 15v-2.5h-2V15h2z"
|
|
5
|
+
/>
|
|
6
|
+
</svg>
|
|
7
|
+
</template>
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor">
|
|
3
|
+
<path
|
|
4
|
+
d="M10 3.22l-.61-.6a5.5 5.5 0 0 0-7.666.105 5.5 5.5 0 0 0-.114 7.665L10 18.78l8.39-8.4a5.5 5.5 0 0 0-.114-7.665 5.5 5.5 0 0 0-7.666-.105l-.61.61z"
|
|
5
|
+
/>
|
|
6
|
+
</svg>
|
|
7
|
+
</template>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<!-- This icon is from <https://github.com/Templarian/MaterialDesign>, distributed under Apache 2.0 (https://www.apache.org/licenses/LICENSE-2.0) license-->
|
|
2
|
+
<template>
|
|
3
|
+
<svg
|
|
4
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
5
|
+
xmlns:xlink="http://www.w3.org/1999/xlink"
|
|
6
|
+
aria-hidden="true"
|
|
7
|
+
role="img"
|
|
8
|
+
class="iconify iconify--mdi"
|
|
9
|
+
width="24"
|
|
10
|
+
height="24"
|
|
11
|
+
preserveAspectRatio="xMidYMid meet"
|
|
12
|
+
viewBox="0 0 24 24"
|
|
13
|
+
>
|
|
14
|
+
<path
|
|
15
|
+
d="M20 18v-4h-3v1h-2v-1H9v1H7v-1H4v4h16M6.33 8l-1.74 4H7v-1h2v1h6v-1h2v1h2.41l-1.74-4H6.33M9 5v1h6V5H9m12.84 7.61c.1.22.16.48.16.8V18c0 .53-.21 1-.6 1.41c-.4.4-.85.59-1.4.59H4c-.55 0-1-.19-1.4-.59C2.21 19 2 18.53 2 18v-4.59c0-.32.06-.58.16-.8L4.5 7.22C4.84 6.41 5.45 6 6.33 6H7V5c0-.55.18-1 .57-1.41C7.96 3.2 8.44 3 9 3h6c.56 0 1.04.2 1.43.59c.39.41.57.86.57 1.41v1h.67c.88 0 1.49.41 1.83 1.22l2.34 5.39z"
|
|
16
|
+
fill="currentColor"
|
|
17
|
+
></path>
|
|
18
|
+
</svg>
|
|
19
|
+
</template>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { fileURLToPath, URL } from 'node:url'
|
|
2
|
+
|
|
3
|
+
import { defineConfig } from 'vite'
|
|
4
|
+
import vue from '@vitejs/plugin-vue'
|
|
5
|
+
import vueDevTools from 'vite-plugin-vue-devtools'
|
|
6
|
+
|
|
7
|
+
// https://vite.dev/config/
|
|
8
|
+
export default defineConfig({
|
|
9
|
+
plugins: [vue(), vueDevTools()],
|
|
10
|
+
resolve: {
|
|
11
|
+
alias: {
|
|
12
|
+
'@': fileURLToPath(new URL('./src', import.meta.url)),
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
})
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { ref, computed } from 'vue'
|
|
2
|
+
import { defineStore } from 'pinia'
|
|
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
|
+
})
|
|
13
|
+
|
|
14
|
+
// TODO: 添加pinia 的模板
|
|
15
|
+
|
|
16
|
+
// TODO: main.js要用ejs来调整
|
|
17
|
+
|
|
18
|
+
// TODO: 添加是否选择pinia持久化的功能
|
package/utils/URL.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// 获得相对路径和模板目录路径的工具函数
|
|
2
|
+
import path from 'path'
|
|
3
|
+
import { fileURLToPath } from 'url'
|
|
4
|
+
|
|
5
|
+
// 拼接相对路径
|
|
6
|
+
const relativePath = (fileURL, targetURL) => {
|
|
7
|
+
const __filename = fileURLToPath(fileURL)
|
|
8
|
+
const __dirname = path.dirname(__filename)
|
|
9
|
+
return path.join(__dirname, targetURL)
|
|
10
|
+
}
|
|
11
|
+
export { relativePath }
|
|
12
|
+
|
|
13
|
+
// 获取模板目录路径
|
|
14
|
+
const templatePath = fileURLToPath(new URL('../template', import.meta.url))
|
|
15
|
+
export { templatePath }
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// print BANANA in big money-se font using figlet
|
|
2
|
+
|
|
3
|
+
import figlet from 'figlet'
|
|
4
|
+
|
|
5
|
+
const printString = async (str) => {
|
|
6
|
+
try {
|
|
7
|
+
return await figlet.text(str, {
|
|
8
|
+
font: 'Big Money-se',
|
|
9
|
+
horizontalLayout: 'default',
|
|
10
|
+
verticalLayout: 'default',
|
|
11
|
+
width: 80,
|
|
12
|
+
whitespaceBreak: true,
|
|
13
|
+
})
|
|
14
|
+
} catch (err) {
|
|
15
|
+
console.log('Something went wrong...')
|
|
16
|
+
console.dir(err)
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export default printString
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// 确认路径是否存在,若存在则提示是否覆盖
|
|
2
|
+
// 若选择覆盖则删除已存在的文件夹,并新建一个文件夹
|
|
3
|
+
// 若选择不覆盖则退出程序
|
|
4
|
+
import fs from 'fs-extra'
|
|
5
|
+
import { select } from '@inquirer/prompts'
|
|
6
|
+
|
|
7
|
+
const confirmPathExists = async (projectName, projectDir) => {
|
|
8
|
+
try {
|
|
9
|
+
// 判断文件夹是否存在
|
|
10
|
+
if (await fs.pathExists(projectDir)) {
|
|
11
|
+
// 如果存在就提示是否要覆盖
|
|
12
|
+
const isOverwrite = await select({
|
|
13
|
+
message: `The target folder "${projectName}" is not empty. Overwrite?`,
|
|
14
|
+
choices: [
|
|
15
|
+
{ name: 'Yes', value: true },
|
|
16
|
+
{ name: 'No', value: false },
|
|
17
|
+
],
|
|
18
|
+
})
|
|
19
|
+
if (!isOverwrite) {
|
|
20
|
+
// TODO: 放一个更友好的提示
|
|
21
|
+
// 例如:X操作取消(换英文)
|
|
22
|
+
console.log('canceled!')
|
|
23
|
+
// 退出程序
|
|
24
|
+
process.exit(0)
|
|
25
|
+
} else {
|
|
26
|
+
// 删除已存在的文件夹并新建一个文件夹
|
|
27
|
+
await fs.remove(projectDir)
|
|
28
|
+
await fs.mkdir(projectDir)
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
} catch (err) {
|
|
32
|
+
// TODO: 放一个更友好的提示
|
|
33
|
+
console.error(err)
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export default confirmPathExists
|
package/utils/rainbow.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// use chalk to print text in rainbow colors
|
|
2
|
+
import chalk from 'chalk'
|
|
3
|
+
|
|
4
|
+
function hslToRgb(h, s, l) {
|
|
5
|
+
s /= 100
|
|
6
|
+
l /= 100
|
|
7
|
+
|
|
8
|
+
const k = (n) => (n + h / 30) % 12
|
|
9
|
+
const a = s * Math.min(l, 1 - l)
|
|
10
|
+
const f = (n) => l - a * Math.max(-1, Math.min(k(n) - 3, Math.min(9 - k(n), 1)))
|
|
11
|
+
|
|
12
|
+
return [Math.round(255 * f(0)), Math.round(255 * f(8)), Math.round(255 * f(4))]
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function rainbowGradient(text) {
|
|
16
|
+
return text
|
|
17
|
+
.split('')
|
|
18
|
+
.map((char, i) => {
|
|
19
|
+
const hue = (i / text.length) * 360
|
|
20
|
+
const [r, g, b] = hslToRgb(hue, 100, 50)
|
|
21
|
+
return chalk.rgb(r, g, b)(char)
|
|
22
|
+
})
|
|
23
|
+
.join('')
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export default rainbowGradient
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// 添加Eslint功能
|
|
2
|
+
import path from 'path'
|
|
3
|
+
import fs from 'fs-extra'
|
|
4
|
+
import { templatePath } from '../URL.js'
|
|
5
|
+
|
|
6
|
+
// TODO: 优化变量名长度,提高可读性
|
|
7
|
+
// TODO: 文件的变量名不要path
|
|
8
|
+
const addEslint = async (projectName, flag) => {
|
|
9
|
+
// 没有选择Eslint则直接返回
|
|
10
|
+
if (!flag) return
|
|
11
|
+
// 路径
|
|
12
|
+
const templateEslintPath = path.join(templatePath, 'eslint')
|
|
13
|
+
const targetPath = path.join(process.cwd(), projectName)
|
|
14
|
+
const targetPackageJsonPath = path.join(targetPath, 'package.json')
|
|
15
|
+
|
|
16
|
+
// 文件
|
|
17
|
+
// 读取package.json文件
|
|
18
|
+
const targetPkg = await fs.readJson(targetPackageJsonPath)
|
|
19
|
+
// 读取添加Eslint附加的package.json文件
|
|
20
|
+
const eslintPkg = await fs.readJson(path.join(templateEslintPath, 'package.json'))
|
|
21
|
+
|
|
22
|
+
targetPkg.devDependencies = {
|
|
23
|
+
...targetPkg.devDependencies,
|
|
24
|
+
...eslintPkg.devDependencies,
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
targetPkg.scripts = {
|
|
28
|
+
...targetPkg.scripts,
|
|
29
|
+
...eslintPkg.scripts,
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
await fs.writeJson(targetPackageJsonPath, targetPkg, { spaces: 2 })
|
|
33
|
+
|
|
34
|
+
// 复制.eslintignore文件
|
|
35
|
+
const eslintIgnorePath = path.join(templateEslintPath, '.eslintignore')
|
|
36
|
+
const eslintIgnoreTargetPath = path.join(targetPath, '.eslintignore')
|
|
37
|
+
fs.copy(eslintIgnorePath, eslintIgnoreTargetPath)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export default addEslint
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// 获取base模板
|
|
2
|
+
import path from 'path'
|
|
3
|
+
import { templatePath } from '../URL.js'
|
|
4
|
+
import fs from 'fs-extra'
|
|
5
|
+
import confirmPathExists from '../pathExists.js'
|
|
6
|
+
|
|
7
|
+
const basePath = path.join(templatePath, 'base')
|
|
8
|
+
|
|
9
|
+
const createBaseProject = async (projectName) => {
|
|
10
|
+
const projectDir = path.join(process.cwd(), projectName)
|
|
11
|
+
// 确认路径存在
|
|
12
|
+
await confirmPathExists(projectName, projectDir)
|
|
13
|
+
// 复制模板文件到目标目录
|
|
14
|
+
fs.copySync(basePath, projectDir)
|
|
15
|
+
// 读取package.json文件路径
|
|
16
|
+
const packageJsonPath = path.join(projectDir, 'package.json')
|
|
17
|
+
// 读取package.json内容
|
|
18
|
+
const packageJson = await fs.readJson(packageJsonPath)
|
|
19
|
+
// 修改name字段
|
|
20
|
+
packageJson.name = projectName
|
|
21
|
+
// 写回package.json文件
|
|
22
|
+
await fs.writeJson(packageJsonPath, packageJson, { spaces: 2 })
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export default createBaseProject
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { templatePath } from '../URL.js'
|
|
2
|
+
import path from 'path'
|
|
3
|
+
import fs from 'fs-extra'
|
|
4
|
+
|
|
5
|
+
const addPrettier = async (projectName, useEslint, flag) => {
|
|
6
|
+
// 没有选择Prettier则直接返回
|
|
7
|
+
if (!flag) return
|
|
8
|
+
// 路径
|
|
9
|
+
const templatePrettierPath = path.join(templatePath, 'prettier')
|
|
10
|
+
const targetPath = path.join(process.cwd(), projectName)
|
|
11
|
+
const targetPackageJson = path.join(targetPath, 'package.json')
|
|
12
|
+
|
|
13
|
+
// 文件
|
|
14
|
+
const targetPkg = await fs.readJson(targetPackageJson)
|
|
15
|
+
const prettierPkg = await fs.readJson(path.join(templatePrettierPath, 'package.json'))
|
|
16
|
+
|
|
17
|
+
// 添加package.json的内容
|
|
18
|
+
targetPkg.scripts = {
|
|
19
|
+
...targetPkg.scripts,
|
|
20
|
+
...prettierPkg.scripts,
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
targetPkg.devDependencies = {
|
|
24
|
+
...targetPkg.devDependencies,
|
|
25
|
+
...prettierPkg.devDependencies,
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
await fs.writeJson(targetPackageJson, targetPkg, { spaces: 2 })
|
|
29
|
+
|
|
30
|
+
// 复制.prettierignore文件
|
|
31
|
+
const prettierignore = path.join(templatePrettierPath, '.prettierignore')
|
|
32
|
+
fs.copy(prettierignore, path.join(targetPath, '.prettierignore'))
|
|
33
|
+
|
|
34
|
+
// 复制.prettierrc.js文件
|
|
35
|
+
const prettierrc = path.join(templatePrettierPath, '.prettierrc')
|
|
36
|
+
fs.copy(prettierrc, path.join(targetPath, '.prettierrc.js'))
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export default addPrettier
|