@component-hook/create-app 1.5.0 → 1.6.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.
Files changed (107) hide show
  1. package/README.md +1 -0
  2. package/dist/index.d.mts +1 -1
  3. package/dist/index.mjs +86 -80
  4. package/package.json +12 -12
  5. package/template-react/.vscode/extensions.json +9 -0
  6. package/template-react/.vscode/settings.json +18 -0
  7. package/template-react/README.md.art +85 -0
  8. package/template-react/e2e/home.spec.ts +40 -0
  9. package/template-react/eslint.config.js +18 -0
  10. package/template-react/index.html.art +13 -0
  11. package/template-react/lint-staged.config.js +6 -0
  12. package/template-react/package.json +70 -0
  13. package/template-react/public/vite.svg +1 -0
  14. package/template-react/src/App.tsx +6 -0
  15. package/template-react/src/assets/svg-icons/react.svg +1 -0
  16. package/template-react/src/components/common/index.ts +1 -0
  17. package/template-react/src/components/common/svg-icon/index.ts +1 -0
  18. package/template-react/src/components/common/svg-icon/src/index.tsx +23 -0
  19. package/template-react/src/main.tsx +26 -0
  20. package/template-react/src/mocks/browser.ts +4 -0
  21. package/template-react/src/mocks/handlers/index.ts +1 -0
  22. package/template-react/src/mocks/server.ts +4 -0
  23. package/template-react/src/pages/home/components/hello-world/index.test.tsx +45 -0
  24. package/template-react/src/pages/home/components/hello-world/index.tsx +49 -0
  25. package/template-react/src/pages/home/index.module.css +8 -0
  26. package/template-react/src/pages/home/index.test.tsx +19 -0
  27. package/template-react/src/pages/home/index.tsx +37 -0
  28. package/template-react/src/plugins/i18n/index.ts +19 -0
  29. package/template-react/src/plugins/i18n/locales/en-US.json +3 -0
  30. package/template-react/src/plugins/i18n/locales/zh-TW.json +3 -0
  31. package/template-react/src/router/index.tsx +22 -0
  32. package/template-react/src/stores/constants.ts +1 -0
  33. package/template-react/src/stores/index.ts +1 -0
  34. package/template-react/src/stores/middleware.ts +17 -0
  35. package/template-react/src/stores/modules/config.ts +27 -0
  36. package/template-react/src/styles/base.css +68 -0
  37. package/template-react/src/styles/common/all.css +1 -0
  38. package/template-react/src/styles/common/button.css +26 -0
  39. package/template-react/src/styles/index.css +3 -0
  40. package/template-react/src/styles/tailwind.css +14 -0
  41. package/template-react/src/test-utils/index.tsx +15 -0
  42. package/template-react/src/vite-env.d.ts +9 -0
  43. package/template-react/tsconfig.app.json +32 -0
  44. package/template-react/tsconfig.vitest.json +10 -0
  45. package/template-react/vite.config.ts +40 -0
  46. package/template-react/vitest.config.ts +18 -0
  47. package/template-react/vitest.setup.ts +13 -0
  48. package/template-shared/.browserslistrc +10 -0
  49. package/template-shared/.github/actions/setup-environment/action.yml +21 -0
  50. package/template-shared/.github/renovate.json +14 -0
  51. package/template-shared/.github/workflows/ci.yml +22 -0
  52. package/template-shared/.github/workflows/deploy.yml +27 -0
  53. package/template-shared/.github/workflows/preview.yml +17 -0
  54. package/template-shared/.gitlab/setup.yml +18 -0
  55. package/template-shared/.husky/commit-msg +1 -0
  56. package/template-shared/.husky/pre-commit +1 -0
  57. package/{LICENSE → template-shared/LICENSE} +1 -1
  58. package/template-shared/_gitignore +32 -0
  59. package/template-shared/_gitlab-ci.yml +22 -0
  60. package/template-shared/commitlint.config.js +3 -0
  61. package/template-shared/playwright.config.ts +49 -0
  62. package/template-shared/postcss.config.js +15 -0
  63. package/template-shared/prettier.config.js +13 -0
  64. package/template-shared/scripts/build-info/index.ts +21 -0
  65. package/template-shared/tsconfig.json +14 -0
  66. package/template-shared/tsconfig.node.json +12 -0
  67. package/template-vue/.vscode/extensions.json +10 -0
  68. package/template-vue/.vscode/settings.json +18 -0
  69. package/template-vue/README.md.art +81 -0
  70. package/template-vue/e2e/home.spec.ts +59 -0
  71. package/template-vue/eslint.config.js +18 -0
  72. package/template-vue/index.html.art +28 -0
  73. package/template-vue/lint-staged.config.js +6 -0
  74. package/template-vue/package.json +69 -0
  75. package/template-vue/public/vite.svg +1 -0
  76. package/template-vue/src/App.vue +7 -0
  77. package/template-vue/src/assets/svg-icons/vue.svg +1 -0
  78. package/template-vue/src/components/common/index.ts +1 -0
  79. package/template-vue/src/components/common/svg-icon/index.ts +1 -0
  80. package/template-vue/src/components/common/svg-icon/src/index.vue +29 -0
  81. package/template-vue/src/locales/en-US.json +3 -0
  82. package/template-vue/src/locales/zh-TW.json +3 -0
  83. package/template-vue/src/main.ts +21 -0
  84. package/template-vue/src/mocks/browser.ts +4 -0
  85. package/template-vue/src/mocks/handlers/index.ts +1 -0
  86. package/template-vue/src/mocks/server.ts +4 -0
  87. package/template-vue/src/pages/home/components/HelloWorld.test.ts +57 -0
  88. package/template-vue/src/pages/home/components/HelloWorld.vue +54 -0
  89. package/template-vue/src/pages/home/index.test.ts +17 -0
  90. package/template-vue/src/pages/home/index.vue +46 -0
  91. package/template-vue/src/plugins/i18n.ts +11 -0
  92. package/template-vue/src/router/index.ts +23 -0
  93. package/template-vue/src/stores/constants.ts.art +1 -0
  94. package/template-vue/src/stores/index.ts +15 -0
  95. package/template-vue/src/stores/modules/config.ts +20 -0
  96. package/template-vue/src/styles/base.css +59 -0
  97. package/template-vue/src/styles/common/all.css +1 -0
  98. package/template-vue/src/styles/common/button.css +15 -0
  99. package/template-vue/src/styles/index.css +3 -0
  100. package/template-vue/src/styles/tailwind.css +1 -0
  101. package/template-vue/src/test-utils/index.ts +33 -0
  102. package/template-vue/src/vite-env.d.ts +9 -0
  103. package/template-vue/tsconfig.app.json +12 -0
  104. package/template-vue/tsconfig.vitest.json +10 -0
  105. package/template-vue/vite.config.ts +46 -0
  106. package/template-vue/vitest.config.ts +18 -0
  107. package/template-vue/vitest.setup.ts +12 -0
@@ -0,0 +1 @@
1
+ npx --no -- commitlint --edit ${1}
@@ -0,0 +1 @@
1
+ npx lint-staged
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2023 Tzuyi
3
+ Copyright (c)
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -0,0 +1,32 @@
1
+ # Logs
2
+ logs
3
+ *.log
4
+ npm-debug.log*
5
+ yarn-debug.log*
6
+ yarn-error.log*
7
+ pnpm-debug.log*
8
+ lerna-debug.log*
9
+
10
+ node_modules
11
+ dist
12
+ dist-ssr
13
+ *.local
14
+ .env
15
+
16
+ # Editor directories and files
17
+ .idea
18
+ .DS_Store
19
+ *.suo
20
+ *.ntvs*
21
+ *.njsproj
22
+ *.sln
23
+ *.sw?
24
+
25
+ # Test reports
26
+ coverage
27
+ /test-results/
28
+ /playwright-report/
29
+ /playwright/.cache/
30
+
31
+ # Visualizer
32
+ stats.html
@@ -0,0 +1,22 @@
1
+ stages:
2
+ - test
3
+ # - deploy
4
+
5
+ include:
6
+ - local: .gitlab/setup.yml
7
+
8
+ run_test:
9
+ stage: test
10
+ image: mcr.microsoft.com/playwright:focal
11
+ script:
12
+ - npx playwright install --with-deps
13
+ - pnpm test:unit
14
+ - pnpm test:ci-e2e
15
+ rules:
16
+ - if: $CI_COMMIT_BRANCH
17
+ changes:
18
+ - 'src/**'
19
+ - pnpm-lock.yaml
20
+ - package.json
21
+ - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
22
+ - when: manual
@@ -0,0 +1,3 @@
1
+ export default {
2
+ extends: ['@commitlint/config-conventional'],
3
+ };
@@ -0,0 +1,49 @@
1
+ import { defineConfig, devices } from '@playwright/test';
2
+
3
+ export default defineConfig({
4
+ testDir: './e2e',
5
+ /* If gets stuck during the test, it will fail if it exceeds the timeout time. */
6
+ timeout: 30 * 1000,
7
+ fullyParallel: true,
8
+ /* Fail the build on CI if you accidentally left test.only in the source code. */
9
+ forbidOnly: !!process.env.CI,
10
+ /* Retry on CI only */
11
+ retries: process.env.CI ? 2 : 0,
12
+ /* Opt out of parallel tests on CI. */
13
+ workers: process.env.CI ? 1 : undefined,
14
+ reporter: 'html',
15
+ use: {
16
+ baseURL: 'http://localhost:5173',
17
+ trace: 'on-first-retry',
18
+ },
19
+ webServer: {
20
+ command: 'pnpm dev:mock',
21
+ port: 5173,
22
+ reuseExistingServer: !process.env.CI,
23
+ },
24
+ projects: [
25
+ {
26
+ name: 'chromium',
27
+ use: {
28
+ browserName: 'chromium',
29
+ ...devices['Macbook Pro'],
30
+ },
31
+ },
32
+
33
+ {
34
+ name: 'firefox',
35
+ use: {
36
+ browserName: 'firefox',
37
+ ...devices['Macbook 11'],
38
+ },
39
+ },
40
+
41
+ {
42
+ name: 'webkit',
43
+ use: {
44
+ browserName: 'webkit',
45
+ ...devices['iPhone SE'],
46
+ },
47
+ },
48
+ ],
49
+ });
@@ -0,0 +1,15 @@
1
+ import cssnano from 'cssnano';
2
+ import postcssPresetEnv from 'postcss-preset-env';
3
+ import postcssPxtorem from 'postcss-pxtorem';
4
+
5
+ export default {
6
+ plugins: [
7
+ postcssPresetEnv({ stage: 3 }),
8
+ postcssPxtorem({
9
+ rootValue: 16,
10
+ propList: ['*'],
11
+ selectorBlackList: ['norem'],
12
+ }),
13
+ ...(process.env.NODE_ENV === 'production' ? [cssnano({ preset: 'default' })] : []),
14
+ ],
15
+ };
@@ -0,0 +1,13 @@
1
+ /** @type {import('prettier').RequiredOptions} */
2
+
3
+ export default {
4
+ $schema: 'https://json.schemastore.org/prettierrc',
5
+ singleQuote: true,
6
+ semi: true,
7
+ endOfLine: 'lf',
8
+ printWidth: 120,
9
+ proseWrap: 'preserve',
10
+ arrowParens: 'avoid',
11
+ singleAttributePerLine: true,
12
+ plugins: ['prettier-plugin-tailwindcss'],
13
+ };
@@ -0,0 +1,21 @@
1
+ import { execFileSync } from 'node:child_process';
2
+ import os from 'node:os';
3
+ import packageJson from '../../package.json' with { type: 'json' };
4
+
5
+ const platform = os.platform();
6
+ const git = platform === 'win32' ? String.raw`C:\Program Files\Git\bin\git.exe` : '/usr/bin/git';
7
+ let hash = 'unknown';
8
+
9
+ try {
10
+ hash = execFileSync(git, ['rev-parse', 'HEAD']).toString().trim().slice(0, 7);
11
+ } catch {
12
+ hash = 'no-git-detected';
13
+ }
14
+
15
+ process.env.VITE_APP_VERSION = packageJson.version;
16
+ process.env.VITE_APP_LAST_COMMIT_HASH = hash;
17
+ process.env.VITE_APP_BUILD_EPOCH = Date.now().toString();
18
+
19
+ if (process.env.MOCK) {
20
+ process.env.VITE_APP_MOCK = 'service-worker';
21
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "references": [
3
+ {
4
+ "path": "./tsconfig.node.json"
5
+ },
6
+ {
7
+ "path": "./tsconfig.app.json"
8
+ },
9
+ {
10
+ "path": "./tsconfig.vitest.json"
11
+ }
12
+ ],
13
+ "files": []
14
+ }
@@ -0,0 +1,12 @@
1
+ {
2
+ "extends": "@tsconfig/node24/tsconfig.json",
3
+ "compilerOptions": {
4
+ "composite": true,
5
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
6
+ "module": "ESNext",
7
+ "moduleResolution": "bundler",
8
+ "types": ["node"],
9
+ "noEmit": true
10
+ },
11
+ "include": ["vite.config.ts", "package.json", "vitest.config.ts", "playwright.config.ts", "scripts/**/*.ts"]
12
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "recommendations": [
3
+ "vue.volar",
4
+ "bradlc.vscode-tailwindcss",
5
+ "esbenp.prettier-vscode",
6
+ "csstools.postcss",
7
+ "cpylua.language-postcss",
8
+ "streetsidesoftware.code-spell-checker"
9
+ ]
10
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "editor.tabSize": 2,
3
+ "editor.formatOnSave": true,
4
+ "editor.defaultFormatter": "esbenp.prettier-vscode",
5
+
6
+ "[json]": {
7
+ "editor.defaultFormatter": "esbenp.prettier-vscode"
8
+ },
9
+
10
+ "debug.javascript.autoAttachFilter": "smart",
11
+
12
+ "typescript.tsdk": "node_modules/typescript/lib",
13
+
14
+ "workbench.editor.splitInGroupLayout": "vertical",
15
+ "terminal.integrated.shellIntegration.enabled": true,
16
+
17
+ "cSpell.words": ["dotenv", "pinia", "persistedstate", "unplugin", "Sonarjs", "typecheck", "pxtorem", "norem"]
18
+ }
@@ -0,0 +1,81 @@
1
+ # {{projectName}}
2
+
3
+ This project is built with [vue3](https://vuejs.org/) + [vite](https://vite.dev/), using [pnpm](https://pnpm.io/) for package management and [pinia](https://pinia.vuejs.org/) for state management.
4
+
5
+ ## Features
6
+
7
+ - **Development Experience**: Written in [typeScript](https://www.typescriptlang.org/), styled with [tailwindcss](https://tailwindcss.com/), and structured with [vue-router](https://router.vuejs.org/), and [vue-i18n](https://vue-i18n.intlify.dev/). Supports SVGs ([vite-plugin-svg-icons](https://github.com/vbenjs/vite-plugin-svg-icons)).
8
+ - **API & Mocking**: Handles requests with [axios](https://axios-http.com/docs/intro) and mocks APIs using [msw](https://mswjs.io/).
9
+ - **Code Quality**: Enforces standards with [eslint](https://eslint.org/) and [prettier](https://prettier.io/), with [husky](https://www.npmjs.com/package/husky), [commitlint](https://commitlint.js.org/#/), and [lint-staged](https://github.com/okonet/lint-staged) for commit validation.
10
+ - **Testing**: Uses [vitest](https://vitest.dev/) + [testing-library](https://testing-library.com/) for unit testing and [playwright](https://playwright.dev/) for E2E testing.
11
+ - **Optimization**: Compresses CSS with [cssnano](https://cssnano.github.io/cssnano/), converts units with [postcss-pxtorem](https://www.npmjs.com/package/postcss-pxtorem), convert modern CSS into something most browsers can understand with [postcss-preset-env](https://www.npmjs.com/package/postcss-preset-env), and analyzes assets with [rollup-plugin-visualizer](https://github.com/btd/rollup-plugin-visualizer).
12
+ {{ciContent}}
13
+
14
+ ## Code Features / Opinions
15
+
16
+ - Project root aliased as `@` to `<project_root>/src`
17
+ - Store persistedstate use [pinia-plugin-persistedstate](https://www.npmjs.com/package/pinia-plugin-persistedstate)
18
+ - ESlint plugin use [@component-hook/eslint-plugin](https://www.npmjs.com/package/@component-hook/eslint-plugin?activeTab=readme)
19
+ - if encounter npx: command not found, can execute `ln -s $(which npx) /usr/local/bin/npx` in zsh
20
+ - Predefined and fully typed global variables:
21
+ - `VITE_APP_VERSION` is read from `package.json` version at build time
22
+ - `VITE_APP_LAST_COMMIT_HASH` is last commit hash at build time
23
+ - `VITE_APP_BUILD_EPOCH` is populated as `Date.now()` at build time
24
+ - `VITE_APP_MOCK` is use mock environment
25
+
26
+ ## Project Files
27
+
28
+ ```text
29
+ e2e/*
30
+ src/
31
+ ├── assets/*
32
+ │ └── svg-icons
33
+ │ └── vue.svg
34
+ ├── components/
35
+ │ └── common
36
+ │ ├── svg-icon/
37
+ │ │ ├── src
38
+ │ │ │ └── index.vue
39
+ │ │ └── index.ts
40
+ │ └── index.ts
41
+ ├── constants/*
42
+ ├── hooks/*
43
+ ├── locales/
44
+ │ ├── en-US.json
45
+ │ └── zh-CN.json
46
+ ├── mocks/
47
+ │ ├── handlers/*
48
+ │ │ ├── modules/*
49
+ │ │ └── index.ts
50
+ │ │── browser.ts
51
+ │ └── server.ts
52
+ ├── pages/
53
+ │ └── home/
54
+ │ ├── components
55
+ │ │ ├── HelloWorld.test.ts
56
+ │ │ └── HelloWorld.vue
57
+ │ ├── index.test.ts
58
+ │ └── index.vue
59
+ ├── plugins/
60
+ │ └── i18n.ts
61
+ ├── router/
62
+ │ └── index.ts
63
+ ├── stores/
64
+ │ ├── modules
65
+ │ │ └── config.ts
66
+ │ └── index.ts
67
+ ├── styles/
68
+ │ ├── common/
69
+ | │ ├── all.css
70
+ | │ └── button.css
71
+ │ ├── base.css
72
+ │ ├── index.css
73
+ │ └── tailwind.css
74
+ ├── test-utils/
75
+ │ └── index.ts
76
+ ├── types/*
77
+ ├── utils/*
78
+ ├── App.vue
79
+ ├── vite-env.d.ts
80
+ └── main.ts
81
+ ```
@@ -0,0 +1,59 @@
1
+ import { expect, test } from '@playwright/test';
2
+
3
+ test.beforeEach(async ({ page }) => {
4
+ await page.goto('/');
5
+ });
6
+
7
+ test('click Vite logo open Vite official website blank tab', async ({ page }) => {
8
+ const link = page.getByRole('link', { name: /vite logo/i });
9
+
10
+ await expect(link).toBeVisible();
11
+ const [popup] = await Promise.all([page.waitForEvent('popup'), link.evaluate((node: HTMLElement) => node.click())]);
12
+
13
+ await popup.waitForLoadState();
14
+ await expect(popup).toHaveTitle('Vite | Next Generation Frontend Tooling');
15
+ });
16
+
17
+ test('click Vue logo open Vue official website blank tab', async ({ page }) => {
18
+ const link = page.getByLabel(/vue link/i);
19
+
20
+ await expect(link).toBeVisible();
21
+ const [popup] = await Promise.all([page.waitForEvent('popup'), link.evaluate((node: HTMLElement) => node.click())]);
22
+
23
+ await popup.waitForLoadState();
24
+ await expect(popup).toHaveTitle('Vue.js - The Progressive JavaScript Framework | Vue.js');
25
+ });
26
+
27
+ test('homepage count button interact', async ({ page }) => {
28
+ await page.getByRole('button', { name: 'count is 0' }).click();
29
+ await expect(page.getByRole('button', { name: 'count is 1' })).toBeVisible();
30
+ await page.getByRole('button', { name: 'count is 1' }).click();
31
+ await expect(page.getByRole('button', { name: 'count is 2' })).toBeVisible();
32
+ });
33
+
34
+ test('locale change interact', async ({ page }) => {
35
+ await page.getByRole('button', { name: 'English' }).click();
36
+ await expect(page.getByRole('button', { name: '中文' })).toBeVisible();
37
+ await page.getByRole('button', { name: '中文' }).click();
38
+ await expect(page.getByRole('button', { name: 'English' })).toBeVisible();
39
+ });
40
+
41
+ test('click create-vue link open Vue quick start blank tab', async ({ page }) => {
42
+ const link = page.getByRole('link', { name: 'create-vue' });
43
+
44
+ await expect(link).toBeVisible();
45
+ const [popup] = await Promise.all([page.waitForEvent('popup'), link.evaluate((node: HTMLElement) => node.click())]);
46
+
47
+ await popup.waitForLoadState();
48
+ await expect(popup).toHaveTitle('Quick Start | Vue.js');
49
+ });
50
+
51
+ test('click Volar link open language-tools github blank tab', async ({ page }) => {
52
+ const link = page.getByRole('link', { name: 'Volar' });
53
+
54
+ await expect(link).toBeVisible();
55
+ const [popup] = await Promise.all([page.waitForEvent('popup'), link.evaluate((node: HTMLElement) => node.click())]);
56
+
57
+ await popup.waitForLoadState();
58
+ await expect(popup).toHaveTitle(/vuejs\/language-tools/);
59
+ });
@@ -0,0 +1,18 @@
1
+ import componentHookPlugin from '@component-hook/eslint-plugin';
2
+
3
+ export default [
4
+ ...componentHookPlugin.configs.basic,
5
+ ...componentHookPlugin.configs.vue,
6
+ componentHookPlugin.configs.prettier,
7
+ ...componentHookPlugin.configs.sonarjs,
8
+ componentHookPlugin.configs.security,
9
+ ...componentHookPlugin.configs.markdown,
10
+ {
11
+ files: ['**/*.test.[jt]s?(x)'],
12
+ ...componentHookPlugin.configs['testing-library/vue'],
13
+ },
14
+ {
15
+ files: ['**/e2e/**/*.spec.[jt]s?(x)'],
16
+ ...componentHookPlugin.configs.playwright,
17
+ },
18
+ ];
@@ -0,0 +1,28 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <link
6
+ rel="icon"
7
+ type="image/svg+xml"
8
+ href="/vite.svg"
9
+ />
10
+ <meta
11
+ name="viewport"
12
+ content="width=device-width, initial-scale=1.0"
13
+ />
14
+ <title>{{projectName}}</title>
15
+ </head>
16
+ <body>
17
+ <div id="app"></div>
18
+ <script
19
+ type="module"
20
+ src="/src/main.ts"
21
+ ></script>
22
+ <noscript>
23
+ <h1>Opinionated, production ready template for Vite and Vue 3</h1>
24
+
25
+ <p>This site requires JavaScript to work.</p>
26
+ </noscript>
27
+ </body>
28
+ </html>
@@ -0,0 +1,6 @@
1
+ /** @type {import('lint-staged').Configuration} */
2
+
3
+ export default {
4
+ '*.{ts,vue}': () => 'pnpm typecheck',
5
+ '*.{ts,js,vue,json,yml}': () => 'pnpm lint',
6
+ };
@@ -0,0 +1,69 @@
1
+ {
2
+ "name": "vue-starter",
3
+ "version": "0.0.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "vite",
8
+ "dev:mock": "cross-env MOCK=true vite",
9
+ "build": "pnpm typecheck && vite build",
10
+ "lint": "eslint --fix .",
11
+ "test:unit": "vitest --coverage",
12
+ "test:e2e": "playwright test --headed",
13
+ "test:ui-e2e": "playwright test --ui",
14
+ "test:ci-e2e": "playwright test",
15
+ "typecheck": "vue-tsc --noEmit",
16
+ "prepare": "husky",
17
+ "preview": "vite preview"
18
+ },
19
+ "dependencies": {
20
+ "axios": "^1.20.0",
21
+ "pinia": "^4.0.3",
22
+ "pinia-plugin-persistedstate": "^4.7.1",
23
+ "vue": "^3.5.43",
24
+ "vue-i18n": "^11.4.12",
25
+ "vue-router": "^5.3.1"
26
+ },
27
+ "devDependencies": {
28
+ "@component-hook/eslint-plugin": "^1.5.1",
29
+ "@intlify/unplugin-vue-i18n": "^11.2.5",
30
+ "@playwright/test": "^1.63.0",
31
+ "@tailwindcss/vite": "^4.3.3",
32
+ "@testing-library/jest-dom": "^7.0.1",
33
+ "@testing-library/user-event": "^14.6.7",
34
+ "@testing-library/vue": "^8.1.0",
35
+ "@tsconfig/node24": "^24.0.5",
36
+ "@types/node": "^24.13.5",
37
+ "@vitejs/plugin-vue": "^6.0.9",
38
+ "@vitest/coverage-v8": "^5.0.1",
39
+ "@vue/tsconfig": "^0.9.1",
40
+ "cross-env": "^10.1.0",
41
+ "cssnano": "^9.0.5",
42
+ "eslint": "^9.39.5",
43
+ "fast-glob": "^3.3.3",
44
+ "jsdom": "^30.1.0",
45
+ "msw": "^2.15.0",
46
+ "postcss": "^8.5.28",
47
+ "postcss-preset-env": "^11.5.3",
48
+ "postcss-pxtorem": "^6.1.0",
49
+ "prettier": "^3.9.8",
50
+ "prettier-plugin-tailwindcss": "^0.8.1",
51
+ "rollup-plugin-visualizer": "^7.1.1",
52
+ "tailwindcss": "^4.3.3",
53
+ "typescript": "^6.0.3",
54
+ "vite": "^8.3.0",
55
+ "vite-plugin-svg-icons": "^2.0.1",
56
+ "vitest": "^5.0.1",
57
+ "vue-tsc": "^3.3.11"
58
+ },
59
+ "optionalDependencies": {
60
+ "@commitlint/cli": "^21.2.2",
61
+ "@commitlint/config-conventional": "^21.2.2",
62
+ "husky": "^9.1.7",
63
+ "lint-staged": "^17.5.1"
64
+ },
65
+ "packageManager": "pnpm@12.4.2",
66
+ "msw": {
67
+ "workerDirectory": "public"
68
+ }
69
+ }
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
@@ -0,0 +1,7 @@
1
+ <script setup lang="ts"></script>
2
+
3
+ <template>
4
+ <router-view />
5
+ </template>
6
+
7
+ <style scoped></style>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="37.07" height="36" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 198"><path fill="#41B883" d="M204.8 0H256L128 220.8L0 0h97.92L128 51.2L157.44 0h47.36Z"></path><path fill="#41B883" d="m0 0l128 220.8L256 0h-51.2L128 132.48L50.56 0H0Z"></path><path fill="#35495E" d="M50.56 0L128 133.12L204.8 0h-47.36L128 51.2L97.92 0H50.56Z"></path></svg>
@@ -0,0 +1 @@
1
+ export * from './svg-icon';
@@ -0,0 +1 @@
1
+ export { default as SvgIcon } from './src/index.vue';
@@ -0,0 +1,29 @@
1
+ <script setup lang="ts">
2
+ import { computed } from 'vue';
3
+
4
+ interface Props {
5
+ name: string;
6
+ prefix?: string;
7
+ color?: string;
8
+ }
9
+
10
+ defineOptions({ name: 'SvgIcon' });
11
+ const props = withDefaults(defineProps<Props>(), {
12
+ prefix: 'icon',
13
+ color: '#333',
14
+ });
15
+
16
+ const symbolId = computed(() => `#${props.prefix}-${props.name}`);
17
+ </script>
18
+
19
+ <template>
20
+ <svg
21
+ aria-hidden="true"
22
+ :title="symbolId"
23
+ >
24
+ <use
25
+ :href="symbolId"
26
+ :fill="color"
27
+ />
28
+ </svg>
29
+ </template>
@@ -0,0 +1,3 @@
1
+ {
2
+ "language": "English"
3
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "language": "中文"
3
+ }
@@ -0,0 +1,21 @@
1
+ import { createApp } from 'vue';
2
+ import i18NPlugin from '@/plugins/i18n';
3
+ import router from '@/router';
4
+ import App from './App.vue';
5
+ import { createPinia } from './stores';
6
+ import 'virtual:svg-icons-register';
7
+ import '@/styles/index.css';
8
+
9
+ if (import.meta.env.VITE_APP_MOCK === 'service-worker') {
10
+ const { worker } = await import('@/mocks/browser');
11
+
12
+ worker.start();
13
+ }
14
+
15
+ const app = createApp(App);
16
+ const pinia = createPinia();
17
+
18
+ app.use(pinia);
19
+ app.use(router);
20
+ app.use(i18NPlugin);
21
+ app.mount('#app');
@@ -0,0 +1,4 @@
1
+ import { setupWorker } from 'msw/browser';
2
+ import { handlers } from '@/mocks/handlers';
3
+
4
+ export const worker = setupWorker(...handlers);
@@ -0,0 +1 @@
1
+ export const handlers = [];
@@ -0,0 +1,4 @@
1
+ import { setupServer } from 'msw/node';
2
+ import { handlers } from '@/mocks/handlers';
3
+
4
+ export const mswServer = setupServer(...handlers);