├── src
├── locales
│ ├── en.json
│ └── fa.json
├── utils
│ ├── index.ts
│ └── i18n.ts
├── assets
│ ├── logo.png
│ ├── main.css
│ └── logo.svg
├── App.vue
├── components
│ ├── NewJsxFile
│ │ ├── NewJsxFile.tsx
│ │ └── NewJsxFile.cy.ts
│ ├── markdown
│ │ └── MDTest.vue
│ └── HelloWorld
│ │ ├── HelloWorld.cy.ts
│ │ ├── HelloWorld.test.ts
│ │ └── HelloWorld.vue
├── env.d.ts
├── store
│ └── main.ts
├── pages
│ ├── test.vue
│ ├── markdown.md
│ └── index.vue
├── layouts
│ ├── default.vue
│ └── sub.vue
├── components.d.ts
├── main.ts
└── auto-imports.d.ts
├── .npmrc
├── .stylelintignore
├── vite-env.d.ts
├── .vscode
├── settings.json
└── extensions.json
├── public
├── favicon.ico
├── maskable-icon-x192.png
├── maskable-icon-x512.png
├── android-chrome-192x192.png
└── android-chrome-512x512.png
├── .husky
└── pre-commit
├── renovate.json
├── .eslintignore
├── postcss.config.cjs
├── tsconfig.node.json
├── .gitignore
├── cypress
├── support
│ ├── commands.js
│ ├── component-index.html
│ ├── e2e.js
│ └── component.js
├── tsconfig.json
└── e2e
│ └── home.cy.ts
├── .editorconfig
├── cypress.config.ts
├── Dockerfile
├── index.html
├── cypress.d.ts
├── unocss.config.ts
├── shims.d.ts
├── LICENSE
├── .versionrc.js
├── tsconfig.json
├── .eslintrc
├── CHANGELOG.md
├── package.json
├── .stylelintrc.cjs
├── vite.config.ts
└── README.md
/src/locales/en.json:
--------------------------------------------------------------------------------
1 | {
2 | "button": "Button"
3 | }
4 |
--------------------------------------------------------------------------------
/src/locales/fa.json:
--------------------------------------------------------------------------------
1 | {
2 | "button": "دکمه"
3 | }
4 |
--------------------------------------------------------------------------------
/.npmrc:
--------------------------------------------------------------------------------
1 | # after pnpm version 7
2 | strict-peer-dependencies=false
--------------------------------------------------------------------------------
/src/utils/index.ts:
--------------------------------------------------------------------------------
1 | import i18n from './i18n'
2 |
3 | export default { i18n }
4 |
--------------------------------------------------------------------------------
/.stylelintignore:
--------------------------------------------------------------------------------
1 | dist
2 | coverage
3 | **/dist
4 | **/node_modules
5 | node_modules
6 |
--------------------------------------------------------------------------------
/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | // vite-env.d.ts
2 | ///
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "i18n-ally.localesPaths": [
3 | "src/locales"
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alibaba-aero/vuilerplate/HEAD/public/favicon.ico
--------------------------------------------------------------------------------
/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alibaba-aero/vuilerplate/HEAD/src/assets/logo.png
--------------------------------------------------------------------------------
/.husky/pre-commit:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 | . "$(dirname -- "$0")/_/husky.sh"
3 |
4 | pnpm lint-staged
5 |
--------------------------------------------------------------------------------
/public/maskable-icon-x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alibaba-aero/vuilerplate/HEAD/public/maskable-icon-x192.png
--------------------------------------------------------------------------------
/public/maskable-icon-x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alibaba-aero/vuilerplate/HEAD/public/maskable-icon-x512.png
--------------------------------------------------------------------------------
/public/android-chrome-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alibaba-aero/vuilerplate/HEAD/public/android-chrome-192x192.png
--------------------------------------------------------------------------------
/public/android-chrome-512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alibaba-aero/vuilerplate/HEAD/public/android-chrome-512x512.png
--------------------------------------------------------------------------------
/src/App.vue:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/renovate.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json",
3 | "extends": [
4 | "config:base"
5 | ]
6 | }
7 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | **/node_modules
2 | **/dist
3 | node_modules
4 | coverage
5 | .vscode
6 | vite.config.ts
7 | postcss.config.js
8 | cypress.config.ts
9 |
--------------------------------------------------------------------------------
/postcss.config.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: [
3 | require('postcss-import'),
4 | require('postcss-nested'),
5 | require('postcss-url'),
6 | ]
7 | }
8 |
--------------------------------------------------------------------------------
/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "composite": true,
4 | "module": "esnext",
5 | "moduleResolution": "node"
6 | },
7 | "include": ["vite.config.ts"]
8 | }
9 |
--------------------------------------------------------------------------------
/src/components/NewJsxFile/NewJsxFile.tsx:
--------------------------------------------------------------------------------
1 | function NewJsxFile() {
2 | return (
3 |
4 | New JSX File
5 |
6 | )
7 | }
8 |
9 | export default NewJsxFile
10 |
--------------------------------------------------------------------------------
/src/components/NewJsxFile/NewJsxFile.cy.ts:
--------------------------------------------------------------------------------
1 | import Component from './NewJsxFile'
2 |
3 | describe('NewJsxFile', () => {
4 | it('should mount component correctly', () => {
5 | cy.mount(Component, {})
6 | })
7 | })
8 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | dist
3 | .nuxt
4 | .DS_Store
5 | .idea
6 | coverage
7 | *-coverage
8 | *.log
9 | .nyc_output
10 | .env*.local
11 | tsconfig.tsbuildinfo
12 | stats.html
13 | .vite-ssg-temp
14 | .vite-ssg-dist
15 |
--------------------------------------------------------------------------------
/cypress/support/commands.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line import/no-extraneous-dependencies
2 | import '@testing-library/cypress/add-commands'
3 |
4 | Cypress.Commands.add('getByTestId', (selector, ...args) => cy.get(`[data-testid=${selector}]`, ...args))
5 |
--------------------------------------------------------------------------------
/src/utils/i18n.ts:
--------------------------------------------------------------------------------
1 | import messages from '@intlify/vite-plugin-vue-i18n/messages'
2 | import { createI18n } from 'vue-i18n'
3 |
4 | const i18n = createI18n({
5 | legacy: false,
6 | locale: 'en',
7 | globalInjection: true,
8 | messages,
9 | })
10 |
11 | export default i18n
12 |
--------------------------------------------------------------------------------
/cypress/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig.json",
3 | "compilerOptions": {
4 | "allowJs": true,
5 | "types": [
6 | "cypress",
7 | "@testing-library/cypress"
8 | ]
9 | },
10 | "exclude": [],
11 | "include": [
12 | "**/*.ts",
13 | "../cypress.d.ts"
14 | ]
15 | }
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | indent_style = space
6 | indent_size = 2
7 | end_of_line = lf
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
11 | [*.css]
12 | indent_size = 2
13 |
14 | [*.md]
15 | insert_final_newline = false
16 | trim_trailing_whitespace = false
17 |
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": [
3 | "antfu.iconify",
4 | "antfu.unocss",
5 | "antfu.vite",
6 | "antfu.goto-alias",
7 | "csstools.postcss",
8 | "dbaeumer.vscode-eslint",
9 | "vue.volar",
10 | "lokalise.i18n-ally",
11 | "streetsidesoftware.code-spell-checker"
12 | ]
13 | }
14 |
--------------------------------------------------------------------------------
/cypress.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'cypress'
2 |
3 | export default defineConfig({
4 | e2e: {
5 | baseUrl: 'http://localhost:5173',
6 | chromeWebSecurity: false,
7 | specPattern: 'cypress/e2e/**/*.cy.*',
8 | },
9 | component: {
10 | devServer: {
11 | framework: 'vue',
12 | bundler: 'vite',
13 | },
14 | },
15 | })
16 |
--------------------------------------------------------------------------------
/cypress/support/component-index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Components App
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/src/env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 |
4 | declare module '*.vue' {
5 | import type { DefineComponent } from 'vue'
6 | // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types
7 | const component: DefineComponent<{}, {}, any>
8 | export default component
9 | }
10 |
--------------------------------------------------------------------------------
/src/store/main.ts:
--------------------------------------------------------------------------------
1 | import { acceptHMRUpdate, defineStore } from 'pinia'
2 |
3 | interface RootState {
4 | counter: number
5 | }
6 |
7 | export const useMainStore = defineStore('main', {
8 | state: (): RootState => ({
9 | counter: 0,
10 | }),
11 | })
12 |
13 | if (import.meta.hot)
14 | import.meta.hot.accept(acceptHMRUpdate(useMainStore, import.meta.hot))
15 |
16 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM node:18-alpine as build-stage
2 |
3 | WORKDIR /app
4 | RUN corepack enable
5 |
6 | COPY package.json pnpm-lock.yaml ./
7 | RUN pnpm install --frozen-lockfile
8 |
9 | COPY . .
10 | RUN pnpm build
11 |
12 | FROM nginx:stable-alpine as production-stage
13 |
14 | COPY --from=build-stage /app/dist /usr/share/nginx/html
15 | EXPOSE 80
16 |
17 | CMD ["nginx", "-g", "daemon off;"]
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite App
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/cypress.d.ts:
--------------------------------------------------------------------------------
1 | import { mount } from 'cypress/vue';
2 |
3 | type MountParams = Parameters;
4 | type OptionsParam = MountParams[1];
5 |
6 | declare global {
7 | namespace Cypress {
8 | interface Chainable {
9 | /**
10 | * Get Element by data-testid
11 | * @example
12 | * cy.getByTestId('selector')
13 | */
14 | getByTestId(selector: string): Chainable
15 | /**
16 | * Mount element
17 | * @example
18 | * cy.mount(Component)
19 | */
20 | mount: typeof mount;
21 | }
22 | }
23 | }
--------------------------------------------------------------------------------
/src/pages/test.vue:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 | {{ t('testPage') }}
8 |
9 |
10 | {{ t('home') }}
11 |
12 |
13 |
14 |
15 |
16 | {
17 | meta: {
18 | layout: "sub"
19 | }
20 | }
21 |
22 |
23 |
24 | {
25 | "en": {
26 | "testPage": "Test Page",
27 | "home": "Home"
28 | },
29 | "fa": {
30 | "testPage": "صفحه تست",
31 | "home": "خانه"
32 | }
33 | }
34 |
35 |
--------------------------------------------------------------------------------
/cypress/e2e/home.cy.ts:
--------------------------------------------------------------------------------
1 | context('Home', () => {
2 | beforeEach(() => {
3 | cy.visit('/')
4 | })
5 |
6 | it('go to test page', () => {
7 | cy.url().should('eq', 'http://localhost:5173/')
8 |
9 | cy.getByTestId('test-link')
10 | .should('have.attr', 'href')
11 | .and('eq', '/test')
12 | cy.getByTestId('test-link').click()
13 |
14 | cy.url().should('eq', 'http://localhost:5173/test')
15 |
16 | cy.getByTestId('home-link')
17 | .should('have.attr', 'href')
18 | .and('eq', '/')
19 | cy.getByTestId('home-link').click()
20 |
21 | cy.url().should('eq', 'http://localhost:5173/')
22 | })
23 | })
24 |
--------------------------------------------------------------------------------
/src/pages/markdown.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: My Markdown Page
3 | title: My Markdown Page
4 | meta:
5 | - name: description
6 | content: Hello World
7 | ---
8 | # Hello World
9 |
10 | Link to alibaba: https://alibaba.ir
11 |
12 | Link: [Alibaba](https://alibaba.ir)
13 |
14 | This is {{ frontmatter.name }}
15 |
16 |
17 |
18 | Home
19 |
20 |
21 | ```javascript
22 | function test() {
23 | return 0;
24 | }
25 | ```
26 |
27 |
37 |
--------------------------------------------------------------------------------
/src/layouts/default.vue:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 | {{ t('header') }}
9 |
10 |
11 |
14 |
15 |
16 |
17 |
26 |
27 |
28 | {
29 | "en": {
30 | "header": "Header",
31 | "footer": "Footer"
32 | },
33 | "fa": {
34 | "header": "هدر",
35 | "footer": "فوتر"
36 | }
37 | }
38 |
39 |
--------------------------------------------------------------------------------
/src/layouts/sub.vue:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 | {{ t('header') }}
9 |
10 |
11 |
14 |
15 |
16 |
17 |
26 |
27 |
28 | {
29 | "en": {
30 | "header": "Header Sub",
31 | "footer": "Footer Sub"
32 | },
33 | "fa": {
34 | "header": "هدر ساب",
35 | "footer": "فوتر ساب"
36 | }
37 | }
38 |
39 |
--------------------------------------------------------------------------------
/src/components.d.ts:
--------------------------------------------------------------------------------
1 | // generated by unplugin-vue-components
2 | // We suggest you to commit this file into source control
3 | // Read more: https://github.com/vuejs/core/pull/3399
4 | import '@vue/runtime-core'
5 |
6 | export {}
7 |
8 | declare module '@vue/runtime-core' {
9 | export interface GlobalComponents {
10 | HelloWorld: typeof import('./components/HelloWorld/HelloWorld.vue')['default']
11 | MDTest: typeof import('./components/markdown/MDTest.vue')['default']
12 | NewJsxFile: typeof import('./components/NewJsxFile/NewJsxFile.tsx')['default']
13 | RouterLink: typeof import('vue-router')['RouterLink']
14 | RouterView: typeof import('vue-router')['RouterView']
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/unocss.config.ts:
--------------------------------------------------------------------------------
1 | import {
2 | defineConfig,
3 | presetAttributify,
4 | presetIcons,
5 | presetTypography,
6 | presetUno,
7 | presetWebFonts,
8 | transformerDirectives,
9 | } from 'unocss'
10 |
11 | export default defineConfig({
12 | presets: [
13 | presetUno(),
14 | presetAttributify({
15 | prefix: 'un-',
16 | }),
17 | presetIcons({
18 | scale: 1.2,
19 | warn: true,
20 | }),
21 | presetTypography(),
22 | presetWebFonts({
23 | fonts: {
24 | sans: 'DM Sans',
25 | serif: 'DM Serif Display',
26 | mono: 'DM Mono',
27 | },
28 | }),
29 | ],
30 | transformers: [
31 | transformerDirectives(),
32 | ],
33 | })
34 |
--------------------------------------------------------------------------------
/src/main.ts:
--------------------------------------------------------------------------------
1 | import generatedRoutes from 'virtual:generated-pages'
2 | import { setupLayouts } from 'virtual:generated-layouts'
3 | import { createPinia } from 'pinia'
4 | import { ViteSSG } from 'vite-ssg'
5 | import App from './App.vue'
6 |
7 | import '@unocss/reset/tailwind.css'
8 | import 'uno.css'
9 |
10 | const routes = setupLayouts(generatedRoutes)
11 |
12 | export const createApp = ViteSSG(
13 | App,
14 | { routes },
15 | ({ app, router, initialState }) => {
16 | const pinia = createPinia()
17 | app.use(pinia)
18 | app.use(router)
19 | app.use(i18n)
20 |
21 | if (import.meta.env.SSR)
22 | initialState.pinia = pinia.state.value
23 | else
24 | pinia.state.value = initialState.pinia || {}
25 | },
26 | )
27 |
--------------------------------------------------------------------------------
/cypress/support/e2e.js:
--------------------------------------------------------------------------------
1 | // ***********************************************************
2 | // This example support/index.js is processed and
3 | // loaded automatically before your test files.
4 | //
5 | // This is a great place to put global configuration and
6 | // behavior that modifies Cypress.
7 | //
8 | // You can change the location of this file or turn off
9 | // automatically serving support files with the
10 | // 'supportFile' configuration option.
11 | //
12 | // You can read more here:
13 | // https://on.cypress.io/configuration
14 | // ***********************************************************
15 |
16 | // Import commands.js using ES2015 syntax:
17 | import './commands'
18 |
19 | // Alternatively you can use CommonJS syntax:
20 | // require('./commands')
21 |
--------------------------------------------------------------------------------
/src/components/markdown/MDTest.vue:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 | {{ t('testComponent') }}
13 |
14 | {{ t('props') }} {{ test }}
15 |
16 |
17 |
18 |
24 |
25 |
26 | {
27 | "en": {
28 | "testComponent": "Test Component in Markdown",
29 | "props": "Props:"
30 | },
31 | "fa": {
32 | "testComponent": "تست کامپوننت در مارک داون",
33 | "props": "پراپس:"
34 | }
35 | }
36 |
37 |
--------------------------------------------------------------------------------
/src/pages/index.vue:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 | {{ t('test') }}
12 |
13 |
14 |
15 |
16 |
17 |
18 |

19 |
20 |
21 |
22 |
23 |
24 |
25 | {
26 | "en": {
27 | "test": "Test"
28 | },
29 | "fa": {
30 | "test": "تست"
31 | }
32 | }
33 |
34 |
--------------------------------------------------------------------------------
/cypress/support/component.js:
--------------------------------------------------------------------------------
1 | // ***********************************************************
2 | // This example support/component.js is processed and
3 | // loaded automatically before your test files.
4 | //
5 | // This is a great place to put global configuration and
6 | // behavior that modifies Cypress.
7 | //
8 | // You can change the location of this file or turn off
9 | // automatically serving support files with the
10 | // 'supportFile' configuration option.
11 | //
12 | // You can read more here:
13 | // https://on.cypress.io/configuration
14 | // ***********************************************************
15 |
16 | // eslint-disable-next-line import/no-extraneous-dependencies
17 | import { mount } from 'cypress/vue'
18 | // Import commands.js using ES2015 syntax:
19 | import './commands'
20 |
21 | // Ensure global styles are loaded
22 | import '../../src/assets/main.css'
23 |
24 | // Alternatively you can use CommonJS syntax:
25 | // require('./commands')
26 |
27 | Cypress.Commands.add('mount', mount)
28 |
--------------------------------------------------------------------------------
/shims.d.ts:
--------------------------------------------------------------------------------
1 | declare interface Window {
2 | // extend the window
3 | }
4 |
5 | // with vite-plugin-vue-markdown, markdown files can be treated as Vue components
6 | declare module '*.md' {
7 | import { type DefineComponent } from 'vue'
8 | const component: DefineComponent<{}, {}, any>
9 | export default component
10 | }
11 |
12 | declare module '*.vue' {
13 | import { type DefineComponent } from 'vue'
14 | const component: DefineComponent<{}, {}, any>
15 | export default component
16 | }
17 | // Vite plugin to load SVG files as Vue components
18 | declare module 'vite-svg-loader' {
19 | import { Plugin } from 'vite'
20 | function svgLoader(options?: { svgoConfig?: Object, svgo?: boolean }): Plugin
21 | export default svgLoader
22 | }
23 |
24 | declare module '*.svg?component' {
25 | import { FunctionalComponent, SVGAttributes } from 'vue'
26 | const src: FunctionalComponent
27 | export default src
28 | }
29 |
30 | declare module '*.svg?url' {
31 | const src: String
32 | export default src
33 | }
34 |
35 | declare module '*.svg?raw' {
36 | const src: String
37 | export default src
38 | }
39 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 Alibaba Travels Co Open Source
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.
22 |
--------------------------------------------------------------------------------
/.versionrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | "releaseCommitMessageFormat": "misc(versions): add version {{currentTag}}",
3 | "types": [
4 | {
5 | "type": "feat",
6 | "section": "Features"
7 | },
8 | {
9 | "type": "fix",
10 | "section": "Bug Fixes"
11 | },
12 | {
13 | "type": "test",
14 | "section": "Tests"
15 | },
16 | {
17 | "type": "build",
18 | "section": "Build System"
19 | },
20 | {
21 | "type": "docs",
22 | "section": "Documentation"
23 | },
24 | {
25 | "type": "refactor",
26 | "section": "Refactors"
27 | },
28 | {
29 | "type": "style",
30 | "section": "Style Changes"
31 | },
32 | {
33 | "type": "perf",
34 | "section": "Performance Related"
35 | },
36 | {
37 | "type": "ci",
38 | "section": "CI/CD Related"
39 | },
40 | {
41 | "type": "misc",
42 | "section": "Miscellaneous"
43 | }
44 | ]
45 | }
46 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "esnext",
4 | "useDefineForClassFields": true,
5 | "module": "esnext",
6 | "moduleResolution": "node",
7 | "strict": true,
8 | "jsx": "preserve",
9 | "sourceMap": true,
10 | "resolveJsonModule": true,
11 | "esModuleInterop": true,
12 | "lib": ["esnext", "dom"],
13 | "skipLibCheck": true,
14 | "types": [
15 | "vitest",
16 | "vite/client",
17 | "vue/ref-macros",
18 | "vite-plugin-pages/client",
19 | "vite-plugin-vue-layouts/client",
20 | "@intlify/vite-plugin-vue-i18n/client"
21 | ],
22 | "allowSyntheticDefaultImports": true,
23 | "baseUrl": ".",
24 | "paths": {
25 | "@/*": ["src/*"],
26 | "@/utils/*": ["src/utils/*"]
27 | },
28 | },
29 | "include": [
30 | "src/**/*.ts",
31 | "src/**/*.d.ts",
32 | "src/**/*.tsx",
33 | "src/**/*.vue",
34 | "src/**/*.js",
35 | "*.ts",
36 | "*.js",
37 | "cypress",
38 | "cypress.d.ts",
39 | ],
40 | "exclude": [
41 | "dist",
42 | "**/dist",
43 | "node_modules",
44 | "**/node_modules",
45 | "coverage"
46 | ],
47 | "references": [{ "path": "./tsconfig.node.json" }]
48 | }
49 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": [
3 | "airbnb",
4 | "airbnb-typescript/base",
5 | "plugin:vue/vue3-recommended",
6 | "plugin:cypress/recommended",
7 | "plugin:@intlify/vue-i18n/recommended",
8 | "@antfu"
9 | ],
10 | "env": {
11 | "cypress/globals": true
12 | },
13 | "parser": "vue-eslint-parser",
14 | "parserOptions": {
15 | "parser": "@typescript-eslint/parser",
16 | "project": "./tsconfig.json",
17 | "extraFileExtensions": [
18 | ".vue",
19 | ".tsx"
20 | ],
21 | "ecmaVersion": 2021,
22 | "ecmaFeatures": {
23 | "jsx": true
24 | },
25 | "sourceType": "module",
26 | "allowImportExportEverywhere": true
27 | },
28 | "rules": {
29 | "react/display-name": "off",
30 | "nonblock-statement-body-position": "off",
31 | "import/prefer-default-export": "off",
32 | "react/jsx-filename-extension": "off",
33 | "import/no-extraneous-dependencies": ["error", {
34 | "devDependencies": true
35 | }],
36 | "@intlify/vue-i18n/no-missing-keys": "off",
37 | "import/extensions": "off"
38 | },
39 | "settings": {
40 | "vue-i18n": {
41 | "localeDir": "./locales/*.{json,json5,yaml,yml}",
42 | "messageSyntaxVersion": "^9.0.0"
43 | }
44 | }
45 | }
--------------------------------------------------------------------------------
/src/components/HelloWorld/HelloWorld.cy.ts:
--------------------------------------------------------------------------------
1 | import { createTestingPinia } from '@pinia/testing'
2 | import Component from './HelloWorld.vue'
3 |
4 | const factory = (options: any) => cy.mount(Component, {
5 | global: {
6 | plugins: [createTestingPinia({ createSpy: cy.spy }), i18n],
7 | },
8 | ...options,
9 | })
10 |
11 | describe('HelloWorld', () => {
12 | it('should mount correctly', () => {
13 | factory({})
14 | cy.getByTestId('counter-pinia').contains('Counter Pinia: 0')
15 | cy.getByTestId('add-btn-pinia')
16 | .contains('Add pinia')
17 | .click()
18 | .contains('Add pinia')
19 | cy.getByTestId('counter-pinia').contains('Counter Pinia: 1')
20 |
21 | cy.getByTestId('counter').contains('Counter: 0')
22 | cy.getByTestId('add-btn')
23 | .contains('Add')
24 | .click()
25 | .contains('Add')
26 | cy.getByTestId('counter').contains('Counter: 1')
27 | })
28 |
29 | it('should change locale correctly', () => {
30 | factory({})
31 | cy.getByTestId('local').contains('Local')
32 | cy.getByTestId('toggle-button')
33 | .contains('Button Change Locale')
34 | .click()
35 | .contains('دکمه تغییر زبان')
36 | cy.getByTestId('local').contains('محلی')
37 | })
38 | })
39 |
--------------------------------------------------------------------------------
/src/assets/main.css:
--------------------------------------------------------------------------------
1 | @import 'prism-theme-vars/base.css';
2 | @import 'prism-theme-vars/themes/vitesse-dark.css';
3 |
4 | html:not(.dark) {
5 | --prism-foreground: #393A34;
6 | --prism-background: #F8F8F8;
7 | --prism-comment: #758575;
8 | --prism-namespace: #444444;
9 | --prism-string: #BC8671;
10 | --prism-punctuation: #80817D;
11 | --prism-literal: #36ACAA;
12 | --prism-keyword: #248459;
13 | --prism-function: #849145;
14 | --prism-deleted: #9A050F;
15 | --prism-class: #2B91AF;
16 | --prism-builtin: maroon;
17 | --prism-property: #CE9178;
18 | --prism-regex: #AD502B;
19 | }
20 |
21 | html.dark {
22 | --prism-foreground: #D4D4D4;
23 | --prism-background: #1E1E1E;
24 | --prism-comment: #758575;
25 | --prism-namespace: #444444;
26 | --prism-string: #CE9178;
27 | --prism-punctuation: #D4D4D4;
28 | --prism-literal: #36ACAA;
29 | --prism-keyword: #38A776;
30 | --prism-function: #DCDCAA;
31 | --prism-deleted: #9A050F;
32 | --prism-class: #4EC9B0;
33 | --prism-builtin: #D16969;
34 | --prism-property: #CE9178;
35 | --prism-regex: #AD502B;
36 | }
37 |
38 | body {
39 | margin: 0;
40 | font-family: 'Avenir', 'Helvetica', 'Arial', sans-serif;
41 | -webkit-font-smoothing: antialiased;
42 | -moz-osx-font-smoothing: grayscale;
43 | text-align: center;
44 | color: #2C3E50;
45 | }
46 |
--------------------------------------------------------------------------------
/src/assets/logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4 |
5 | ### [0.0.3](https://github.com/alibaba-aero/vue-boilerplate/compare/v0.0.2...v0.0.3) (2022-07-08)
6 |
7 |
8 | ### Features
9 |
10 | * **cypress:** add cypress for e2e and component testing ([#24](https://github.com/alibaba-aero/vue-boilerplate/issues/24)) ([a9b1d4f](https://github.com/alibaba-aero/vue-boilerplate/commit/a9b1d4f34f7332af52eafb815f976282a1d9ef4d))
11 | * **deployment:** add dockerfile ([#2](https://github.com/alibaba-aero/vue-boilerplate/issues/2)) ([b244d59](https://github.com/alibaba-aero/vue-boilerplate/commit/b244d598d33ded914b5b5361f1232740b94d0719))
12 | * **markdown:** add markdown support ([#27](https://github.com/alibaba-aero/vue-boilerplate/issues/27)) ([d188931](https://github.com/alibaba-aero/vue-boilerplate/commit/d18893150bf1ca17faf0dfa6c5c46989c75d37ec))
13 |
14 |
15 | ### Bug Fixes
16 |
17 | * **deps:** update dependency @vueuse/core to v8.9.0 ([#19](https://github.com/alibaba-aero/vue-boilerplate/issues/19)) ([f2bd2c5](https://github.com/alibaba-aero/vue-boilerplate/commit/f2bd2c56948884ded069c905f1ecf5708a3d10cf))
18 | * **deps:** update dependency @vueuse/core to v8.9.1 ([#25](https://github.com/alibaba-aero/vue-boilerplate/issues/25)) ([e7cf90c](https://github.com/alibaba-aero/vue-boilerplate/commit/e7cf90c319c13dd47e55f7bc771c84863f85f324))
19 | * **deps:** update dependency vue-router to v4.1.1 ([#14](https://github.com/alibaba-aero/vue-boilerplate/issues/14)) ([12da71c](https://github.com/alibaba-aero/vue-boilerplate/commit/12da71c82053c3bbfdc9c1a32ef27a9fab5c306a))
20 |
21 | ### [0.0.2](https://github.com/alibaba-aero/vue-boilerplate/compare/v0.0.1...v0.0.2) (2022-07-01)
22 |
23 | ### 0.0.1 (2022-07-01)
24 |
25 |
26 | ### Features
27 |
28 | * initialize project ([0633a85](https://github.com/alibaba-aero/vue-boilerplate/commit/0633a855d86b1b76b1e33ee99212b1c08e6a32af))
29 |
--------------------------------------------------------------------------------
/src/components/HelloWorld/HelloWorld.test.ts:
--------------------------------------------------------------------------------
1 | import { describe, expect, it, vi } from 'vitest'
2 | import type { MountingOptions } from '@vue/test-utils'
3 | import { createTestingPinia } from '@pinia/testing'
4 | import { fireEvent, render } from '@testing-library/vue'
5 |
6 | import Component from './HelloWorld.vue'
7 |
8 | const factory = (options?: MountingOptions) => render(Component, {
9 | global: {
10 | plugins: [createTestingPinia({ createSpy: vi.fn }), i18n],
11 | },
12 | ...options,
13 | })
14 |
15 | describe('HelloWorld', () => {
16 | it('shold mount correctly', async () => {
17 | const wrapper = factory({})
18 | expect(wrapper).toBeTruthy()
19 | wrapper.unmount()
20 | })
21 |
22 | it('shold add counter correctly', async () => {
23 | const wrapper = factory({})
24 | const { getByTestId } = wrapper
25 | const counterElement = getByTestId('counter')
26 | const counterPiniaElement = getByTestId('counter-pinia')
27 | const addElement = getByTestId('add-btn')
28 | const addPiniaElement = getByTestId('add-btn-pinia')
29 |
30 | expect(counterElement.innerHTML).toBe('Counter: 0')
31 | await fireEvent.click(addElement)
32 | expect(counterElement.innerHTML).toBe('Counter: 1')
33 |
34 | expect(counterPiniaElement.innerHTML).toBe('Counter Pinia: 0')
35 | await fireEvent.click(addPiniaElement)
36 | expect(counterPiniaElement.innerHTML).toBe('Counter Pinia: 1')
37 | wrapper.unmount()
38 | })
39 |
40 | it('shold change locale correctly', async () => {
41 | const wrapper = factory({})
42 | const { getByTestId } = wrapper
43 | const toggleElement = getByTestId('toggle-button')
44 | const localElement = getByTestId('local')
45 |
46 | expect(toggleElement.innerHTML).toBe('Button Change Locale')
47 | expect(localElement.innerHTML).toBe('Local')
48 | await fireEvent.click(toggleElement)
49 | expect(toggleElement.innerHTML).toBe('دکمه تغییر زبان')
50 | expect(localElement.innerHTML).toBe('محلی')
51 |
52 | wrapper.unmount()
53 | })
54 | })
55 |
--------------------------------------------------------------------------------
/src/components/HelloWorld/HelloWorld.vue:
--------------------------------------------------------------------------------
1 |
22 |
23 |
24 |
25 |
28 |
29 | {{ t('local') }}
30 |
31 |
32 |
33 |
34 | {{ t('couterPinia') }} {{ main.counter }}
35 |
36 |
39 |
40 |
41 | {{ t('counter') }} {{ count }}
42 |
43 |
46 |
47 | {{ t('postCssTest') }}
48 |
49 | {{ t('inner') }}
50 |
51 |
52 |
53 |
54 |
68 |
69 |
70 | {
71 | "en": {
72 | "local": "Local",
73 | "changeLocale": "Change Locale",
74 | "couterPinia": "Counter Pinia:",
75 | "addPinia": "Add pinia",
76 | "counter": "Counter:",
77 | "add": "Add",
78 | "postCssTest": "PostCSS Styling test",
79 | "inner": "Inner"
80 | },
81 | "fa": {
82 | "local": "محلی",
83 | "changeLocale": "تغییر زبان",
84 | "couterPinia": "شمارشگر پینیا:",
85 | "addPinia": "اضافه کردن پینیا",
86 | "counter": "شمارشگر:",
87 | "add": "اضافه کردن",
88 | "postCssTest": "PostCSS تست استایل",
89 | "inner": "درونی"
90 | }
91 | }
92 |
93 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "module",
3 | "name": "vuilerplate",
4 | "private": true,
5 | "version": "0.0.3",
6 | "scripts": {
7 | "build": "vue-tsc --noEmit && MODE=production vite-ssg build",
8 | "coverage": "vitest run --coverage",
9 | "dev": "vite",
10 | "lint:js": "eslint . --ext .js,.ts,.vue",
11 | "lint:style": "stylelint '**/*.{scss,css,vue}'",
12 | "lint": "pnpm lint:js && pnpm lint:style",
13 | "release:stg": "standard-version -s -a --prerelease beta && git push --follow-tags",
14 | "release:prod": "standard-version -s -a && git push --follow-tags",
15 | "preview": "vite preview",
16 | "test": "vitest",
17 | "test:e2e": "cypress open",
18 | "prepare": "husky install",
19 | "typecheck": "vue-tsc --noEmit"
20 | },
21 | "lint-staged": {
22 | "*.{js,ts,vue}": [
23 | "eslint --ext .js,.ts,.vue --fix",
24 | "pnpm vitest related --run"
25 | ],
26 | "*.{scss,vue}": "stylelint --fix"
27 | },
28 | "dependencies": {
29 | "@unocss/reset": "0.47.5",
30 | "@vueuse/core": "9.1.1",
31 | "@vueuse/head": "0.9.8",
32 | "@vueuse/schema-org": "1.0.2",
33 | "pinia": "2.0.22",
34 | "prism-theme-vars": "0.2.4",
35 | "vue": "3.2.40",
36 | "vue-i18n": "9.2.2",
37 | "vue-router": "4.1.5"
38 | },
39 | "devDependencies": {
40 | "@antfu/eslint-config": "0.27.0",
41 | "@iconify-json/carbon": "1.1.11",
42 | "@intlify/eslint-plugin-vue-i18n": "2.0.0",
43 | "@intlify/vite-plugin-vue-i18n": "6.0.3",
44 | "@pinia/testing": "0.0.14",
45 | "@testing-library/cypress": "8.0.7",
46 | "@testing-library/jest-dom": "5.16.5",
47 | "@testing-library/vue": "6.6.1",
48 | "@typescript-eslint/parser": "5.40.0",
49 | "@vitejs/plugin-vue": "3.1.0",
50 | "@vitejs/plugin-vue-jsx": "2.0.1",
51 | "@vue/test-utils": "2.1.0",
52 | "c8": "7.12.0",
53 | "critters": "0.0.16",
54 | "cypress": "10.9.0",
55 | "eslint": "8.27.0",
56 | "eslint-config-airbnb": "19.0.4",
57 | "eslint-config-airbnb-typescript": "17.0.0",
58 | "eslint-plugin-cypress": "2.12.1",
59 | "eslint-plugin-jsx-a11y": "6.6.1",
60 | "eslint-plugin-vue": "9.6.0",
61 | "happy-dom": "6.0.4",
62 | "husky": "8.0.2",
63 | "jsdom": "20.0.0",
64 | "lint-staged": "13.0.3",
65 | "markdown-it": "13.0.1",
66 | "markdown-it-prism": "2.3.0",
67 | "postcss": "8.4.17",
68 | "postcss-html": "1.5.0",
69 | "postcss-import": "14.1.0",
70 | "postcss-nested": "5.0.6",
71 | "postcss-url": "10.1.3",
72 | "rollup-plugin-visualizer": "5.8.3",
73 | "standard-version": "9.5.0",
74 | "stylelint": "14.13.0",
75 | "stylelint-config-recommended-vue": "1.4.0",
76 | "typescript": "4.8.4",
77 | "unocss": "0.45.26",
78 | "unplugin-auto-import": "0.11.2",
79 | "unplugin-vue-components": "0.22.8",
80 | "vite": "3.0.9",
81 | "vite-plugin-compression": "0.5.1",
82 | "vite-plugin-istanbul": "3.0.1",
83 | "vite-plugin-pages": "0.26.0",
84 | "vite-plugin-pwa": "0.13.1",
85 | "vite-plugin-vue-layouts": "0.7.0",
86 | "vite-plugin-vue-markdown": "0.21.1",
87 | "vite-ssg": "0.21.1",
88 | "vite-ssg-sitemap": "0.4.3",
89 | "vite-svg-loader": "3.6.0",
90 | "vitest": "0.23.4",
91 | "vue-eslint-parser": "9.1.0",
92 | "vue-tsc": "0.40.13"
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/.stylelintrc.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | extends: "stylelint-config-recommended-vue",
3 | rules: {
4 | "block-opening-brace-space-before": "always",
5 | "block-no-empty": true,
6 | "declaration-colon-space-after": "always",
7 | "max-empty-lines": 1,
8 | "color-no-invalid-hex": true,
9 | "font-family-no-duplicate-names": true,
10 | "function-calc-no-unspaced-operator": true,
11 | "string-no-newline": true,
12 | "unit-no-unknown": true,
13 | "property-no-unknown": true,
14 | "keyframe-declaration-no-important": true,
15 | "declaration-block-no-duplicate-properties": true,
16 | "declaration-colon-space-before": "never",
17 | "declaration-block-no-shorthand-property-overrides": true,
18 | "selector-pseudo-element-no-unknown": [true, {
19 | "ignorePseudoElements": ["deep"]
20 | }],
21 | "selector-type-no-unknown": true,
22 | "media-feature-name-no-unknown": true,
23 | "at-rule-no-unknown": [true, {
24 | "ignoreAtRules": [
25 | "/^use/",
26 | "/^include/",
27 | "/^extend/",
28 | "/^mixin/",
29 | "/^if/",
30 | "/^else/",
31 | "/^function/",
32 | "/^return/",
33 | "/^for/",
34 | "/^each/",
35 | "tailwind",
36 | "apply",
37 | "variants",
38 | "screen"
39 | ]
40 | }],
41 | "comment-no-empty": true,
42 | "no-duplicate-at-import-rules": true,
43 | "no-empty-source": true,
44 | "no-extra-semicolons": true,
45 | "no-invalid-double-slash-comments": true,
46 | "color-named": "always-where-possible",
47 | "shorthand-property-no-redundant-values": true,
48 | "declaration-block-no-redundant-longhand-properties": [true, {
49 | "ignoreShorthands": ["/flex-flow/"]
50 | }],
51 | "declaration-block-single-line-max-declarations": 1,
52 | "selector-max-empty-lines": 0,
53 | "color-hex-case": "upper",
54 | "font-family-name-quotes": "always-unless-keyword",
55 | "function-comma-space-after": "always",
56 | "function-max-empty-lines": 0,
57 | "function-whitespace-after": "always",
58 | "number-no-trailing-zeros": true,
59 | "string-quotes": "single",
60 | "length-zero-no-unit": true,
61 | "unit-case": "lower",
62 | "value-keyword-case": ["lower", {
63 | "ignoreKeywords": ["IranSans"],
64 | "ignoreProperties": ["font-family", "filter"]
65 | }],
66 | "value-list-comma-space-after": "always-single-line",
67 | "property-case": "lower",
68 | "declaration-bang-space-after": "never",
69 | "declaration-bang-space-before": "always",
70 | "declaration-empty-line-before": "never",
71 | "declaration-block-semicolon-newline-after": "always-multi-line",
72 | "declaration-block-semicolon-space-after": "always-single-line",
73 | "declaration-block-trailing-semicolon": "always",
74 | "block-closing-brace-empty-line-before": "never",
75 | "block-closing-brace-newline-after": ["always", {
76 | "ignoreAtRules": ["if", "else"]
77 | }],
78 | "block-closing-brace-newline-before": "always-multi-line",
79 | "block-closing-brace-space-before": "always-single-line",
80 | "block-opening-brace-space-after": "always-single-line",
81 | "selector-attribute-brackets-space-inside": "never",
82 | "selector-attribute-operator-space-after": "always",
83 | "selector-attribute-operator-space-before": "always",
84 | "selector-attribute-quotes": "always",
85 | "selector-combinator-space-after": "always",
86 | "selector-combinator-space-before": "always",
87 | "selector-descendant-combinator-no-non-space": true,
88 | "selector-pseudo-class-case": "lower",
89 | "selector-pseudo-class-parentheses-space-inside": "never",
90 | "selector-pseudo-element-case": "lower",
91 | "selector-pseudo-element-colon-notation": "double",
92 | "selector-type-case": "lower",
93 | "selector-list-comma-space-after": "always-single-line",
94 | "selector-list-comma-space-before": "never",
95 | "media-feature-colon-space-after": "always",
96 | "media-feature-colon-space-before": "never",
97 | "media-feature-name-case": "lower",
98 | "media-feature-parentheses-space-inside": "never",
99 | "media-feature-range-operator-space-after": "always",
100 | "media-feature-range-operator-space-before": "always",
101 | "media-query-list-comma-newline-after": "never-multi-line",
102 | "at-rule-name-case": "lower",
103 | "at-rule-name-space-after": "always",
104 | "at-rule-semicolon-newline-after": "always",
105 | "comment-whitespace-inside": "always",
106 | "indentation": 2,
107 | "no-eol-whitespace": true,
108 | "no-missing-end-of-source-newline": true,
109 | "no-empty-first-line": true,
110 | "comment-empty-line-before": "always",
111 | "number-leading-zero": "always"
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/vite.config.ts:
--------------------------------------------------------------------------------
1 | // @ts-ignore
2 | import path from 'path'
3 | import { defineConfig } from 'vitest/config'
4 | import Vue from '@vitejs/plugin-vue'
5 | import Layouts from 'vite-plugin-vue-layouts'
6 | import { VitePWA } from 'vite-plugin-pwa'
7 | import Pages from 'vite-plugin-pages'
8 | import Components from 'unplugin-vue-components/vite'
9 | import AutoImport from 'unplugin-auto-import/vite'
10 | import VueJsx from '@vitejs/plugin-vue-jsx'
11 | import { visualizer as Visualizer } from 'rollup-plugin-visualizer'
12 | import ViteCompression from 'vite-plugin-compression'
13 | import Markdown from 'vite-plugin-vue-markdown'
14 | import Prism from 'markdown-it-prism'
15 | import VueI18n from '@intlify/vite-plugin-vue-i18n'
16 | import SvgLoader from 'vite-svg-loader'
17 | import Unocss from 'unocss/vite'
18 | import generateSitemap from 'vite-ssg-sitemap'
19 | import istanbul from 'vite-plugin-istanbul';
20 |
21 | function removeDataTestAttrs(node: any) {
22 | if (node.type === 1 /* NodeTypes.ELEMENT */) {
23 | node.props = node.props.filter((prop: any) =>
24 | prop.type === 6 /* NodeTypes.ATTRIBUTE */
25 | ? prop.name !== 'data-testid'
26 | : true
27 | )
28 | }
29 | }
30 | // https://github.com/antfu/unplugin-icons
31 | // for our icons
32 |
33 | // https://vitejs.dev/config/
34 | export default defineConfig(({ command }) => ({
35 | resolve:{
36 | alias:{
37 | '@' : path.resolve(__dirname, './src'),
38 | '@/utils': path.resolve(__dirname, './src/utils')
39 | },
40 | },
41 | build: {
42 | sourcemap: true
43 | },
44 | plugins: [
45 | Vue({
46 | include: [/\.vue$/, /\.md$/],
47 | reactivityTransform: true,
48 | template: {
49 | compilerOptions: {
50 | nodeTransforms: process.env.MODE === 'production' ? [removeDataTestAttrs] : [],
51 | }
52 | }
53 | }),
54 | Pages({
55 | extensions: ['vue', 'md'],
56 | }),
57 | Components({
58 | extensions: ['vue', 'md', 'tsx', 'jsx'],
59 | include: [/\.vue$/, /\.vue\?vue/, /\.md$/],
60 | dts: 'src/components.d.ts',
61 | }),
62 | Layouts(),
63 | VitePWA({
64 | registerType: 'autoUpdate',
65 | includeAssets: ['favicon.svg', 'safari-pinned-tab.svg'],
66 | manifest: {
67 | name: 'Alibaba Travels',
68 | short_name: 'Alibaba',
69 | theme_color: '#FDB713',
70 | icons: [
71 | {
72 | src: '/android-chrome-192x192.png',
73 | sizes: '192x192',
74 | type: 'image/png',
75 | },
76 | {
77 | src: '/android-chrome-512x512.png',
78 | sizes: '512x512',
79 | type: 'image/png',
80 | },
81 | {
82 | src: '/maskable-icon-x512.png',
83 | sizes: '512x512',
84 | type: 'image/png',
85 | purpose: 'maskable',
86 | },
87 | {
88 | src: '/maskable-icon-x192.png',
89 | sizes: '192x192',
90 | type: 'image/png',
91 | purpose: 'maskable',
92 | },
93 | ],
94 | },
95 | }),
96 | AutoImport({
97 | imports: [
98 | 'vue',
99 | 'vue/macros',
100 | 'vue-router',
101 | '@vueuse/head',
102 | '@vueuse/core',
103 | 'pinia',
104 | 'vue-i18n',
105 | // 'vitest',
106 | ],
107 | dts: 'src/auto-imports.d.ts',
108 | dirs: [
109 | 'src/composables',
110 | 'src/store',
111 | 'src/utils'
112 | ],
113 | vueTemplate: true,
114 | }),
115 | VueJsx({ optimize: true }),
116 | ...(command === 'build'
117 | ? [Visualizer({ filename: `stats.html` })]
118 | : []
119 | ),
120 | ...(process.env.COMPRESS !== '0'
121 | ? [ViteCompression({}), ViteCompression({ algorithm: 'brotliCompress', ext: '.br' })]
122 | : []
123 | ),
124 | Markdown({
125 | wrapperClasses: 'markdown-wrapper',
126 | headEnabled: true,
127 | markdownItOptions: {
128 | html: true,
129 | linkify: true,
130 | typographer: true,
131 | },
132 | markdownItSetup(md) {
133 | md.use(Prism)
134 | },
135 | }),
136 | VueI18n({
137 | include: path.resolve(__dirname, './src/locales/**'),
138 | }),
139 | SvgLoader({
140 | svgo: true,
141 | svgoConfig: {
142 | multipass: true,
143 | plugins: [
144 | {
145 | name: 'preset-default',
146 | params: {
147 | overrides: {
148 | inlineStyles: {
149 | onlyMatchedOnce: false,
150 | },
151 | },
152 | },
153 | },
154 | ],
155 | }
156 | }),
157 | Unocss(),
158 | istanbul({
159 | include: 'src/*',
160 | exclude: ['node_modules', 'test/'],
161 | extension: [ '.js', '.ts', '.vue' , '.tsx'],
162 | requireEnv: true,
163 | }),
164 | ],
165 | server: {
166 | port: 5173,
167 | host: '127.0.0.1'
168 | },
169 | ssgOptions: {
170 | script: 'async',
171 | formatting: 'minify',
172 | onFinished() { generateSitemap() },
173 | },
174 | ssr: {
175 | // TODO: workaround until they support native ESM
176 | noExternal: ['workbox-window', /vue-i18n/],
177 | },
178 | test: {
179 | // environment: 'jsdom',
180 | environment: 'happy-dom',
181 | deps: {
182 | inline: ['@vue', '@vueuse', 'vue-demi'],
183 | },
184 | outputFile: {
185 | json: './coverage/final.json',
186 | junit: './coverage/junit.xml',
187 | },
188 | reporters: ['verbose', 'junit', 'json'],
189 | coverage: {
190 | clean: false,
191 | },
192 | },
193 | }))
194 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Alibaba Travels Vue 3 starter package with vite
2 | - Check Vitesse
3 |
4 |
5 | ## Features
6 |
7 | - ⚡️ [Vue 3](https://github.com/vuejs/core), [Vite 2](https://github.com/vitejs/vite), [pnpm](https://pnpm.io/), [ESBuild](https://github.com/evanw/esbuild)
8 |
9 | - 🗂 [File based routing](./src/pages)
10 |
11 | - 📑 [Layout system](./src/layouts)
12 |
13 | - 📦 [Components auto importing](./src/components)
14 |
15 | - 📥 [APIs auto importing](https://github.com/antfu/unplugin-auto-import) - use Composition API and others directly
16 |
17 | - 📐 [JSX Support](https://www.npmjs.com/package/@vitejs/plugin-vue-jsx)
18 |
19 | - 🍍 [State Management via Pinia](https://pinia.vuejs.org/)
20 |
21 | - ⚖️ [Rollup Visualizer](https://github.com/btd/rollup-plugin-visualizer)
22 |
23 | - 🗜️ [File compression](https://github.com/vbenjs/vite-plugin-compression) - Use `gzip` or `brotli` to compress resources.
24 |
25 | - 🌍 [Vue i18n](https://github.com/intlify/vue-i18n-next)
26 |
27 | - 📲 [PWA](https://github.com/antfu/vite-plugin-pwa)
28 |
29 | - 📩 [Markdown Support](https://github.com/antfu/vite-plugin-md)
30 |
31 | - 🖨 Static-site generation (SSG) via [vite-ssg](https://github.com/antfu/vite-ssg)
32 |
33 | - 🦔 Critical CSS via [critters](https://github.com/GoogleChromeLabs/critters)
34 |
35 | - 💡 [PostCSS](https://postcss.org/)
36 |
37 | - ⚙️ Unit testing with [Vitest](https://github.com/vitest-dev/vitest)
38 |
39 | - ⚙️ E2E and component testing with [Cypress](https://www.cypress.io/)
40 |
41 | - 🦾 TypeScript
42 |
43 | - 🔥 Use the [new `