diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c4c30b5592..79a4d11b1b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -19230,7 +19230,3 @@ packages: which: 3.0.1 yaml: 2.3.4 dev: true - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false diff --git a/suites/boilerplate/src/index.ts b/suites/boilerplate/src/index.ts index 88d359f8e3..8a1feabf77 100644 --- a/suites/boilerplate/src/index.ts +++ b/suites/boilerplate/src/index.ts @@ -47,6 +47,7 @@ export default async ({ choices: [ { title: 'Static Site', value: 'site' }, { title: 'React Library', value: 'react' }, + { title: 'Vue Library', value: 'vue' }, { title: 'Theme Package', value: 'theme' }, ], initial: 0, @@ -75,6 +76,7 @@ export default async ({ const descriptions = { site: 'A static site based on dumi', react: 'A react library developed with dumi', + vue: 'A vue library developed with dumi', theme: 'A theme package for dumi', }; const questions: prompts.PromptObject[] = [ @@ -125,6 +127,16 @@ export default async ({ return 'NPM package name is required'; }, }); + } else if (type === 'vue') { + questions.unshift({ + name: 'name', + type: 'text', + message: 'Input NPM package name', + validate: (value: string) => { + if (value && value.trim()) return true; + return 'NPM package name is required'; + }, + }); } const generator = new BaseGenerator({ diff --git a/suites/boilerplate/templates/vue/.dumirc.ts.tpl b/suites/boilerplate/templates/vue/.dumirc.ts.tpl new file mode 100644 index 0000000000..e9a0609a0f --- /dev/null +++ b/suites/boilerplate/templates/vue/.dumirc.ts.tpl @@ -0,0 +1,13 @@ +import { defineConfig } from 'dumi'; + +export default defineConfig({ + apiParser: {}, + resolve: { + entryFile: 'src/index.ts', + }, + outputPath: 'docs-dist', + themeConfig: { + name: '{{{ name }}}', + }, + presets: [require.resolve('@dumijs/preset-vue')], +}); diff --git a/suites/boilerplate/templates/vue/.editorconfig b/suites/boilerplate/templates/vue/.editorconfig new file mode 100644 index 0000000000..e717f5eb63 --- /dev/null +++ b/suites/boilerplate/templates/vue/.editorconfig @@ -0,0 +1,13 @@ +# http://editorconfig.org +root = true + +[*] +indent_style = space +indent_size = 2 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md] +trim_trailing_whitespace = false diff --git a/suites/boilerplate/templates/vue/.eslintrc.js b/suites/boilerplate/templates/vue/.eslintrc.js new file mode 100644 index 0000000000..f5711b2db8 --- /dev/null +++ b/suites/boilerplate/templates/vue/.eslintrc.js @@ -0,0 +1,13 @@ +module.exports = { + extends: ['plugin:vue/vue3-recommended'], + parser: 'vue-eslint-parser', + parserOptions: { + parser: '@typescript-eslint/parser', + sourceType: 'module', + ecmaVersion: 2020, + ecmaFeatures: { + jsx: true, + }, + }, + rules: {}, +}; diff --git a/suites/boilerplate/templates/vue/.gitignore.tpl b/suites/boilerplate/templates/vue/.gitignore.tpl new file mode 100644 index 0000000000..8df3240707 --- /dev/null +++ b/suites/boilerplate/templates/vue/.gitignore.tpl @@ -0,0 +1,7 @@ +node_modules +/dist +.dumi/tmp +.dumi/tmp-test +.dumi/tmp-production +.DS_Store +/coverage diff --git a/suites/boilerplate/templates/vue/.husky/commit-msg b/suites/boilerplate/templates/vue/.husky/commit-msg new file mode 100755 index 0000000000..5b0b35410a --- /dev/null +++ b/suites/boilerplate/templates/vue/.husky/commit-msg @@ -0,0 +1,4 @@ +#!/usr/bin/env sh +. "$(dirname -- "$0")/_/husky.sh" + +npx commitlint --edit "${1}" diff --git a/suites/boilerplate/templates/vue/.husky/pre-commit b/suites/boilerplate/templates/vue/.husky/pre-commit new file mode 100755 index 0000000000..d24fdfc601 --- /dev/null +++ b/suites/boilerplate/templates/vue/.husky/pre-commit @@ -0,0 +1,4 @@ +#!/usr/bin/env sh +. "$(dirname -- "$0")/_/husky.sh" + +npx lint-staged diff --git a/suites/boilerplate/templates/vue/.prettierignore b/suites/boilerplate/templates/vue/.prettierignore new file mode 100644 index 0000000000..6a50e206c7 --- /dev/null +++ b/suites/boilerplate/templates/vue/.prettierignore @@ -0,0 +1,2 @@ +/dist +*.yaml diff --git a/suites/boilerplate/templates/vue/.prettierrc.js b/suites/boilerplate/templates/vue/.prettierrc.js new file mode 100644 index 0000000000..e6df093da7 --- /dev/null +++ b/suites/boilerplate/templates/vue/.prettierrc.js @@ -0,0 +1,19 @@ +module.exports = { + pluginSearchDirs: false, + plugins: [ + require.resolve('prettier-plugin-organize-imports'), + require.resolve('prettier-plugin-packagejson'), + ], + printWidth: 80, + proseWrap: 'never', + singleQuote: true, + trailingComma: 'all', + overrides: [ + { + files: '*.md', + options: { + proseWrap: 'preserve', + }, + }, + ], +}; diff --git a/suites/boilerplate/templates/vue/.stylelintrc b/suites/boilerplate/templates/vue/.stylelintrc new file mode 100644 index 0000000000..e3621944ff --- /dev/null +++ b/suites/boilerplate/templates/vue/.stylelintrc @@ -0,0 +1,3 @@ +{ + "extends": "@umijs/lint/dist/config/stylelint" +} diff --git a/suites/boilerplate/templates/vue/LICENSE.tpl b/suites/boilerplate/templates/vue/LICENSE.tpl new file mode 100644 index 0000000000..1b77645ee5 --- /dev/null +++ b/suites/boilerplate/templates/vue/LICENSE.tpl @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) {{{ author }}} + +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. diff --git a/suites/boilerplate/templates/vue/README.md.tpl b/suites/boilerplate/templates/vue/README.md.tpl new file mode 100644 index 0000000000..9f1b5782ce --- /dev/null +++ b/suites/boilerplate/templates/vue/README.md.tpl @@ -0,0 +1,64 @@ +# {{{ name }}} + +[![NPM version](https://img.shields.io/npm/v/{{{ name }}}.svg?style=flat)](https://npmjs.org/package/{{{ name }}}) +[![NPM downloads](http://img.shields.io/npm/dm/{{{ name }}}.svg?style=flat)](https://npmjs.org/package/{{{ name }}}) + +{{{ description }}} + +## Usage + +First, introduce css file: + +```ts +import '{{ name }}/dist/style.css'; +``` + +Then, introduce components: + +```html + +``` + +## Options + +TODO + +## Development + +```bash +# install dependencies +$ {{ npmClient }} install + +# develop library by docs demo +$ {{ npmClient }} start + +# build library source code +$ {{ npmClient }} run build + +# build library source code in watch mode +$ {{ npmClient }} run build:watch + +# build docs +$ {{ npmClient }} run docs:build + +# Locally preview the production build. +$ {{ npmClient }} run docs:preview + +# check your project for potential problems +$ {{ npmClient }} run doctor + +# Test +$ {{ npmClient }} test + +# Coverage +$ {{ npmClient }} test:cov + +# Lint +$ {{ npmClient }} lint +``` + +## LICENSE + +MIT diff --git a/suites/boilerplate/templates/vue/docs/guide.md b/suites/boilerplate/templates/vue/docs/guide.md new file mode 100644 index 0000000000..5504ddf6ab --- /dev/null +++ b/suites/boilerplate/templates/vue/docs/guide.md @@ -0,0 +1 @@ +This is a guide example. diff --git a/suites/boilerplate/templates/vue/docs/index.md.tpl b/suites/boilerplate/templates/vue/docs/index.md.tpl new file mode 100644 index 0000000000..c9aba4e652 --- /dev/null +++ b/suites/boilerplate/templates/vue/docs/index.md.tpl @@ -0,0 +1,22 @@ +--- +hero: + title: library + description: {{{ description }}} + actions: + - text: Hello + link: / + - text: Vue + link: / +features: + - title: Hello + emoji: 💎 + description: Put hello description here + - title: Vue + emoji: 🌈 + description: Put world description here + - title: '!' + emoji: 🚀 + description: Put ! description here +--- + +{{{ name }}} diff --git a/suites/boilerplate/templates/vue/package.json.tpl b/suites/boilerplate/templates/vue/package.json.tpl new file mode 100644 index 0000000000..633824b69a --- /dev/null +++ b/suites/boilerplate/templates/vue/package.json.tpl @@ -0,0 +1,103 @@ +{ + "name": "{{{ name }}}", + "version": "0.0.1", + "description": "{{{ description }}}", + "scripts": { + "build": "vite build && vue-tsc --project ./tsconfig.build.json", + "build:watch": "vite build --watch", + "dev": "dumi dev", + "docs:build": "dumi build", + "docs:preview": "dumi preview", + "lint": "npm run lint:es && npm run lint:css", + "lint:css": "stylelint \"{src,test}/**/*.{css,less}\"", + "lint:es": "eslint \"{src,test}/**/*.{js,jsx,ts,tsx,vue}\"", + "prepare": "husky install && dumi setup", + "prepublishOnly": "npm run test && npm run build", + "start": "npm run dev", + "test": "vitest", + "test:cov": "vitest --coverage", + "typecheck": "vue-tsc --noEmit" + }, + "authors": [{{#author}} + "{{{ author }}}" + {{/author}}], + "repository": { + "type": "git" + }, + "license": "MIT", + "exports": { + ".": { + "types": "./dist/typings/index.d.ts", + "import": "./dist/index.mjs", + "require": "./dist/index.umd.js" + }, + "./dist/style.css": "./dist/style.css" + }, + "main": "./dist/index.umd.js", + "module": "./dist/index.mjs", + "types": "./dist/typings/index.d.ts", + "files": [ + "dist" + ], + "commitlint": { + "extends": [ + "@commitlint/config-conventional" + ] + }, + "lint-staged": { + "*.{md,json}": [ + "prettier --write --no-error-on-unmatched-pattern" + ], + "*.{css,less}": [ + "stylelint --fix", + "prettier --write" + ], + "*.{js,jsx}": [ + "eslint --fix", + "prettier --write" + ], + "*.{ts,tsx}": [ + "eslint --fix", + "prettier --parser=typescript --write" + ] + }, + "publishConfig": { + "access": "public" + }, + "peerDependencies": { + "vue": ">=3.3.0" + }, + "devDependencies": { + "@commitlint/cli": "^17.1.2", + "@commitlint/config-conventional": "^17.1.0", + "@dumijs/preset-vue": "^2.4.12", + "@eslint/js": "^9.11.1", + "@types/react": "^18.0.0", + "@types/react-dom": "^18.0.0", + "@typescript-eslint/eslint-plugin": "^8.7.0", + "@typescript-eslint/parser": "^8.7.0", + "@umijs/lint": "^4.3.24", + "@vitejs/plugin-vue": "^5.1.4", + "@vitejs/plugin-vue-jsx": "^4.0.1", + "@vitest/coverage-v8": "^2.1.1", + "@vue/test-utils": "^2.4.6", + "dumi": "{{{ version }}}", + "eslint": "^8.57.1", + "eslint-plugin-vue": "^9.17.0", + "happy-dom": "^15.7.4", + "husky": "^8.0.1", + "less": "^4.2.0", + "lint-staged": "^13.0.3", + "prettier": "^2.7.1", + "prettier-plugin-organize-imports": "^3.0.0", + "prettier-plugin-packagejson": "^2.2.18", + "react": "^18.0.0", + "react-dom": "^18.0.0", + "stylelint": "^14.9.1", + "typescript": "~5.5.4", + "vite": "^5.4.8", + "vitest": "^2.1.1", + "vue": "^3.5.10", + "vue-tsc": "^2.1.6" + } +} diff --git a/suites/boilerplate/templates/vue/src/Bar/Bar.test.ts.tpl b/suites/boilerplate/templates/vue/src/Bar/Bar.test.ts.tpl new file mode 100644 index 0000000000..b6d2741b9b --- /dev/null +++ b/suites/boilerplate/templates/vue/src/Bar/Bar.test.ts.tpl @@ -0,0 +1,15 @@ +import { mount, type VueWrapper } from '@vue/test-utils'; +import { beforeEach, describe, expect, it } from 'vitest'; +import Bar from './RootBar.vue'; + +describe('Bar', () => { + let wrapper: VueWrapper>; + + beforeEach(() => { + wrapper = mount(Bar, { props: { icon: 'V' } }); + }); + + it('should render', () => { + expect(wrapper.html()).contain('V'); + }); +}); diff --git a/suites/boilerplate/templates/vue/src/Bar/RootBar.vue b/suites/boilerplate/templates/vue/src/Bar/RootBar.vue new file mode 100644 index 0000000000..18d8472d21 --- /dev/null +++ b/suites/boilerplate/templates/vue/src/Bar/RootBar.vue @@ -0,0 +1,51 @@ + + + + + diff --git a/suites/boilerplate/templates/vue/src/Bar/index.md.tpl b/suites/boilerplate/templates/vue/src/Bar/index.md.tpl new file mode 100644 index 0000000000..84de568e55 --- /dev/null +++ b/suites/boilerplate/templates/vue/src/Bar/index.md.tpl @@ -0,0 +1,39 @@ +# Bar + +This is an example component of Vue SFC. + +```vue + + + + + +``` +## Bar API + +### Props + + + +### Slots + + + +### Events + + diff --git a/suites/boilerplate/templates/vue/src/Bar/index.ts b/suites/boilerplate/templates/vue/src/Bar/index.ts new file mode 100644 index 0000000000..e6dfbcd077 --- /dev/null +++ b/suites/boilerplate/templates/vue/src/Bar/index.ts @@ -0,0 +1 @@ +export { default as Bar } from './RootBar.vue'; diff --git a/suites/boilerplate/templates/vue/src/Foo/Foo.less b/suites/boilerplate/templates/vue/src/Foo/Foo.less new file mode 100644 index 0000000000..a15c877ac0 --- /dev/null +++ b/suites/boilerplate/templates/vue/src/Foo/Foo.less @@ -0,0 +1,3 @@ +.foo { + color: red; +} diff --git a/suites/boilerplate/templates/vue/src/Foo/Foo.test.ts.tpl b/suites/boilerplate/templates/vue/src/Foo/Foo.test.ts.tpl new file mode 100644 index 0000000000..5845a912f8 --- /dev/null +++ b/suites/boilerplate/templates/vue/src/Foo/Foo.test.ts.tpl @@ -0,0 +1,10 @@ +import { mount } from '@vue/test-utils'; +import { describe, expect, it } from 'vitest'; +import { Foo } from './index'; + +describe('Foo', () => { + it('should render', () => { + const wrapper = mount(Foo, { props: { title: 'foo' } }); + expect(wrapper.html()).contain('foo'); + }); +}); diff --git a/suites/boilerplate/templates/vue/src/Foo/index.md.tpl b/suites/boilerplate/templates/vue/src/Foo/index.md.tpl new file mode 100644 index 0000000000..6e14197c44 --- /dev/null +++ b/suites/boilerplate/templates/vue/src/Foo/index.md.tpl @@ -0,0 +1,14 @@ +# Foo + +This is an example component of Vue JSX. + +```jsx +import { Foo } from '{{{ name }}}'; + +export default () => +``` +## Foo API + +### Props + + diff --git a/suites/boilerplate/templates/vue/src/Foo/index.tsx b/suites/boilerplate/templates/vue/src/Foo/index.tsx new file mode 100644 index 0000000000..fe50e1f0a3 --- /dev/null +++ b/suites/boilerplate/templates/vue/src/Foo/index.tsx @@ -0,0 +1,17 @@ +import { defineComponent } from 'vue'; +import './Foo.less'; + +export const Foo = defineComponent({ + props: { + /** + * @description 标题 + */ + title: { + type: String, + default: '', + }, + }, + setup({ title }) { + return () =>
{title}
; + }, +}); diff --git a/suites/boilerplate/templates/vue/src/index.ts b/suites/boilerplate/templates/vue/src/index.ts new file mode 100644 index 0000000000..ac2f1b4577 --- /dev/null +++ b/suites/boilerplate/templates/vue/src/index.ts @@ -0,0 +1,2 @@ +export * from './Bar'; +export * from './Foo'; diff --git a/suites/boilerplate/templates/vue/tsconfig.build.json.tpl b/suites/boilerplate/templates/vue/tsconfig.build.json.tpl new file mode 100644 index 0000000000..293da39e07 --- /dev/null +++ b/suites/boilerplate/templates/vue/tsconfig.build.json.tpl @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "emitDeclarationOnly": true, + "declarationDir": "./dist/typings", + "lib": ["esnext", "dom"] + }, + "include": ["src/**/*"], + "exclude": ["src/**/*.test.*"] +} diff --git a/suites/boilerplate/templates/vue/tsconfig.json.tpl b/suites/boilerplate/templates/vue/tsconfig.json.tpl new file mode 100644 index 0000000000..45ebc86437 --- /dev/null +++ b/suites/boilerplate/templates/vue/tsconfig.json.tpl @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "strict": true, + "declaration": true, + "skipLibCheck": true, + "esModuleInterop": true, + "jsx": "preserve", + "jsxImportSource": "vue", + "strictNullChecks": false, + "baseUrl": "./", + "paths": { + "@@/*": [".dumi/tmp/*"], + "{{{ name }}}": ["src"], + "{{{ name }}}/*": ["src/*", "*"] + } + }, + "include": [".dumirc.ts", "src/**/*"] +} diff --git a/suites/boilerplate/templates/vue/vite.config.mts b/suites/boilerplate/templates/vue/vite.config.mts new file mode 100644 index 0000000000..bbb0d4338c --- /dev/null +++ b/suites/boilerplate/templates/vue/vite.config.mts @@ -0,0 +1,36 @@ +import { defineConfig } from 'vite'; +import { resolve } from 'node:path'; +import vue from '@vitejs/plugin-vue'; +import vueJsx from '@vitejs/plugin-vue-jsx'; + + +const externals = ['vue']; + +export default defineConfig({ + plugins: [ + vue(), + vueJsx(), + ], + build: { + lib: { + entry: resolve(__dirname, 'src/index.ts'), + name: 'index', + fileName: 'index', + }, + rollupOptions: { + external: [...externals], + output: { + globals: { + 'vue': 'Vue', + }, + }, + }, + outDir: 'dist', + }, + resolve: { + dedupe: ['vue'], + }, + optimizeDeps: { + include: [...externals], + }, +}); diff --git a/suites/boilerplate/templates/vue/vitest.config.mts b/suites/boilerplate/templates/vue/vitest.config.mts new file mode 100644 index 0000000000..45c99b72f4 --- /dev/null +++ b/suites/boilerplate/templates/vue/vitest.config.mts @@ -0,0 +1,19 @@ +import { defineConfig } from 'vitest/config'; +import vue from '@vitejs/plugin-vue'; +import vueJsx from '@vitejs/plugin-vue-jsx'; + + +export default defineConfig({ + plugins: [ + vue(), + vueJsx(), + ], + test: { + environment: 'happy-dom', + include: ['./**/*.test.{ts,js,tsx}'], + coverage: { + provider: 'v8', + reporter: ['html', 'text', 'json'], + }, + }, +});