chore: update vite 8

This commit is contained in:
xingyu4j
2026-03-13 15:51:28 +08:00
parent 0e4bf80bf4
commit 443e4b04cd
12 changed files with 867 additions and 257 deletions

View File

@@ -51,6 +51,7 @@
"rollup": "catalog:", "rollup": "catalog:",
"rollup-plugin-visualizer": "catalog:", "rollup-plugin-visualizer": "catalog:",
"sass": "catalog:", "sass": "catalog:",
"sass-embedded": "catalog:",
"vite": "catalog:", "vite": "catalog:",
"vite-plugin-compression": "catalog:", "vite-plugin-compression": "catalog:",
"vite-plugin-dts": "catalog:", "vite-plugin-dts": "catalog:",

View File

@@ -6,7 +6,7 @@ import path, { relative } from 'node:path';
import { findMonorepoRoot } from '@vben/node-utils'; import { findMonorepoRoot } from '@vben/node-utils';
import { NodePackageImporter } from 'sass'; import { NodePackageImporter } from 'sass-embedded';
import { defineConfig, loadEnv, mergeConfig } from 'vite'; import { defineConfig, loadEnv, mergeConfig } from 'vite';
import { defaultImportmapOptions, getDefaultPwaOptions } from '../options'; import { defaultImportmapOptions, getDefaultPwaOptions } from '../options';
@@ -58,25 +58,23 @@ function defineApplicationConfig(userConfigPromise?: DefineApplicationOptions) {
const applicationConfig: UserConfig = { const applicationConfig: UserConfig = {
base, base,
build: { build: {
rollupOptions: { rolldownOptions: {
output: { output: {
assetFileNames: '[ext]/[name]-[hash].[ext]', assetFileNames: '[ext]/[name]-[hash].[ext]',
chunkFileNames: 'js/[name]-[hash].js', chunkFileNames: 'js/[name]-[hash].js',
entryFileNames: 'jse/index-[name]-[hash].js', entryFileNames: 'jse/index-[name]-[hash].js',
minify: isBuild
? {
compress: {
dropDebugger: true,
},
}
: false,
}, },
}, },
target: 'es2015', target: 'es2015',
}, },
css: createCssOptions(injectGlobalScss), css: createCssOptions(injectGlobalScss),
esbuild: {
drop: isBuild
? [
// 'console',
'debugger',
]
: [],
legalComments: 'none',
},
plugins, plugins,
server: { server: {
host: true, host: true,

View File

@@ -40,7 +40,7 @@ function defineLibraryConfig(userConfigPromise?: DefineLibraryOptions) {
fileName: () => 'index.mjs', fileName: () => 'index.mjs',
formats: ['es'], formats: ['es'],
}, },
rollupOptions: { rolldownOptions: {
external: (id) => { external: (id) => {
return externalPackages.some( return externalPackages.some(
(pkg) => id === pkg || id.startsWith(`${pkg}/`), (pkg) => id === pkg || id.startsWith(`${pkg}/`),

View File

@@ -77,11 +77,13 @@ async function loadCommonPlugins(
}, },
{ {
condition: isBuild && !!visualizer, condition: isBuild && !!visualizer,
plugins: () => [<PluginOption>viteVisualizerPlugin({ plugins: () => [
viteVisualizerPlugin({
filename: './node_modules/.cache/visualizer/stats.html', filename: './node_modules/.cache/visualizer/stats.html',
gzipSize: true, gzipSize: true,
open: true, open: true,
})], }) as PluginOption,
],
}, },
]; ];
} }

View File

@@ -30,6 +30,12 @@ interface BasicUserInfo {
username: string; username: string;
} }
type ClassType = Array<object | string> | object | string; type ClassType =
| Array<ClassType>
| boolean
| null
| object
| string
| undefined;
export type { BasicOption, BasicUserInfo, ClassType, SelectOption, TabOption }; export type { BasicOption, BasicUserInfo, ClassType, SelectOption, TabOption };

View File

@@ -57,12 +57,10 @@ function menuIcon(menu: MenuRecordRaw) {
</template> </template>
</ul> </ul>
</template> </template>
<style lang="scss" scoped> <style scoped>
$namespace: vben;
@reference "@vben-core/design/theme"; @reference "@vben-core/design/theme";
.#{$namespace}-normal-menu { .vben-normal-menu {
--menu-item-margin-y: 4px; --menu-item-margin-y: 4px;
--menu-item-margin-x: 0px; --menu-item-margin-x: 0px;
--menu-item-padding-y: 9px; --menu-item-padding-y: 9px;
@@ -70,96 +68,93 @@ $namespace: vben;
--menu-item-radius: 0px; --menu-item-radius: 0px;
height: calc(100% - 4px); height: calc(100% - 4px);
}
&.is-rounded { .vben-normal-menu.is-rounded {
--menu-item-radius: 6px; --menu-item-radius: 6px;
--menu-item-margin-x: 8px; --menu-item-margin-x: 8px;
} }
&.is-dark { .vben-normal-menu.is-dark .vben-normal-menu__item {
.#{$namespace}-normal-menu__item { @apply text-foreground/80;
@apply text-foreground/80; }
// color: hsl(var(--foreground) / 80%);
&:not(.is-active):hover { .vben-normal-menu.is-dark .vben-normal-menu__item:not(.is-active):hover {
@apply text-foreground; @apply text-foreground;
} }
&.is-active { .vben-normal-menu.is-dark
.#{$namespace}-normal-menu__name, .vben-normal-menu__item.is-active
.#{$namespace}-normal-menu__icon { .vben-normal-menu__name,
@apply text-foreground; .vben-normal-menu.is-dark
} .vben-normal-menu__item.is-active
} .vben-normal-menu__icon {
} @apply text-foreground;
} }
&.is-collapse { .vben-normal-menu.is-collapse .vben-normal-menu__name {
.#{$namespace}-normal-menu__name { width: 0;
width: 0; height: 0;
height: 0; margin-top: 0;
margin-top: 0; overflow: hidden;
overflow: hidden; opacity: 0;
opacity: 0; }
}
.#{$namespace}-normal-menu__icon { .vben-normal-menu.is-collapse .vben-normal-menu__icon {
font-size: calc(var(--font-size-base, 16px) * 1.25); font-size: calc(var(--font-size-base, 16px) * 1.25);
} }
}
&__item { .vben-normal-menu__item {
position: relative; position: relative;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
// max-width: 64px;
// max-height: 64px;
padding: var(--menu-item-padding-y) var(--menu-item-padding-x);
margin: var(--menu-item-margin-y) var(--menu-item-margin-x);
color: hsl(var(--foreground) / 90%);
cursor: pointer;
border-radius: var(--menu-item-radius);
transition:
background 0.15s ease,
padding 0.15s ease,
border-color 0.15s ease;
&.is-active { /* max-width: 64px; */
@apply bg-primary text-primary dark:bg-accent;
.#{$namespace}-normal-menu__name, /* max-height: 64px; */
.#{$namespace}-normal-menu__icon { padding: var(--menu-item-padding-y) var(--menu-item-padding-x);
@apply text-primary-foreground font-semibold; margin: var(--menu-item-margin-y) var(--menu-item-margin-x);
} color: hsl(var(--foreground) / 90%);
} cursor: pointer;
border-radius: var(--menu-item-radius);
transition:
background 0.15s ease,
padding 0.15s ease,
border-color 0.15s ease;
}
&:not(.is-active):hover { .vben-normal-menu__item.is-active {
@apply bg-heavy text-primary dark:bg-accent dark:text-foreground; @apply bg-primary text-primary dark:bg-accent;
} }
&:hover { .vben-normal-menu__item.is-active .vben-normal-menu__name,
.#{$namespace}-normal-menu__icon { .vben-normal-menu__item.is-active .vben-normal-menu__icon {
transform: scale(1.2); @apply text-primary-foreground font-semibold;
} }
}
}
&__icon { .vben-normal-menu__item:not(.is-active):hover {
max-height: 20px; @apply bg-heavy text-primary dark:bg-accent dark:text-foreground;
font-size: calc(var(--font-size-base, 16px) * 1.25); }
transition: all 0.25s ease;
}
&__name { .vben-normal-menu__item:hover .vben-normal-menu__icon {
width: 100%; transform: scale(1.2);
margin-top: 8px; }
margin-bottom: 0;
font-size: calc(var(--font-size-base, 16px) * 0.75); .vben-normal-menu__icon {
font-weight: 400; max-height: 20px;
text-align: center; font-size: calc(var(--font-size-base, 16px) * 1.25);
transition: all 0.25s ease; transition: all 0.25s ease;
} }
.vben-normal-menu__name {
width: 100%;
margin-top: 8px;
margin-bottom: 0;
font-size: calc(var(--font-size-base, 16px) * 0.75);
font-weight: 400;
text-align: center;
transition: all 0.25s ease;
} }
</style> </style>

View File

@@ -1,6 +1,6 @@
import type { Component, Ref } from 'vue'; import type { Component, Ref } from 'vue';
import type { MaybePromise } from '@vben-core/typings'; import type { ClassType, MaybePromise } from '@vben-core/typings';
import type { ModalApi } from './modal-api'; import type { ModalApi } from './modal-api';
@@ -30,7 +30,7 @@ export interface ModalProps {
*/ */
centered?: boolean; centered?: boolean;
class?: string; class?: ClassType;
/** /**
* 是否显示右上角的关闭按钮 * 是否显示右上角的关闭按钮
@@ -60,7 +60,7 @@ export interface ModalProps {
* 确定按钮文字 * 确定按钮文字
*/ */
confirmText?: string; confirmText?: string;
contentClass?: string; contentClass?: ClassType;
/** /**
* 弹窗描述 * 弹窗描述
*/ */
@@ -79,7 +79,7 @@ export interface ModalProps {
* @default true * @default true
*/ */
footer?: boolean; footer?: boolean;
footerClass?: string; footerClass?: ClassType;
/** /**
* 是否全屏 * 是否全屏
* @default false * @default false
@@ -95,7 +95,7 @@ export interface ModalProps {
* @default true * @default true
*/ */
header?: boolean; header?: boolean;
headerClass?: string; headerClass?: ClassType;
/** /**
* 弹窗是否显示 * 弹窗是否显示
* @default false * @default false

View File

@@ -175,39 +175,38 @@ function onMouseDown(e: MouseEvent, tab: TabConfig) {
<style scoped> <style scoped>
@reference "@vben-core/design/theme"; @reference "@vben-core/design/theme";
.tabs-chrome { .tabs-chrome__item:not(.dragging) {
&__item:not(.dragging) { @apply cursor-pointer;
@apply cursor-pointer; }
&:hover:not(.is-active) { .tabs-chrome__item:not(.dragging):hover:not(.is-active)
& + .tabs-chrome__item { + .tabs-chrome__item
.tabs-chrome__divider { .tabs-chrome__divider {
@apply opacity-0; @apply opacity-0;
} }
}
.tabs-chrome__divider { .tabs-chrome__item:not(.dragging):hover:not(.is-active)
@apply opacity-0; .tabs-chrome__divider {
} @apply opacity-0;
}
.tabs-chrome__background { .tabs-chrome__item:not(.dragging):hover:not(.is-active)
@apply pb-[2px]; .tabs-chrome__background {
@apply pb-[2px];
}
&-content { .tabs-chrome__item:not(.dragging):hover:not(.is-active)
@apply bg-accent mx-[2px] rounded-md; .tabs-chrome__background-content {
} @apply bg-accent mx-[2px] rounded-md;
} }
}
&.is-active { .tabs-chrome__item:not(.dragging).is-active {
@apply z-[2]; @apply z-[2];
}
& + .tabs-chrome__item { .tabs-chrome__item:not(.dragging).is-active
.tabs-chrome__divider { + .tabs-chrome__item
@apply !opacity-0; .tabs-chrome__divider {
} @apply !opacity-0;
}
}
}
} }
</style> </style>

View File

@@ -51,8 +51,10 @@ defineExpose({
const wrapperRef = useTemplateRef<HTMLDivElement>('wrapperRef'); const wrapperRef = useTemplateRef<HTMLDivElement>('wrapperRef');
const barRef = useTemplateRef<InstanceType<typeof SliderCaptchaBar>>('barRef'); const barRef = useTemplateRef<InstanceType<typeof SliderCaptchaBar>>('barRef');
const contentRef = useTemplateRef<InstanceType<typeof SliderCaptchaContent>>('contentRef'); const contentRef =
const actionRef = useTemplateRef<InstanceType<typeof SliderCaptchaAction>>('actionRef'); useTemplateRef<InstanceType<typeof SliderCaptchaContent>>('contentRef');
const actionRef =
useTemplateRef<InstanceType<typeof SliderCaptchaAction>>('actionRef');
watch( watch(
() => state.isPassing, () => state.isPassing,
@@ -83,20 +85,19 @@ function handleDragStart(e: MouseEvent | TouchEvent) {
if (state.isPassing) { if (state.isPassing) {
return; return;
} }
if (!actionRef.value) return; const actionEl = actionRef.value;
const actionStyle = actionEl?.getStyle();
if (!actionEl || !actionStyle) return;
emit('start', e); emit('start', e);
state.moveDistance = state.moveDistance =
getEventPageX(e) - getEventPageX(e) -
Number.parseInt( Number.parseInt(actionStyle.left.replace('px', '') || '0', 10);
actionRef.value.getStyle().left.replace('px', '') || '0',
10,
);
state.startTime = Date.now(); state.startTime = Date.now();
state.isMoving = true; state.isMoving = true;
} }
function getOffset(actionEl: HTMLDivElement) { function getOffset(actionEl?: HTMLDivElement | null) {
const wrapperWidth = wrapperRef.value?.offsetWidth ?? 220; const wrapperWidth = wrapperRef.value?.offsetWidth ?? 220;
const actionWidth = actionEl?.offsetWidth ?? 40; const actionWidth = actionEl?.offsetWidth ?? 40;
const offset = wrapperWidth - actionWidth - 6; const offset = wrapperWidth - actionWidth - 6;
@@ -109,7 +110,9 @@ function handleDragMoving(e: MouseEvent | TouchEvent) {
const actionEl = unref(actionRef); const actionEl = unref(actionRef);
const barEl = unref(barRef); const barEl = unref(barRef);
if (!actionEl || !barEl) return; if (!actionEl || !barEl) return;
const { actionWidth, offset, wrapperWidth } = getOffset(actionEl.getEl()); const actionNode = actionEl.getEl();
if (!actionNode) return;
const { actionWidth, offset, wrapperWidth } = getOffset(actionNode);
const moveX = getEventPageX(e) - moveDistance; const moveX = getEventPageX(e) - moveDistance;
emit('move', { emit('move', {
@@ -138,14 +141,18 @@ function handleDragOver(e: MouseEvent | TouchEvent) {
const barEl = unref(barRef); const barEl = unref(barRef);
if (!actionEl || !barEl) return; if (!actionEl || !barEl) return;
const moveX = getEventPageX(e) - moveDistance; const moveX = getEventPageX(e) - moveDistance;
const { actionWidth, offset, wrapperWidth } = getOffset(actionEl.getEl()); const actionNode = actionEl.getEl();
if (!actionNode) return;
const { actionWidth, offset, wrapperWidth } = getOffset(actionNode);
if (moveX < offset) { if (moveX < offset) {
if (props.isSlot) { if (props.isSlot) {
setTimeout(() => { setTimeout(() => {
if (modelValue.value) { if (modelValue.value) {
const contentEl = unref(contentRef); const contentEl = unref(contentRef);
if (contentEl) { const contentNode = contentEl?.getEl();
contentEl.getEl().style.width = `${Number.parseInt(barEl.getEl().style.width)}px`; const barNode = barEl.getEl();
if (contentNode && barNode) {
contentNode.style.width = `${Number.parseInt(barNode.style.width || '0', 10)}px`;
} }
} else { } else {
resume(); resume();
@@ -185,7 +192,10 @@ function resume() {
const contentEl = unref(contentRef); const contentEl = unref(contentRef);
if (!actionEl || !barEl || !contentEl) return; if (!actionEl || !barEl || !contentEl) return;
contentEl.getEl().style.width = '100%'; const contentNode = contentEl.getEl();
if (!contentNode) return;
contentNode.style.width = '100%';
state.toLeft = true; state.toLeft = true;
useTimeoutFn(() => { useTimeoutFn(() => {
state.toLeft = false; state.toLeft = false;

View File

@@ -7,6 +7,28 @@ import SecureLS from 'secure-ls';
let pinia: Pinia; let pinia: Pinia;
type SecureLSStorage = {
get(key: string): any;
set(key: string, value: unknown): void;
};
type SecureLSCtor = new (config?: {
encodingType?: string;
encryptionSecret?: string;
isCompression?: boolean;
metaKey?: string;
}) => SecureLSStorage;
const secureLSModule = SecureLS as unknown as {
SecureLS?: SecureLSCtor;
default?: SecureLSCtor;
};
const SecureLSConstructor =
secureLSModule.default ??
secureLSModule.SecureLS ??
(SecureLS as unknown as SecureLSCtor);
export interface InitStoreOptions { export interface InitStoreOptions {
/** /**
* @zh_CN 应用名,由于 @vben/stores 是公用的后续可能有多个app为了防止多个app缓存冲突可在这里配置应用名,应用名将被用于持久化的前缀 * @zh_CN 应用名,由于 @vben/stores 是公用的后续可能有多个app为了防止多个app缓存冲突可在这里配置应用名,应用名将被用于持久化的前缀
@@ -21,7 +43,7 @@ export async function initStores(app: App, options: InitStoreOptions) {
const { createPersistedState } = await import('pinia-plugin-persistedstate'); const { createPersistedState } = await import('pinia-plugin-persistedstate');
pinia = createPinia(); pinia = createPinia();
const { namespace } = options; const { namespace } = options;
const ls = new SecureLS({ const ls = new SecureLSConstructor({
encodingType: 'aes', encodingType: 'aes',
encryptionSecret: import.meta.env.VITE_APP_STORE_SECURE_KEY, encryptionSecret: import.meta.env.VITE_APP_STORE_SECURE_KEY,
isCompression: true, isCompression: true,

785
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -42,12 +42,14 @@ catalog:
'@nolebase/vitepress-plugin-git-changelog': ^2.18.2 '@nolebase/vitepress-plugin-git-changelog': ^2.18.2
'@playwright/test': ^1.58.2 '@playwright/test': ^1.58.2
'@pnpm/workspace.read-manifest': ^1000.3.0 '@pnpm/workspace.read-manifest': ^1000.3.0
'@shikijs/vitepress-twoslash': ^4.0.2
'@stylistic/stylelint-plugin': ^5.0.1 '@stylistic/stylelint-plugin': ^5.0.1
'@tailwindcss/typography': ^0.5.19 '@tailwindcss/typography': ^0.5.19
'@tailwindcss/vite': ^4.2.1 '@tailwindcss/vite': ^4.2.1
'@tanstack/vue-query': ^5.92.9 '@tanstack/vue-query': ^5.92.9
'@tanstack/vue-store': ^0.9.2 '@tanstack/vue-store': ^0.9.2
'@types/archiver': ^7.0.0 '@types/archiver': ^7.0.0
'@types/express': ^5.0.6
'@types/html-minifier-terser': ^7.0.2 '@types/html-minifier-terser': ^7.0.2
'@types/json-bigint': ^1.0.4 '@types/json-bigint': ^1.0.4
'@types/jsonwebtoken': ^9.0.10 '@types/jsonwebtoken': ^9.0.10
@@ -64,6 +66,7 @@ catalog:
'@vitejs/plugin-vue': ^6.0.5 '@vitejs/plugin-vue': ^6.0.5
'@vitejs/plugin-vue-jsx': ^5.1.5 '@vitejs/plugin-vue-jsx': ^5.1.5
'@vitest/eslint-plugin': ^1.6.11 '@vitest/eslint-plugin': ^1.6.11
'@voidzero-dev/vitepress-theme': ^4.8.3
'@vue/shared': ^3.5.30 '@vue/shared': ^3.5.30
'@vue/test-utils': ^2.4.6 '@vue/test-utils': ^2.4.6
'@vueuse/core': ^14.2.1 '@vueuse/core': ^14.2.1
@@ -112,6 +115,7 @@ catalog:
eslint-plugin-vue: ^10.8.0 eslint-plugin-vue: ^10.8.0
eslint-plugin-yml: ^3.3.1 eslint-plugin-yml: ^3.3.1
execa: ^9.6.1 execa: ^9.6.1
feed: ^5.2.0
find-up: ^8.0.0 find-up: ^8.0.0
get-port: ^7.1.0 get-port: ^7.1.0
globals: ^17.4.0 globals: ^17.4.0
@@ -124,11 +128,13 @@ catalog:
lefthook: ^2.1.4 lefthook: ^2.1.4
lodash.clonedeep: ^4.5.0 lodash.clonedeep: ^4.5.0
lucide-vue-next: ^0.577.0 lucide-vue-next: ^0.577.0
markdown-it-image-size: ^15.0.1
medium-zoom: ^1.1.0 medium-zoom: ^1.1.0
naive-ui: ^2.44.1 naive-ui: ^2.44.1
nitropack: ^2.13.1 nitropack: ^2.13.1
nprogress: ^0.2.0 nprogress: ^0.2.0
ora: ^9.3.0 ora: ^9.3.0
oxc-minify: ^0.115.0
pinia: ^3.0.4 pinia: ^3.0.4
pinia-plugin-persistedstate: ^4.7.1 pinia-plugin-persistedstate: ^4.7.1
pkg-types: ^2.3.0 pkg-types: ^2.3.0
@@ -146,6 +152,7 @@ catalog:
rollup: ^4.59.0 rollup: ^4.59.0
rollup-plugin-visualizer: ^7.0.1 rollup-plugin-visualizer: ^7.0.1
sass: ^1.98.0 sass: ^1.98.0
sass-embedded: ^1.98.0
secure-ls: ^2.0.0 secure-ls: ^2.0.0
sortablejs: ^1.15.7 sortablejs: ^1.15.7
stylelint: ^17.4.0 stylelint: ^17.4.0
@@ -154,7 +161,7 @@ catalog:
stylelint-config-recommended-scss: ^17.0.0 stylelint-config-recommended-scss: ^17.0.0
stylelint-config-recommended-vue: ^1.6.1 stylelint-config-recommended-vue: ^1.6.1
stylelint-config-standard: ^40.0.0 stylelint-config-standard: ^40.0.0
stylelint-order: ^7.0.1 stylelint-order: ^8.0.0
stylelint-prettier: ^5.0.3 stylelint-prettier: ^5.0.3
stylelint-scss: ^7.0.0 stylelint-scss: ^7.0.0
tailwind-merge: ^3.5.0 tailwind-merge: ^3.5.0
@@ -168,7 +175,7 @@ catalog:
unbuild: ^3.6.1 unbuild: ^3.6.1
unplugin-element-plus: ^0.11.2 unplugin-element-plus: ^0.11.2
vee-validate: ^4.15.1 vee-validate: ^4.15.1
vite: ^7.3.1 vite: ^8.0.0
vite-plugin-compression: ^0.5.1 vite-plugin-compression: ^0.5.1
vite-plugin-dts: ^4.5.4 vite-plugin-dts: ^4.5.4
vite-plugin-html: ^3.2.2 vite-plugin-html: ^3.2.2
@@ -176,7 +183,9 @@ catalog:
vite-plugin-pwa: ^1.2.0 vite-plugin-pwa: ^1.2.0
vite-plugin-vue-devtools: ^8.1.0 vite-plugin-vue-devtools: ^8.1.0
vitepress: ^1.6.4 vitepress: ^1.6.4
vitepress-plugin-graphviz: ^0.0.1
vitepress-plugin-group-icons: ^1.7.1 vitepress-plugin-group-icons: ^1.7.1
vitepress-plugin-llms: ^1.11.0
vitest: ^4.1.0 vitest: ^4.1.0
vue: ^3.5.30 vue: ^3.5.30
vue-eslint-parser: ^10.4.0 vue-eslint-parser: ^10.4.0
@@ -185,9 +194,12 @@ catalog:
vue-router: ^5.0.3 vue-router: ^5.0.3
vue-tippy: ^6.7.1 vue-tippy: ^6.7.1
vue-tsc: ^3.2.5 vue-tsc: ^3.2.5
vxe-pc-ui: ^4.13.4 vxe-pc-ui: ^4.13.5
vxe-table: ^4.18.2 vxe-table: ^4.18.2
watermark-js-plus: ^1.6.3 watermark-js-plus: ^1.6.3
yaml-eslint-parser: ^2.0.0 yaml-eslint-parser: ^2.0.0
zod: ^3.25.76 zod: ^3.25.76
zod-defaults: 0.1.3 zod-defaults: 0.1.3
catalogs:
conflicts_vitepress_h2_0_0malpha_16:
vitepress: ^2.0.0-alpha.16