diff --git a/package.json b/package.json
index 34ed2fc..a79bae2 100644
--- a/package.json
+++ b/package.json
@@ -85,6 +85,7 @@
"@vue/eslint-config-typescript": "^14.6.0",
"@vue/test-utils": "^2.4.6",
"@vue/tsconfig": "^0.8.1",
+ "consola": "^3.4.2",
"eslint": "^9.35.0",
"eslint-plugin-oxlint": "~1.23.0",
"eslint-plugin-playwright": "^2.2.2",
@@ -107,6 +108,7 @@
"stylelint-config-standard-scss": "^16.0.0",
"stylelint-config-standard-vue": "^1.0.0",
"stylelint-define-config": "^16.24.0",
+ "tinyglobby": "^0.2.15",
"typescript": "~5.9.2",
"unocss": "^66.5.1",
"unocss-preset-animations": "^1.2.1",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 2e42d5a..b290519 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -135,6 +135,9 @@ importers:
'@vue/tsconfig':
specifier: ^0.8.1
version: 0.8.1(typescript@5.9.2)(vue@3.5.22(typescript@5.9.2))
+ consola:
+ specifier: ^3.4.2
+ version: 3.4.2
eslint:
specifier: ^9.35.0
version: 9.38.0(jiti@2.6.1)
@@ -201,6 +204,9 @@ importers:
stylelint-define-config:
specifier: ^16.24.0
version: 16.24.0(stylelint@16.25.0(typescript@5.9.2))
+ tinyglobby:
+ specifier: ^0.2.15
+ version: 0.2.15
typescript:
specifier: ~5.9.2
version: 5.9.2
diff --git a/tsconfig.node.json b/tsconfig.node.json
index e0c1690..63809e1 100644
--- a/tsconfig.node.json
+++ b/tsconfig.node.json
@@ -8,6 +8,7 @@
"playwright.config.*",
"eslint.config.*",
"stylelint.config.*",
+ "vite-plugins",
"fake/**/*"
],
"compilerOptions": {
@@ -16,6 +17,7 @@
"module": "ESNext",
"moduleResolution": "Bundler",
- "types": ["node"]
+ "types": ["node"],
+ "allowImportingTsExtensions": true
}
}
diff --git a/vite-plugins/00.vue-macros.ts b/vite-plugins/00.vue-macros.ts
new file mode 100644
index 0000000..4a592c8
--- /dev/null
+++ b/vite-plugins/00.vue-macros.ts
@@ -0,0 +1,26 @@
+import vue from '@vitejs/plugin-vue';
+import vueJsx from '@vitejs/plugin-vue-jsx';
+import { getPascalCaseRouteName } from 'unplugin-vue-router';
+import vueRouter from 'unplugin-vue-router/vite';
+import type { PluginOption } from 'vite';
+import VueMacros from 'vue-macros/vite';
+
+export default [
+ VueMacros({
+ plugins: {
+ vue: vue({ include: [/\.vue$/, /\.md$/] }),
+ vueJsx: vueJsx(),
+
+ // https://uvr.esm.is/guide/configuration.html
+ // https://github.com/posva/unplugin-vue-router
+ // ⚠️ Vue must be placed after VueRouter()
+ vueRouter: vueRouter({
+ exclude: ['**/__*', '**/__*/**/*'],
+ extensions: ['.page.vue', '.page.md'],
+ getRouteName: (routeNode) => getPascalCaseRouteName(routeNode),
+ logs: false,
+ routesFolder: 'src/pages',
+ }),
+ },
+ }),
+] satisfies PluginOption;
diff --git a/vite-plugins/02.vite-plugin-vue-layouts.disabled.ts b/vite-plugins/02.vite-plugin-vue-layouts.disabled.ts
new file mode 100644
index 0000000..93764fe
--- /dev/null
+++ b/vite-plugins/02.vite-plugin-vue-layouts.disabled.ts
@@ -0,0 +1,6 @@
+import type { PluginOption } from 'vite';
+
+export default [
+ // https://github.com/JohnCampionJr/vite-plugin-vue-layouts?tab=readme-ov-file#configuration
+ // Layouts({ defaultLayout: 'sakai-vue/AppLayout', pagesDirs: [] }),
+] satisfies PluginOption;
diff --git a/vite-plugins/02.vite-plugin-vue-meta-layouts.ts b/vite-plugins/02.vite-plugin-vue-meta-layouts.ts
new file mode 100644
index 0000000..fb0ba59
--- /dev/null
+++ b/vite-plugins/02.vite-plugin-vue-meta-layouts.ts
@@ -0,0 +1,12 @@
+import type { PluginOption } from 'vite';
+import MetaLayouts from 'vite-plugin-vue-meta-layouts';
+
+export default [
+ // https://github.com/dishait/vite-plugin-vue-meta-layouts
+ MetaLayouts({
+ // defaultLayout: 'sakai-vue/AppLayout',
+ // defaultLayout: 'naive-ui/AppLayout',
+ defaultLayout: 'base-layout/base-layout',
+ skipTopLevelRouteLayout: true, // 打开修复 https://github.com/JohnCampionJr/vite-plugin-vue-layouts/issues/134,默认为 false 关闭
+ }),
+] satisfies PluginOption;
diff --git a/vite-plugins/03.unplugin-auto-import.ts b/vite-plugins/03.unplugin-auto-import.ts
new file mode 100644
index 0000000..c3071b4
--- /dev/null
+++ b/vite-plugins/03.unplugin-auto-import.ts
@@ -0,0 +1,29 @@
+import type { PluginOption } from 'vite';
+import AutoImport from 'unplugin-auto-import/vite';
+import { createUtils4uAutoImports } from 'utils4u/auto-imports';
+import { VueRouterAutoImports } from 'unplugin-vue-router';
+
+export default [
+ // https://github.com/antfu/unplugin-auto-import
+ AutoImport({
+ dirs: [
+ // 'src/composables',
+ // 'src/utils',
+ 'src/stores',
+ ],
+ imports: [
+ 'vue',
+ 'vue-i18n',
+ 'pinia',
+ '@vueuse/core',
+ VueRouterAutoImports,
+ createUtils4uAutoImports([]),
+ {
+ 'consola/browser': ['consola'],
+ 'vue-router/auto': ['useLink'],
+ 'naive-ui': ['useModal', 'useDialog', 'useMessage', 'useNotification', 'useLoadingBar'],
+ },
+ ],
+ vueTemplate: true,
+ }),
+] satisfies PluginOption;
diff --git a/vite-plugins/03.unplugin-icons.ts b/vite-plugins/03.unplugin-icons.ts
new file mode 100644
index 0000000..23d65f8
--- /dev/null
+++ b/vite-plugins/03.unplugin-icons.ts
@@ -0,0 +1,17 @@
+import type { PluginOption } from 'vite';
+import { FileSystemIconLoader } from 'unplugin-icons/loaders';
+import Icons from 'unplugin-icons/vite';
+
+export default [
+ Icons({
+ autoInstall: true,
+ customCollections: {
+ svg: FileSystemIconLoader('src/assets/icons/svgs', (svg) => {
+ return svg.replace(/^ or */,
+ }), // https://github.com/unplugin/unplugin-icons?tab=readme-ov-file#auto-importing
+ TDesignResolver({ esm: true, library: 'mobile-vue' }),
+ VantResolver({ importStyle: true }),
+ PrimeVueResolver(/* { components: { prefix: 'P' } } */),
+ NaiveUiResolver(),
+ ],
+ }),
+] satisfies PluginOption;
diff --git a/vite.config.plugin.index-html-plugin.ts b/vite-plugins/999.index-html-plugin.ts
similarity index 81%
rename from vite.config.plugin.index-html-plugin.ts
rename to vite-plugins/999.index-html-plugin.ts
index 97ecde6..095f1d6 100644
--- a/vite.config.plugin.index-html-plugin.ts
+++ b/vite-plugins/999.index-html-plugin.ts
@@ -1,7 +1,7 @@
+import type { PluginOption } from 'vite';
import { minify as minifyHtml } from 'html-minifier-terser';
-import { type PluginOption } from 'vite';
-export function IndexHtmlPlugin(): PluginOption {
+function IndexHtmlPlugin(): PluginOption {
return {
name: 'index-html-plugin',
apply: 'build',
@@ -24,3 +24,5 @@ export function IndexHtmlPlugin(): PluginOption {
},
};
}
+
+export default [IndexHtmlPlugin()] satisfies PluginOption[];
diff --git a/vite-plugins/_x-demo.disabled.ts b/vite-plugins/_x-demo.disabled.ts
new file mode 100644
index 0000000..f258958
--- /dev/null
+++ b/vite-plugins/_x-demo.disabled.ts
@@ -0,0 +1,9 @@
+import type { ConfigEnv, PluginOption } from 'vite';
+
+export default [
+ // ...
+] satisfies PluginOption;
+
+export function loadPlugin(_configEnv: ConfigEnv): PluginOption {
+ return [];
+}
diff --git a/vite-plugins/cloudflare.ts b/vite-plugins/cloudflare.ts
new file mode 100644
index 0000000..2245ec4
--- /dev/null
+++ b/vite-plugins/cloudflare.ts
@@ -0,0 +1,4 @@
+import type { PluginOption } from 'vite';
+import { cloudflare } from '@cloudflare/vite-plugin';
+
+export default [cloudflare()] satisfies PluginOption;
diff --git a/vite-plugins/unocss.ts b/vite-plugins/unocss.ts
new file mode 100644
index 0000000..3226453
--- /dev/null
+++ b/vite-plugins/unocss.ts
@@ -0,0 +1,8 @@
+import type { PluginOption } from 'vite';
+import UnoCSS from 'unocss/vite';
+
+export default [
+ // https://github.com/antfu/unocss
+ // see uno.config.ts for config
+ UnoCSS(),
+] satisfies PluginOption;
diff --git a/vite-plugins/unplugin-vue-i18n.ts b/vite-plugins/unplugin-vue-i18n.ts
new file mode 100644
index 0000000..c9fa84c
--- /dev/null
+++ b/vite-plugins/unplugin-vue-i18n.ts
@@ -0,0 +1,19 @@
+import type { PluginOption } from 'vite';
+import VueI18nPlugin from '@intlify/unplugin-vue-i18n/vite';
+import path from 'node:path';
+
+export default [
+ // https://github.com/intlify/bundle-tools/tree/main/packages/unplugin-vue-i18n
+ VueI18nPlugin({
+ /* options */
+ // locale messages resource pre-compile option
+ include: [path.resolve(import.meta.dirname, './src/locales/**')],
+
+ // https://github.com/intlify/bundle-tools/tree/main/packages/unplugin-vue-i18n#transformi18nblock
+ // transformI18nBlock(src) {
+ // console.debug(`src :>> `, src);
+ // console.debug(`typeof src :>> `, typeof src);
+ // return src as string;
+ // },
+ }),
+] satisfies PluginOption;
diff --git a/vite-plugins/unplugin-vue-markdown.ts b/vite-plugins/unplugin-vue-markdown.ts
new file mode 100644
index 0000000..67efc86
--- /dev/null
+++ b/vite-plugins/unplugin-vue-markdown.ts
@@ -0,0 +1,9 @@
+import type { PluginOption } from 'vite';
+import Markdown from 'unplugin-vue-markdown/vite';
+
+export default [
+ // https://github.com/unplugin/unplugin-vue-markdown
+ Markdown({
+ headEnabled: true,
+ }),
+] satisfies PluginOption;
diff --git a/vite-plugins/vite-plugin-checker.ts b/vite-plugins/vite-plugin-checker.ts
new file mode 100644
index 0000000..d11a1e6
--- /dev/null
+++ b/vite-plugins/vite-plugin-checker.ts
@@ -0,0 +1,19 @@
+import type { PluginOption } from 'vite';
+import checker from 'vite-plugin-checker';
+
+export default [
+ // https://vite-plugin-checker.netlify.app/introduction/introduction.html
+ checker({
+ eslint: {
+ lintCommand: 'eslint "./src/**/*.{js,jsx,ts,tsx,vue}"',
+ useFlatConfig: true,
+ },
+ vueTsc: true,
+ overlay: {
+ initialIsOpen: false,
+ },
+ terminal: true,
+ enableBuild: true,
+ // XXX: pnpm add vls vti -D
+ }),
+] satisfies PluginOption;
diff --git a/vite-plugins/vite-plugin-fake-server.ts b/vite-plugins/vite-plugin-fake-server.ts
new file mode 100644
index 0000000..1343749
--- /dev/null
+++ b/vite-plugins/vite-plugin-fake-server.ts
@@ -0,0 +1,16 @@
+import type { ConfigEnv, PluginOption } from 'vite';
+import { vitePluginFakeServer } from 'vite-plugin-fake-server';
+// https://github.com/condorheroblog/vite-plugin-fake-server?tab=readme-ov-file#usage
+
+// // if (mode !== 'test') {}
+// export default [
+
+// ] satisfies PluginOption;
+
+export function loadPlugin(_configEnv: ConfigEnv): PluginOption {
+ return vitePluginFakeServer({
+ basename: 'fake-api',
+ enableProd: true,
+ include: 'fake',
+ });
+}
diff --git a/vite-plugins/vite-plugin-image-optimizer.ts b/vite-plugins/vite-plugin-image-optimizer.ts
new file mode 100644
index 0000000..351df1d
--- /dev/null
+++ b/vite-plugins/vite-plugin-image-optimizer.ts
@@ -0,0 +1,11 @@
+import type { PluginOption } from 'vite';
+import { ViteImageOptimizer } from 'vite-plugin-image-optimizer';
+
+// env.VITE_ENABLE_VUE_DEVTOOLS === 'true'
+
+export default [
+ // https://github.com/FatehAK/vite-plugin-image-optimizer?tab=readme-ov-file#default-configuration
+ ViteImageOptimizer({
+ /* pass your config */
+ }),
+] satisfies PluginOption;
diff --git a/vite-plugins/vite-plugin-vue-devtools.ts b/vite-plugins/vite-plugin-vue-devtools.ts
new file mode 100644
index 0000000..9c2267a
--- /dev/null
+++ b/vite-plugins/vite-plugin-vue-devtools.ts
@@ -0,0 +1,6 @@
+import type { PluginOption } from 'vite';
+import vueDevTools from 'vite-plugin-vue-devtools';
+
+// env.VITE_ENABLE_VUE_DEVTOOLS === 'true'
+
+export default [vueDevTools()] satisfies PluginOption;
diff --git a/vite-plugins/vite-plugin-webfont-dl.ts b/vite-plugins/vite-plugin-webfont-dl.ts
new file mode 100644
index 0000000..948e2ed
--- /dev/null
+++ b/vite-plugins/vite-plugin-webfont-dl.ts
@@ -0,0 +1,11 @@
+import type { PluginOption } from 'vite';
+import { ViteWebfontDownload } from 'vite-plugin-webfont-dl';
+
+export default [
+ // https://github.com/feat-agency/vite-plugin-webfont-dl?tab=readme-ov-file#-usage-simple-config-method-b-
+ ViteWebfontDownload([
+ 'https://fonts.googleapis.com/css2?family=Press+Start+2P&display=swap',
+ 'https://fonts.googleapis.com/css2?family=Fira+Code&display=swap',
+ 'https://fonts.googleapis.com/css?family=Montserrat:300,400,500,600,700,900',
+ ]),
+] satisfies PluginOption;
diff --git a/vite-plugins/x-vite-plugin-purgecss-v5.ts b/vite-plugins/x-vite-plugin-purgecss-v5.ts
new file mode 100644
index 0000000..ad30829
--- /dev/null
+++ b/vite-plugins/x-vite-plugin-purgecss-v5.ts
@@ -0,0 +1,8 @@
+import type { PluginOption } from 'vite';
+
+export default [
+ // // https://github.com/rsnakdmx/vite-plugin-purgecss-v5?tab=readme-ov-file#-usage
+ // pluginPurgeCss({
+ // variables: true,
+ // }),
+] satisfies PluginOption;
diff --git a/vite-plugins/x-vite-plugin-singlefile.ts b/vite-plugins/x-vite-plugin-singlefile.ts
new file mode 100644
index 0000000..6d903f0
--- /dev/null
+++ b/vite-plugins/x-vite-plugin-singlefile.ts
@@ -0,0 +1,5 @@
+import type { PluginOption } from 'vite';
+
+export default [
+ // ...
+] satisfies PluginOption;
diff --git a/vite-plugins/x-vite-plugin-static-copy.ts b/vite-plugins/x-vite-plugin-static-copy.ts
new file mode 100644
index 0000000..799e7ab
--- /dev/null
+++ b/vite-plugins/x-vite-plugin-static-copy.ts
@@ -0,0 +1,15 @@
+import type { PluginOption } from 'vite';
+
+export default [
+ // plugins.push(
+ // viteStaticCopy({
+ // targets: [
+ // // globalThis.CESIUM_BASE_URL = 'https://digitalarsenal.io/';
+ // { dest: cesiumBaseUrl, src: `${cesiumSource}/ThirdParty` },
+ // { dest: cesiumBaseUrl, src: `${cesiumSource}/Workers` },
+ // { dest: cesiumBaseUrl, src: `${cesiumSource}/Assets` },
+ // { dest: cesiumBaseUrl, src: `${cesiumSource}/Widgets` },
+ // ],
+ // }),
+ // )
+] satisfies PluginOption;
diff --git a/vite-plugins/x-vite-plugin-zip-file.ts b/vite-plugins/x-vite-plugin-zip-file.ts
new file mode 100644
index 0000000..37973eb
--- /dev/null
+++ b/vite-plugins/x-vite-plugin-zip-file.ts
@@ -0,0 +1,17 @@
+import type { PluginOption } from 'vite';
+
+export default [
+ // // 检查是否在VS Code终端中运行
+ // if (process.env.TERM_PROGRAM === 'vscode' || process.env.VSCODE_PID) {
+ // // plugins.push(
+ // // // 构建后自动将dist目录打包成zip文件
+ // // viteArchiverPlugin({
+ // // addTimestamp: false, // 是否添加时间戳到输出文件名
+ // // format: 'zip', // 输出的压缩文件格式
+ // // outputDir: '', // 输出目录,默认为项目根目录
+ // // outputFileName: 'dist', // 输出的zip文件名(不含扩展名)
+ // // sourceDir: 'dist', // 要打包的源目录
+ // // }),
+ // // )
+ // }
+] satisfies PluginOption;
diff --git a/vite.config.optimizeDeps.ts b/vite.config.optimizeDeps.ts
index 47dddbd..54db753 100644
--- a/vite.config.optimizeDeps.ts
+++ b/vite.config.optimizeDeps.ts
@@ -6,7 +6,11 @@ import type { DepOptimizationOptions } from 'vite';
// })();
export function optimizeDeps(): DepOptimizationOptions {
return {
- entries: ['src/main.ts', 'src/pages/**/*.vue'],
+ entries: [
+ 'src/main.ts',
+ 'src/pages/**/*.vue',
+ 'packages/materials/src/index.ts', // > simplebar-vue
+ ],
// include: [
// ...primevuecomponents,
// '@primeuix/themes',
diff --git a/vite.config.plugins.ts b/vite.config.plugins.ts
deleted file mode 100644
index d53ccd3..0000000
--- a/vite.config.plugins.ts
+++ /dev/null
@@ -1,246 +0,0 @@
-import { cloudflare } from '@cloudflare/vite-plugin';
-import VueI18nPlugin from '@intlify/unplugin-vue-i18n/vite';
-import { PrimeVueResolver } from '@primevue/auto-import-resolver';
-import { VantResolver } from '@vant/auto-import-resolver';
-import vue from '@vitejs/plugin-vue';
-import vueJsx from '@vitejs/plugin-vue-jsx';
-import path from 'node:path';
-import UnoCSS from 'unocss/vite';
-import AutoImport from 'unplugin-auto-import/vite';
-import { FileSystemIconLoader } from 'unplugin-icons/loaders';
-import IconsResolver from 'unplugin-icons/resolver';
-import Icons from 'unplugin-icons/vite';
-import {
- AntDesignVueResolver,
- NaiveUiResolver,
- TDesignResolver,
-} from 'unplugin-vue-components/resolvers';
-import Components from 'unplugin-vue-components/vite';
-import Markdown from 'unplugin-vue-markdown/vite';
-import { getPascalCaseRouteName, VueRouterAutoImports } from 'unplugin-vue-router';
-import vueRouter from 'unplugin-vue-router/vite';
-import { createUtils4uAutoImports } from 'utils4u/auto-imports';
-import { type PluginOption } from 'vite';
-import { checker } from 'vite-plugin-checker';
-import { vitePluginFakeServer } from 'vite-plugin-fake-server';
-import { ViteImageOptimizer } from 'vite-plugin-image-optimizer';
-import vueDevTools from 'vite-plugin-vue-devtools';
-import MetaLayouts from 'vite-plugin-vue-meta-layouts';
-import { ViteWebfontDownload } from 'vite-plugin-webfont-dl';
-import VueMacros from 'vue-macros/vite';
-import { IndexHtmlPlugin } from './vite.config.plugin.index-html-plugin';
-
-export function Plugins({
- mode,
- env,
-}: {
- mode: string;
- env: Record;
-}): PluginOption[] {
- const plugins: PluginOption[] = [
- VueMacros({
- plugins: {
- vue: vue({ include: [/\.vue$/, /\.md$/] }),
- vueJsx: vueJsx(),
-
- // https://uvr.esm.is/guide/configuration.html
- // https://github.com/posva/unplugin-vue-router
- // ⚠️ Vue must be placed after VueRouter()
- vueRouter: vueRouter({
- exclude: ['**/__*', '**/__*/**/*'],
- extensions: ['.page.vue', '.page.md'],
- getRouteName: (routeNode) => getPascalCaseRouteName(routeNode),
- logs: false,
- routesFolder: 'src/pages',
- }),
- },
- }),
- ];
-
- plugins.push(
- // https://github.com/JohnCampionJr/vite-plugin-vue-layouts?tab=readme-ov-file#configuration
- // Layouts({ defaultLayout: 'sakai-vue/AppLayout', pagesDirs: [] }),
-
- // https://github.com/dishait/vite-plugin-vue-meta-layouts
- MetaLayouts({
- // defaultLayout: 'sakai-vue/AppLayout',
- // defaultLayout: 'naive-ui/AppLayout',
- defaultLayout: 'base-layout/base-layout',
- skipTopLevelRouteLayout: true, // 打开修复 https://github.com/JohnCampionJr/vite-plugin-vue-layouts/issues/134,默认为 false 关闭
- }),
- );
-
- plugins.push(
- // https://github.com/unplugin/unplugin-vue-markdown
- Markdown({
- headEnabled: true,
- }),
-
- cloudflare(),
- );
-
- plugins.push(
- // https://github.com/antfu/unocss
- // see uno.config.ts for config
- UnoCSS(),
- );
-
- plugins.push(
- // https://github.com/antfu/unplugin-auto-import
- AutoImport({
- dirs: [
- // 'src/composables',
- // 'src/utils',
- 'src/stores',
- ],
- imports: [
- 'vue',
- 'vue-i18n',
- 'pinia',
- '@vueuse/core',
- VueRouterAutoImports,
- createUtils4uAutoImports([]),
- {
- 'consola/browser': ['consola'],
- 'vue-router/auto': ['useLink'],
- 'naive-ui': ['useModal', 'useDialog', 'useMessage', 'useNotification', 'useLoadingBar'],
- },
- ],
- vueTemplate: true,
- }),
-
- // https://github.com/antfu/unplugin-vue-components
- Components({
- // __开头的
- excludeNames: [/^__/],
- // allow auto load markdown components under `./src/components/`
- extensions: ['vue', 'md'],
- // allow auto import and register components used in markdown
- include: [/\.vue$/, /\.vue\?vue/, /\.md$/],
- resolvers: [
- AntDesignVueResolver({
- importStyle: false, // css in js
- resolveIcons: true,
- }),
- IconsResolver({
- customCollections: ['svg'],
- prefix: 'icon' /* or */,
- }), // https://github.com/unplugin/unplugin-icons?tab=readme-ov-file#auto-importing
- TDesignResolver({ esm: true, library: 'mobile-vue' }),
- VantResolver({ importStyle: true }),
- PrimeVueResolver(/* { components: { prefix: 'P' } } */),
- NaiveUiResolver(),
- ],
- }),
-
- Icons({
- autoInstall: true,
- customCollections: {
- svg: FileSystemIconLoader('src/assets/icons/svgs', (svg) => {
- return svg.replace(/^