Browse Source

fix: page spinner is styled incorrectly when scrolling (#4163)

* feat: add contributor information to documents

* fix: page spinner is styled incorrectly when scrolling
Vben 7 months ago
parent
commit
debb32d353

+ 10 - 0
docs/.vitepress/config.mts

@@ -2,6 +2,10 @@ import type { DefaultTheme, HeadConfig } from 'vitepress';
 
 import { resolve } from 'node:path';
 
+import {
+  GitChangelog,
+  GitChangelogMarkdownSection,
+} from '@nolebase/vitepress-plugin-git-changelog/vite';
 import { type PwaOptions, withPwa } from '@vite-pwa/vitepress';
 import { defineConfigWithTheme } from 'vitepress';
 
@@ -98,6 +102,12 @@ export default withPwa(
       json: {
         stringify: true,
       },
+      plugins: [
+        GitChangelog({
+          repoURL: () => 'https://github.com/vbenjs/vue-vben-admin',
+        }),
+        GitChangelogMarkdownSection(),
+      ],
       server: {
         fs: {
           allow: ['../..'],

+ 4 - 1
docs/.vitepress/theme/index.ts

@@ -1,6 +1,7 @@
 // https://vitepress.dev/guide/custom-theme
 import type { Theme } from 'vitepress';
 
+import { NolebaseGitChangelogPlugin } from '@nolebase/vitepress-plugin-git-changelog/client';
 import DefaultTheme from 'vitepress/theme';
 
 import SiteLayout from './components/site-layout.vue';
@@ -9,11 +10,13 @@ import { initHmPlugin } from './plugins/hm';
 
 import './styles';
 
+import '@nolebase/vitepress-plugin-git-changelog/client/style.css';
+
 export default {
   enhanceApp({ app }) {
     // ...
     app.component('VbenContributors', VbenContributors);
-
+    app.use(NolebaseGitChangelogPlugin);
     // 百度统计
     initHmPlugin();
   },

+ 1 - 0
docs/package.json

@@ -11,6 +11,7 @@
     "medium-zoom": "^1.1.0"
   },
   "devDependencies": {
+    "@nolebase/vitepress-plugin-git-changelog": "^2.4.0",
     "@vite-pwa/vitepress": "^0.5.0",
     "vitepress": "^1.3.2",
     "vue": "^3.4.37"

+ 3 - 3
docs/src/guide/in-depth/theme.md

@@ -223,7 +223,7 @@ css 变量内的颜色,必须使用 `hsl` 格式,如 `0 0% 100%`,不需要
 
 你只需要在你的项目中覆盖你想要修改的 CSS 变量即可。例如,要更改默认卡片背景色,你可以在你的 CSS 文件中添加以下内容进行覆盖:
 
-### 默认主题下
+### 默认主题下
 
 ```css
 :root {
@@ -1222,7 +1222,7 @@ export const overridesPreferences = defineOverridesPreferences({
 
 侧边栏颜色通过`--sidebar`变量来配置
 
-### 默认主题下
+### 默认主题下
 
 ```css
 :root {
@@ -1244,7 +1244,7 @@ export const overridesPreferences = defineOverridesPreferences({
 
 侧边栏颜色通过`--header`变量来配置
 
-### 默认主题下
+### 默认主题下
 
 ```css
 :root {

+ 1 - 1
internal/vite-config/src/plugins/index.ts

@@ -23,7 +23,7 @@ import { viteImportMapPlugin } from './importmap';
 import { viteInjectAppLoadingPlugin } from './inject-app-loading';
 import { viteMetadataPlugin } from './inject-metadata';
 import { viteLicensePlugin } from './license';
-import { viteNitroMockPlugin } from './nitor-mock';
+import { viteNitroMockPlugin } from './nitro-mock';
 import { vitePrintPlugin } from './print';
 
 /**

+ 0 - 0
internal/vite-config/src/plugins/nitor-mock.ts → internal/vite-config/src/plugins/nitro-mock.ts


+ 1 - 0
packages/@core/base/shared/src/constants/globals.ts

@@ -3,6 +3,7 @@
  * @en_US Layout content height
  */
 export const CSS_VARIABLE_LAYOUT_CONTENT_HEIGHT = `--vben-content-height`;
+export const CSS_VARIABLE_LAYOUT_CONTENT_WIDTH = `--vben-content-width`;
 
 /**
  * @zh_CN 默认命名空间

+ 103 - 116
packages/@core/base/shared/src/utils/dom.test.ts

@@ -1,140 +1,127 @@
-import { afterAll, beforeAll, describe, expect, it, vi } from 'vitest';
-
-import { getElementVisibleHeight } from './dom'; // 假设函数位于 utils.ts 中
-
-describe('getElementVisibleHeight', () => {
-  // Mocking the getBoundingClientRect method
-  const mockGetBoundingClientRect = vi.fn();
-  const originalGetBoundingClientRect = Element.prototype.getBoundingClientRect;
-
-  beforeAll(() => {
-    // Mock getBoundingClientRect method
-    Element.prototype.getBoundingClientRect = mockGetBoundingClientRect;
-  });
-
-  afterAll(() => {
-    // Restore original getBoundingClientRect method
-    Element.prototype.getBoundingClientRect = originalGetBoundingClientRect;
+import { beforeEach, describe, expect, it, vi } from 'vitest';
+
+import { getElementVisibleRect } from './dom'; // 假设函数位于 utils.ts 中
+
+describe('getElementVisibleRect', () => {
+  // 设置浏览器视口尺寸的 mock
+  beforeEach(() => {
+    vi.spyOn(document.documentElement, 'clientHeight', 'get').mockReturnValue(
+      800,
+    );
+    vi.spyOn(window, 'innerHeight', 'get').mockReturnValue(800);
+    vi.spyOn(document.documentElement, 'clientWidth', 'get').mockReturnValue(
+      1000,
+    );
+    vi.spyOn(window, 'innerWidth', 'get').mockReturnValue(1000);
   });
 
-  it('should return 0 if the element is null or undefined', () => {
-    expect(getElementVisibleHeight(null)).toBe(0);
-    expect(getElementVisibleHeight()).toBe(0);
-  });
-
-  it('should return the visible height of the element', () => {
-    // Mock the getBoundingClientRect return value
-    mockGetBoundingClientRect.mockReturnValue({
-      bottom: 500,
-      height: 400,
+  it('should return default rect if element is undefined', () => {
+    expect(getElementVisibleRect()).toEqual({
+      bottom: 0,
+      height: 0,
       left: 0,
       right: 0,
-      toJSON: () => ({}),
-      top: 100,
+      top: 0,
       width: 0,
-      x: 0,
-      y: 0,
-    });
-
-    const mockElement = document.createElement('div');
-    document.body.append(mockElement);
-
-    // Mocking window.innerHeight and document.documentElement.clientHeight
-    const originalInnerHeight = window.innerHeight;
-    const originalClientHeight = document.documentElement.clientHeight;
-
-    Object.defineProperty(window, 'innerHeight', {
-      value: 600,
-      writable: true,
-    });
-
-    Object.defineProperty(document.documentElement, 'clientHeight', {
-      value: 600,
-      writable: true,
-    });
-
-    expect(getElementVisibleHeight(mockElement)).toBe(400);
-
-    // Restore original values
-    Object.defineProperty(window, 'innerHeight', {
-      value: originalInnerHeight,
-      writable: true,
-    });
-
-    Object.defineProperty(document.documentElement, 'clientHeight', {
-      value: originalClientHeight,
-      writable: true,
     });
-
-    mockElement.remove();
   });
 
-  it('should return the visible height when element is partially out of viewport', () => {
-    // Mock the getBoundingClientRect return value
-    mockGetBoundingClientRect.mockReturnValue({
-      bottom: 300,
-      height: 400,
+  it('should return default rect if element is null', () => {
+    expect(getElementVisibleRect(null)).toEqual({
+      bottom: 0,
+      height: 0,
       left: 0,
       right: 0,
-      toJSON: () => ({}),
-      top: -100,
+      top: 0,
       width: 0,
-      x: 0,
-      y: 0,
-    });
-
-    const mockElement = document.createElement('div');
-    document.body.append(mockElement);
-
-    // Mocking window.innerHeight and document.documentElement.clientHeight
-    const originalInnerHeight = window.innerHeight;
-    const originalClientHeight = document.documentElement.clientHeight;
-
-    Object.defineProperty(window, 'innerHeight', {
-      value: 600,
-      writable: true,
     });
+  });
 
-    Object.defineProperty(document.documentElement, 'clientHeight', {
-      value: 600,
-      writable: true,
+  it('should return correct visible rect when element is fully visible', () => {
+    const element = {
+      getBoundingClientRect: () => ({
+        bottom: 400,
+        height: 300,
+        left: 200,
+        right: 600,
+        top: 100,
+        width: 400,
+      }),
+    } as HTMLElement;
+
+    expect(getElementVisibleRect(element)).toEqual({
+      bottom: 400,
+      height: 300,
+      left: 200,
+      right: 600,
+      top: 100,
+      width: 400,
     });
+  });
 
-    expect(getElementVisibleHeight(mockElement)).toBe(300);
-
-    // Restore original values
-    Object.defineProperty(window, 'innerHeight', {
-      value: originalInnerHeight,
-      writable: true,
+  it('should return correct visible rect when element is partially off-screen at the top', () => {
+    const element = {
+      getBoundingClientRect: () => ({
+        bottom: 200,
+        height: 250,
+        left: 100,
+        right: 500,
+        top: -50,
+        width: 400,
+      }),
+    } as HTMLElement;
+
+    expect(getElementVisibleRect(element)).toEqual({
+      bottom: 200,
+      height: 200,
+      left: 100,
+      right: 500,
+      top: 0,
+      width: 400,
     });
+  });
 
-    Object.defineProperty(document.documentElement, 'clientHeight', {
-      value: originalClientHeight,
-      writable: true,
+  it('should return correct visible rect when element is partially off-screen at the right', () => {
+    const element = {
+      getBoundingClientRect: () => ({
+        bottom: 400,
+        height: 300,
+        left: 800,
+        right: 1200,
+        top: 100,
+        width: 400,
+      }),
+    } as HTMLElement;
+
+    expect(getElementVisibleRect(element)).toEqual({
+      bottom: 400,
+      height: 300,
+      left: 800,
+      right: 1000,
+      top: 100,
+      width: 200,
     });
-
-    mockElement.remove();
   });
 
-  it('should return 0 if the element is completely out of viewport', () => {
-    // Mock the getBoundingClientRect return value
-    mockGetBoundingClientRect.mockReturnValue({
-      bottom: -100,
-      height: 400,
-      left: 0,
-      right: 0,
-      toJSON: () => ({}),
-      top: -500,
+  it('should return all zeros when element is completely off-screen', () => {
+    const element = {
+      getBoundingClientRect: () => ({
+        bottom: 1200,
+        height: 300,
+        left: 1100,
+        right: 1400,
+        top: 900,
+        width: 300,
+      }),
+    } as HTMLElement;
+
+    expect(getElementVisibleRect(element)).toEqual({
+      bottom: 800,
+      height: 0,
+      left: 1100,
+      right: 1000,
+      top: 900,
       width: 0,
-      x: 0,
-      y: 0,
     });
-
-    const mockElement = document.createElement('div');
-    document.body.append(mockElement);
-
-    expect(getElementVisibleHeight(mockElement)).toBe(0);
-
-    mockElement.remove();
   });
 });

+ 36 - 7
packages/@core/base/shared/src/utils/dom.ts

@@ -1,12 +1,28 @@
+export interface VisibleDomRect {
+  bottom: number;
+  height: number;
+  left: number;
+  right: number;
+  top: number;
+  width: number;
+}
+
 /**
- * 获取元素可见高度
+ * 获取元素可见信息
  * @param element
  */
-function getElementVisibleHeight(
+export function getElementVisibleRect(
   element?: HTMLElement | null | undefined,
-): number {
+): VisibleDomRect {
   if (!element) {
-    return 0;
+    return {
+      bottom: 0,
+      height: 0,
+      left: 0,
+      right: 0,
+      top: 0,
+      width: 0,
+    };
   }
   const rect = element.getBoundingClientRect();
   const viewHeight = Math.max(
@@ -17,7 +33,20 @@ function getElementVisibleHeight(
   const top = Math.max(rect.top, 0);
   const bottom = Math.min(rect.bottom, viewHeight);
 
-  return Math.max(0, bottom - top);
-}
+  const viewWidth = Math.max(
+    document.documentElement.clientWidth,
+    window.innerWidth,
+  );
+
+  const left = Math.max(rect.left, 0);
+  const right = Math.min(rect.right, viewWidth);
 
-export { getElementVisibleHeight };
+  return {
+    bottom,
+    height: Math.max(0, bottom - top),
+    left,
+    right,
+    top,
+    width: Math.max(0, right - left),
+  };
+}

+ 1 - 1
packages/@core/composables/src/index.ts

@@ -1,4 +1,4 @@
-export * from './use-content-height';
+export * from './use-content-style';
 export * from './use-namespace';
 export * from './use-sortable';
 export {

+ 0 - 47
packages/@core/composables/src/use-content-height.ts

@@ -1,47 +0,0 @@
-import { computed, onMounted, ref, watch } from 'vue';
-
-import {
-  CSS_VARIABLE_LAYOUT_CONTENT_HEIGHT,
-  getElementVisibleHeight,
-} from '@vben-core/shared';
-
-import { useCssVar, useDebounceFn, useWindowSize } from '@vueuse/core';
-/**
- * @zh_CN 获取内容高度(可视区域,不包含滚动条)
- */
-function useContentHeight() {
-  const contentHeight = useCssVar(CSS_VARIABLE_LAYOUT_CONTENT_HEIGHT);
-
-  const contentStyles = computed(() => {
-    return {
-      height: `var(${CSS_VARIABLE_LAYOUT_CONTENT_HEIGHT})`,
-    };
-  });
-
-  return { contentHeight, contentStyles };
-}
-
-/**
- * @zh_CN 创建内容高度监听
- */
-function useContentHeightListener() {
-  const contentElement = ref<HTMLDivElement | null>(null);
-
-  const { height, width } = useWindowSize();
-  const contentHeight = useCssVar(CSS_VARIABLE_LAYOUT_CONTENT_HEIGHT);
-  const debouncedCalcHeight = useDebounceFn(() => {
-    contentHeight.value = `${getElementVisibleHeight(contentElement.value)}px`;
-  }, 200);
-
-  watch([height, width], () => {
-    debouncedCalcHeight();
-  });
-
-  onMounted(() => {
-    debouncedCalcHeight();
-  });
-
-  return { contentElement };
-}
-
-export { useContentHeight, useContentHeightListener };

+ 55 - 0
packages/@core/composables/src/use-content-style.ts

@@ -0,0 +1,55 @@
+import type { CSSProperties } from 'vue';
+import { computed, nextTick, onMounted, ref } from 'vue';
+
+import {
+  CSS_VARIABLE_LAYOUT_CONTENT_HEIGHT,
+  CSS_VARIABLE_LAYOUT_CONTENT_WIDTH,
+  getElementVisibleRect,
+  type VisibleDomRect,
+} from '@vben-core/shared';
+
+import { useCssVar, useDebounceFn } from '@vueuse/core';
+
+/**
+ * @zh_CN content style
+ */
+function useContentStyle() {
+  const contentElement = ref<HTMLDivElement | null>(null);
+  const visibleDomRect = ref<null | VisibleDomRect>(null);
+  const contentHeight = useCssVar(CSS_VARIABLE_LAYOUT_CONTENT_HEIGHT);
+  const contentWidth = useCssVar(CSS_VARIABLE_LAYOUT_CONTENT_WIDTH);
+
+  const overlayStyle = computed((): CSSProperties => {
+    const { height, left, top, width } = visibleDomRect.value ?? {};
+    return {
+      height: `${height}px`,
+      left: `${left}px`,
+      position: 'fixed',
+      top: `${top}px`,
+      width: `${width}px`,
+      zIndex: 1000,
+    };
+  });
+
+  const debouncedCalcHeight = useDebounceFn(
+    (_entries: ResizeObserverEntry[]) => {
+      visibleDomRect.value = getElementVisibleRect(contentElement.value);
+      contentHeight.value = `${visibleDomRect.value.height}px`;
+      contentWidth.value = `${visibleDomRect.value.width}px`;
+    },
+    100,
+  );
+
+  onMounted(() => {
+    nextTick(() => {
+      if (contentElement.value) {
+        const observer = new ResizeObserver(debouncedCalcHeight);
+        observer.observe(contentElement.value);
+      }
+    });
+  });
+
+  return { contentElement, overlayStyle, visibleDomRect };
+}
+
+export { useContentStyle };

+ 5 - 3
packages/@core/ui-kit/layout-ui/src/components/layout-content.vue

@@ -4,7 +4,7 @@ import type { ContentCompactType } from '@vben-core/typings';
 import type { CSSProperties } from 'vue';
 import { computed } from 'vue';
 
-import { useContentHeightListener } from '@vben-core/composables';
+import { useContentStyle } from '@vben-core/composables';
 
 interface Props {
   /**
@@ -24,7 +24,7 @@ interface Props {
 
 const props = withDefaults(defineProps<Props>(), {});
 
-const { contentElement } = useContentHeightListener();
+const { contentElement, overlayStyle } = useContentStyle();
 
 const style = computed((): CSSProperties => {
   const {
@@ -53,7 +53,9 @@ const style = computed((): CSSProperties => {
 </script>
 
 <template>
-  <main ref="contentElement" :style="style" class="bg-background-deep">
+  <main ref="contentElement" :style="style" class="bg-background-deep relative">
+    <!-- <BlurShadow :style="shadowStyle" /> -->
+    <slot :overlay-style="overlayStyle" name="overlay"></slot>
     <slot></slot>
   </main>
 </template>

+ 4 - 0
packages/@core/ui-kit/layout-ui/src/vben-layout.vue

@@ -519,6 +519,10 @@ function handleOpenMenu() {
         class="transition-[margin-top] duration-200"
       >
         <slot name="content"></slot>
+
+        <template #overlay="{ overlayStyle }">
+          <slot :overlay-style="overlayStyle" name="content-overlay"></slot>
+        </template>
       </LayoutContent>
 
       <LayoutFooter

+ 16 - 0
packages/effects/layouts/src/basic/content/content-spinner.vue

@@ -0,0 +1,16 @@
+<script lang="ts" setup>
+import type { CSSProperties } from 'vue';
+
+import { VbenSpinner } from '@vben-core/shadcn-ui';
+
+import { useContentSpinner } from './use-content-spinner';
+
+defineOptions({ name: 'LayoutContentSpinner' });
+
+defineProps<{ overlayStyle: CSSProperties }>();
+
+const { spinning } = useContentSpinner();
+</script>
+<template>
+  <VbenSpinner :spinning="spinning" :style="overlayStyle" />
+</template>

+ 0 - 10
packages/effects/layouts/src/basic/content/content.vue

@@ -7,20 +7,15 @@ import type {
 import { type VNode } from 'vue';
 import { RouterView } from 'vue-router';
 
-import { useContentHeight } from '@vben/hooks';
 import { preferences, usePreferences } from '@vben/preferences';
 import { storeToRefs, useTabbarStore } from '@vben/stores';
-import { VbenSpinner } from '@vben-core/shadcn-ui';
 
 import { IFrameRouterView } from '../../iframe';
-import { useContentSpinner } from './use-content-spinner';
 
 defineOptions({ name: 'LayoutContent' });
 
 const tabbarStore = useTabbarStore();
 const { keepAlive } = usePreferences();
-const { spinning } = useContentSpinner();
-const { contentStyles } = useContentHeight();
 
 const { getCachedTabs, getExcludeCachedTabs, renderRouteView } =
   storeToRefs(tabbarStore);
@@ -86,11 +81,6 @@ function transformComponent(
 
 <template>
   <div class="relative h-full">
-    <VbenSpinner
-      v-if="preferences.transition.loading"
-      :spinning="spinning"
-      :style="contentStyles"
-    />
     <IFrameRouterView />
     <RouterView v-slot="{ Component, route }">
       <Transition :name="getTransitionName(route)" appear mode="out-in">

+ 1 - 0
packages/effects/layouts/src/basic/content/index.ts

@@ -1 +1,2 @@
 export { default as LayoutContent } from './content.vue';
+export { default as LayoutContentSpinner } from './content-spinner.vue';

+ 7 - 1
packages/effects/layouts/src/basic/layout.vue

@@ -16,7 +16,7 @@ import { VbenAdminLayout } from '@vben-core/layout-ui';
 import { Toaster, VbenBackTop, VbenLogo } from '@vben-core/shadcn-ui';
 
 import { Breadcrumb, CheckUpdates, Preferences } from '../widgets';
-import { LayoutContent } from './content';
+import { LayoutContent, LayoutContentSpinner } from './content';
 import { Copyright } from './copyright';
 import { LayoutFooter } from './footer';
 import { LayoutHeader } from './header';
@@ -297,6 +297,12 @@ const headerSlots = computed(() => {
     <template #content>
       <LayoutContent />
     </template>
+    <template
+      v-if="preferences.transition.loading"
+      #content-overlay="{ overlayStyle }"
+    >
+      <LayoutContentSpinner :overlay-style="overlayStyle" />
+    </template>
 
     <!-- 页脚 -->
     <template v-if="preferences.footer.enable" #footer>

+ 10 - 8
playground/src/views/demos/features/clipboard/index.vue

@@ -4,7 +4,7 @@ import { ref } from 'vue';
 import { Page } from '@vben/common-ui';
 
 import { useClipboard } from '@vueuse/core';
-import { Button, Input } from 'ant-design-vue';
+import { Button, Card, Input } from 'ant-design-vue';
 
 const source = ref('Hello');
 const { copy, text } = useClipboard({ source });
@@ -12,12 +12,14 @@ const { copy, text } = useClipboard({ source });
 
 <template>
   <Page title="剪切板示例">
-    <p class="mb-3">
-      Current copied: <code>{{ text || 'none' }}</code>
-    </p>
-    <Input.Group class="flex">
-      <Input v-model:value="source" placeholder="请输入" />
-      <Button type="primary" @click="copy(source)"> Copy </Button>
-    </Input.Group>
+    <Card title="基本使用">
+      <p class="mb-3">
+        Current copied: <code>{{ text || 'none' }}</code>
+      </p>
+      <div class="flex">
+        <Input class="mr-3 flex w-[200px]" />
+        <Button type="primary" @click="copy(source)"> Copy </Button>
+      </div>
+    </Card>
   </Page>
 </template>

+ 1 - 1
playground/src/views/demos/features/full-screen/index.vue

@@ -31,7 +31,7 @@ const { isFullscreen: isDomFullscreen, toggle: toggleDom } =
       </div>
     </Card>
 
-    <Card class="mt-3" title="Dom Full Screen">
+    <Card class="mt-5" title="Dom Full Screen">
       <Button type="primary" @click="toggleDom"> Enter Dom Full Screen </Button>
     </Card>
 

+ 289 - 58
pnpm-lock.yaml

@@ -57,10 +57,10 @@ importers:
         version: link:scripts/vsh
       '@vitejs/plugin-vue':
         specifier: ^5.1.2
-        version: 5.1.2(vite@5.4.0(@types/node@22.3.0)(sass@1.77.8)(terser@5.31.3))(vue@3.4.37(typescript@5.5.4))
+        version: 5.1.2(vite@5.4.0(@types/node@22.3.0)(less@4.2.0)(sass@1.77.8)(terser@5.31.3))(vue@3.4.37(typescript@5.5.4))
       '@vitejs/plugin-vue-jsx':
         specifier: ^4.0.1
-        version: 4.0.1(vite@5.4.0(@types/node@22.3.0)(sass@1.77.8)(terser@5.31.3))(vue@3.4.37(typescript@5.5.4))
+        version: 4.0.1(vite@5.4.0(@types/node@22.3.0)(less@4.2.0)(sass@1.77.8)(terser@5.31.3))(vue@3.4.37(typescript@5.5.4))
       '@vue/test-utils':
         specifier: ^2.4.6
         version: 2.4.6
@@ -102,10 +102,10 @@ importers:
         version: 2.0.0(sass@1.77.8)(typescript@5.5.4)(vue-tsc@2.0.29(typescript@5.5.4))
       vite:
         specifier: ^5.4.0
-        version: 5.4.0(@types/node@22.3.0)(sass@1.77.8)(terser@5.31.3)
+        version: 5.4.0(@types/node@22.3.0)(less@4.2.0)(sass@1.77.8)(terser@5.31.3)
       vitest:
         specifier: ^2.0.5
-        version: 2.0.5(@types/node@22.3.0)(jsdom@24.1.1)(sass@1.77.8)(terser@5.31.3)
+        version: 2.0.5(@types/node@22.3.0)(jsdom@24.1.1)(less@4.2.0)(sass@1.77.8)(terser@5.31.3)
       vue:
         specifier: ^3.4.37
         version: 3.4.37(typescript@5.5.4)
@@ -315,12 +315,15 @@ importers:
         specifier: ^1.1.0
         version: 1.1.0
     devDependencies:
+      '@nolebase/vitepress-plugin-git-changelog':
+        specifier: ^2.4.0
+        version: 2.4.0(@algolia/client-search@4.24.0)(@types/node@22.3.0)(async-validator@4.2.5)(axios@1.7.4)(nprogress@0.2.0)(postcss@8.4.41)(qrcode@1.5.4)(sass@1.77.8)(search-insights@2.16.0)(sortablejs@1.15.2)(terser@5.31.3)(typescript@5.5.4)
       '@vite-pwa/vitepress':
         specifier: ^0.5.0
-        version: 0.5.0(vite-plugin-pwa@0.20.1(vite@5.4.0(@types/node@22.3.0)(sass@1.77.8)(terser@5.31.3))(workbox-build@7.1.1)(workbox-window@7.1.0))
+        version: 0.5.0(vite-plugin-pwa@0.20.1(vite@5.4.0(@types/node@22.3.0)(less@4.2.0)(sass@1.77.8)(terser@5.31.3))(workbox-build@7.1.1)(workbox-window@7.1.0))
       vitepress:
         specifier: ^1.3.2
-        version: 1.3.2(@algolia/client-search@4.24.0)(@types/node@22.3.0)(async-validator@4.2.5)(axios@1.7.4)(nprogress@0.2.0)(postcss@8.4.41)(qrcode@1.5.4)(sass@1.77.8)(search-insights@2.16.0)(sortablejs@1.15.2)(terser@5.31.3)(typescript@5.5.4)
+        version: 1.3.2(@algolia/client-search@4.24.0)(@types/node@22.3.0)(async-validator@4.2.5)(axios@1.7.4)(less@4.2.0)(nprogress@0.2.0)(postcss@8.4.41)(qrcode@1.5.4)(sass@1.77.8)(search-insights@2.16.0)(sortablejs@1.15.2)(terser@5.31.3)(typescript@5.5.4)
       vue:
         specifier: ^3.4.37
         version: 3.4.37(typescript@5.5.4)
@@ -408,7 +411,7 @@ importers:
         version: 4.1.3(@typescript-eslint/eslint-plugin@8.1.0(@typescript-eslint/parser@8.1.0(eslint@9.9.0(jiti@1.21.6))(typescript@5.5.4))(eslint@9.9.0(jiti@1.21.6))(typescript@5.5.4))(eslint@9.9.0(jiti@1.21.6))
       eslint-plugin-vitest:
         specifier: ^0.5.4
-        version: 0.5.4(@typescript-eslint/eslint-plugin@8.1.0(@typescript-eslint/parser@8.1.0(eslint@9.9.0(jiti@1.21.6))(typescript@5.5.4))(eslint@9.9.0(jiti@1.21.6))(typescript@5.5.4))(eslint@9.9.0(jiti@1.21.6))(typescript@5.5.4)(vitest@2.0.5(@types/node@22.3.0)(jsdom@24.1.1)(sass@1.77.8)(terser@5.31.3))
+        version: 0.5.4(@typescript-eslint/eslint-plugin@8.1.0(@typescript-eslint/parser@8.1.0(eslint@9.9.0(jiti@1.21.6))(typescript@5.5.4))(eslint@9.9.0(jiti@1.21.6))(typescript@5.5.4))(eslint@9.9.0(jiti@1.21.6))(typescript@5.5.4)(vitest@2.0.5(@types/node@22.3.0)(jsdom@24.1.1)(less@4.2.0)(sass@1.77.8)(terser@5.31.3))
       eslint-plugin-vue:
         specifier: ^9.27.0
         version: 9.27.0(eslint@9.9.0(jiti@1.21.6))
@@ -573,7 +576,7 @@ importers:
         version: link:../../packages/types
       vite:
         specifier: ^5.4.0
-        version: 5.4.0(@types/node@22.3.0)(sass@1.77.8)(terser@5.31.3)
+        version: 5.4.0(@types/node@22.3.0)(less@4.2.0)(sass@1.77.8)(terser@5.31.3)
 
   internal/vite-config:
     dependencies:
@@ -600,13 +603,13 @@ importers:
         version: 2.0.2
       vite-plugin-lib-inject-css:
         specifier: ^2.1.1
-        version: 2.1.1(vite@5.4.0(@types/node@22.3.0)(sass@1.77.8)(terser@5.31.3))
+        version: 2.1.1(vite@5.4.0(@types/node@22.3.0)(less@4.2.0)(sass@1.77.8)(terser@5.31.3))
       vite-plugin-pwa:
         specifier: ^0.20.1
-        version: 0.20.1(vite@5.4.0(@types/node@22.3.0)(sass@1.77.8)(terser@5.31.3))(workbox-build@7.1.1)(workbox-window@7.1.0)
+        version: 0.20.1(vite@5.4.0(@types/node@22.3.0)(less@4.2.0)(sass@1.77.8)(terser@5.31.3))(workbox-build@7.1.1)(workbox-window@7.1.0)
       vite-plugin-vue-devtools:
         specifier: ^7.3.8
-        version: 7.3.8(rollup@4.20.0)(vite@5.4.0(@types/node@22.3.0)(sass@1.77.8)(terser@5.31.3))(vue@3.4.37(typescript@5.5.4))
+        version: 7.3.8(rollup@4.20.0)(vite@5.4.0(@types/node@22.3.0)(less@4.2.0)(sass@1.77.8)(terser@5.31.3))(vue@3.4.37(typescript@5.5.4))
     devDependencies:
       '@types/html-minifier-terser':
         specifier: ^7.0.2
@@ -616,10 +619,10 @@ importers:
         version: link:../node-utils
       '@vitejs/plugin-vue':
         specifier: ^5.1.2
-        version: 5.1.2(vite@5.4.0(@types/node@22.3.0)(sass@1.77.8)(terser@5.31.3))(vue@3.4.37(typescript@5.5.4))
+        version: 5.1.2(vite@5.4.0(@types/node@22.3.0)(less@4.2.0)(sass@1.77.8)(terser@5.31.3))(vue@3.4.37(typescript@5.5.4))
       '@vitejs/plugin-vue-jsx':
         specifier: ^4.0.1
-        version: 4.0.1(vite@5.4.0(@types/node@22.3.0)(sass@1.77.8)(terser@5.31.3))(vue@3.4.37(typescript@5.5.4))
+        version: 4.0.1(vite@5.4.0(@types/node@22.3.0)(less@4.2.0)(sass@1.77.8)(terser@5.31.3))(vue@3.4.37(typescript@5.5.4))
       dayjs:
         specifier: ^1.11.12
         version: 1.11.12
@@ -637,16 +640,16 @@ importers:
         version: 1.77.8
       vite:
         specifier: ^5.4.0
-        version: 5.4.0(@types/node@22.3.0)(sass@1.77.8)(terser@5.31.3)
+        version: 5.4.0(@types/node@22.3.0)(less@4.2.0)(sass@1.77.8)(terser@5.31.3)
       vite-plugin-compression:
         specifier: ^0.5.1
-        version: 0.5.1(vite@5.4.0(@types/node@22.3.0)(sass@1.77.8)(terser@5.31.3))
+        version: 0.5.1(vite@5.4.0(@types/node@22.3.0)(less@4.2.0)(sass@1.77.8)(terser@5.31.3))
       vite-plugin-dts:
         specifier: 4.0.3
-        version: 4.0.3(@types/node@22.3.0)(rollup@4.20.0)(typescript@5.5.4)(vite@5.4.0(@types/node@22.3.0)(sass@1.77.8)(terser@5.31.3))
+        version: 4.0.3(@types/node@22.3.0)(rollup@4.20.0)(typescript@5.5.4)(vite@5.4.0(@types/node@22.3.0)(less@4.2.0)(sass@1.77.8)(terser@5.31.3))
       vite-plugin-html:
         specifier: ^3.2.2
-        version: 3.2.2(vite@5.4.0(@types/node@22.3.0)(sass@1.77.8)(terser@5.31.3))
+        version: 3.2.2(vite@5.4.0(@types/node@22.3.0)(less@4.2.0)(sass@1.77.8)(terser@5.31.3))
 
   packages/@core/base/design: {}
 
@@ -3255,6 +3258,9 @@ packages:
     resolution: {integrity: sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==}
     engines: {node: '>=18.18'}
 
+  '@iconify-json/octicon@1.1.57':
+    resolution: {integrity: sha512-ruzC4/zCOHoYP7nY9aGg7Pc8K9l+w1m03kHfhJgJwqHwqcLJWK8Bm+ZoINLupvQbB6GX5q11LATSX+0U/aOUpA==}
+
   '@iconify/json@2.2.237':
     resolution: {integrity: sha512-lMK5I9JX90L2LR18Lz6C5XrivxxAGejdJvFQI7TQkj03WcaxRJlciPbQb6z4nX+DS1T6k591ZQ2/hyRVbjqrgA==}
 
@@ -3353,7 +3359,6 @@ packages:
 
   '@ls-lint/ls-lint@2.2.3':
     resolution: {integrity: sha512-ekM12jNm/7O2I/hsRv9HvYkRdfrHpiV1epVuI2NP+eTIcEgdIdKkKCs9KgQydu/8R5YXTov9aHdOgplmCHLupw==}
-    cpu: [x64, arm64, s390x]
     os: [darwin, linux, win32]
     hasBin: true
 
@@ -3416,6 +3421,12 @@ packages:
     resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
     engines: {node: '>= 8'}
 
+  '@nolebase/ui@2.4.0':
+    resolution: {integrity: sha512-xkcPq6G1E94PStNQtBQnfDNHqMNRLJLpLNuQA85k8ZazHWu7MiUodrKFYObOkS7NRhQT0bH2jk/Vbi+vskJuZQ==}
+
+  '@nolebase/vitepress-plugin-git-changelog@2.4.0':
+    resolution: {integrity: sha512-7LBojOHiK/s6hxKdAb94ULau1TGfjRks3uYS/zEgK7R+DUpVUbz1fuXc/X+AYwKzErPmEqj/ACK9vjsG2XkcKA==}
+
   '@npmcli/fs@1.1.1':
     resolution: {integrity: sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==}
 
@@ -4922,6 +4933,9 @@ packages:
   cookie-es@1.2.2:
     resolution: {integrity: sha512-+W7VmiVINB+ywl1HGXJXmrqkOhpKrIiVZV6tQuV54ZyQC7MMuBt81Vc336GMLoHBq5hV/F9eXgt5Mnx0Rha5Fg==}
 
+  copy-anything@2.0.6:
+    resolution: {integrity: sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==}
+
   copy-anything@3.0.5:
     resolution: {integrity: sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==}
     engines: {node: '>=12.13'}
@@ -5166,6 +5180,9 @@ packages:
     resolution: {integrity: sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==}
     engines: {node: '>=0.11'}
 
+  date-fns@3.6.0:
+    resolution: {integrity: sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==}
+
   dayjs@1.11.12:
     resolution: {integrity: sha512-Rt2g+nTbLlDWZTwwrIXjy9MeiZmSDI375FvZs72ngxx8PDC6YXOeR3q5LAuPzjZQxhiWdRKac7RKV+YyQYfYIg==}
 
@@ -5467,6 +5484,10 @@ packages:
   err-code@2.0.3:
     resolution: {integrity: sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==}
 
+  errno@0.1.8:
+    resolution: {integrity: sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==}
+    hasBin: true
+
   error-ex@1.3.2:
     resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==}
 
@@ -5500,6 +5521,9 @@ packages:
     resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==}
     engines: {node: '>= 0.4'}
 
+  es-toolkit@1.15.1:
+    resolution: {integrity: sha512-2rPCylgxxpgZ3jQLyvbm+B9dNAMdHv4S80iabK9njEWxDbObhAPJCQUpqHv8iaOZrfprl3UlWhfxZd7kKSQtbg==}
+
   esbuild@0.19.12:
     resolution: {integrity: sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==}
     engines: {node: '>=12'}
@@ -5788,6 +5812,10 @@ packages:
     resolution: {integrity: sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==}
     engines: {node: '>=0.10.0'}
 
+  extend-shallow@2.0.1:
+    resolution: {integrity: sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==}
+    engines: {node: '>=0.10.0'}
+
   extendable-error@0.1.7:
     resolution: {integrity: sha512-UOiS2in6/Q0FK0R0q6UY9vYpQ21mr/Qn1KOnte7vsACuNJf514WvCCUHSRCPcgjPT2bAhNIJdlE6bVap1GKmeg==}
 
@@ -6150,6 +6178,10 @@ packages:
   graphemer@1.4.0:
     resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==}
 
+  gray-matter@4.0.3:
+    resolution: {integrity: sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==}
+    engines: {node: '>=6.0'}
+
   gzip-size@7.0.0:
     resolution: {integrity: sha512-O1Ld7Dr+nqPnmGpdhzLmMTQ4vAsD+rHwMm1NLUmoUFFymBOMKxCCrtDxqdBRYXdeEPEi3SyoR4TizJLQrnKBNA==}
     engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
@@ -6307,6 +6339,11 @@ packages:
     resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==}
     engines: {node: '>= 4'}
 
+  image-size@0.5.5:
+    resolution: {integrity: sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==}
+    engines: {node: '>=0.10.0'}
+    hasBin: true
+
   immutable@4.3.7:
     resolution: {integrity: sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw==}
 
@@ -6417,6 +6454,10 @@ packages:
     engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
     hasBin: true
 
+  is-extendable@0.1.1:
+    resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==}
+    engines: {node: '>=0.10.0'}
+
   is-extglob@2.1.1:
     resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
     engines: {node: '>=0.10.0'}
@@ -6566,6 +6607,9 @@ packages:
   is-weakref@1.0.2:
     resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==}
 
+  is-what@3.14.1:
+    resolution: {integrity: sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==}
+
   is-what@4.1.16:
     resolution: {integrity: sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==}
     engines: {node: '>=12.13'}
@@ -6744,6 +6788,11 @@ packages:
     resolution: {integrity: sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==}
     engines: {node: '>= 0.6.3'}
 
+  less@4.2.0:
+    resolution: {integrity: sha512-P3b3HJDBtSzsXUl0im2L7gTO5Ubg8mEN6G8qoTS77iXxXX4Hvu4Qj540PZDvQ8V6DmX6iXo98k7Md0Cm1PrLaA==}
+    engines: {node: '>=6'}
+    hasBin: true
+
   leven@3.1.0:
     resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==}
     engines: {node: '>=6'}
@@ -6906,6 +6955,10 @@ packages:
   magic-string@0.30.11:
     resolution: {integrity: sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==}
 
+  make-dir@2.1.0:
+    resolution: {integrity: sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==}
+    engines: {node: '>=6'}
+
   make-dir@3.1.0:
     resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==}
     engines: {node: '>=8'}
@@ -7138,6 +7191,11 @@ packages:
   natural-compare@1.4.0:
     resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
 
+  needle@3.3.1:
+    resolution: {integrity: sha512-6k0YULvhpw+RoLNiQCRKOl09Rv1dPLr8hHnVjHqdolKwDrdNyk+Hmrthi4lIGPPz3r39dLx0hsF5s40sZ3Us4Q==}
+    engines: {node: '>= 4.4.x'}
+    hasBin: true
+
   nitropack@2.9.7:
     resolution: {integrity: sha512-aKXvtNrWkOCMsQbsk4A0qQdBjrJ1ZcvwlTQevI/LAgLWLYc5L7Q/YiYxGLal4ITyNSlzir1Cm1D2ZxnYhmpMEw==}
     engines: {node: ^16.11.0 || >=17.0.0}
@@ -7392,6 +7450,10 @@ packages:
     resolution: {integrity: sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==}
     engines: {node: '>=18'}
 
+  parse-node-version@1.0.1:
+    resolution: {integrity: sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==}
+    engines: {node: '>= 0.10'}
+
   parse-passwd@1.0.0:
     resolution: {integrity: sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==}
     engines: {node: '>=0.10.0'}
@@ -8068,6 +8130,9 @@ packages:
   proxy-from-env@1.1.0:
     resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
 
+  prr@1.0.1:
+    resolution: {integrity: sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==}
+
   ps-tree@1.2.0:
     resolution: {integrity: sha512-0VnamPPYHl4uaU/nSFeZZpR21QAWRz+sRv4iW9+v/GS/J5U5iZB5BNN6J0RMoOvdx2gWM2+ZFMIm58q24e4UYA==}
     engines: {node: '>= 0.10'}
@@ -8373,6 +8438,9 @@ packages:
     engines: {node: '>=14.0.0'}
     hasBin: true
 
+  sax@1.4.1:
+    resolution: {integrity: sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==}
+
   saxes@6.0.0:
     resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==}
     engines: {node: '>=v12.22.7'}
@@ -8390,6 +8458,10 @@ packages:
   search-insights@2.16.0:
     resolution: {integrity: sha512-6ukNTOkN2OvJ8SJRmWionpn39OHOov1rx72kyGDYk60CaGrDfmT8wXYzgKLW9VFk+dVVXlUmWQVvrkRvx/x3Mg==}
 
+  section-matter@1.0.0:
+    resolution: {integrity: sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==}
+    engines: {node: '>=4'}
+
   seemly@0.3.8:
     resolution: {integrity: sha512-MW8Qs6vbzo0pHmDpFSYPna+lwpZ6Zk1ancbajw/7E8TKtHdV+1DfZZD+kKJEhG/cAoB/i+LiT+5msZOqj0DwRA==}
 
@@ -8675,6 +8747,10 @@ packages:
     resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==}
     engines: {node: '>=12'}
 
+  strip-bom-string@1.0.0:
+    resolution: {integrity: sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==}
+    engines: {node: '>=0.10.0'}
+
   strip-bom@3.0.0:
     resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==}
     engines: {node: '>=4'}
@@ -11890,6 +11966,10 @@ snapshots:
 
   '@humanwhocodes/retry@0.3.0': {}
 
+  '@iconify-json/octicon@1.1.57':
+    dependencies:
+      '@iconify/types': 2.0.0
+
   '@iconify/json@2.2.237':
     dependencies:
       '@iconify/types': 2.0.0
@@ -12119,6 +12199,84 @@ snapshots:
       '@nodelib/fs.scandir': 2.1.5
       fastq: 1.17.1
 
+  '@nolebase/ui@2.4.0(@algolia/client-search@4.24.0)(@types/node@22.3.0)(async-validator@4.2.5)(axios@1.7.4)(nprogress@0.2.0)(postcss@8.4.41)(qrcode@1.5.4)(sass@1.77.8)(search-insights@2.16.0)(sortablejs@1.15.2)(terser@5.31.3)(typescript@5.5.4)':
+    dependencies:
+      '@iconify-json/octicon': 1.1.57
+      less: 4.2.0
+      vitepress: 1.3.2(@algolia/client-search@4.24.0)(@types/node@22.3.0)(async-validator@4.2.5)(axios@1.7.4)(less@4.2.0)(nprogress@0.2.0)(postcss@8.4.41)(qrcode@1.5.4)(sass@1.77.8)(search-insights@2.16.0)(sortablejs@1.15.2)(terser@5.31.3)(typescript@5.5.4)
+      vue: 3.4.37(typescript@5.5.4)
+    transitivePeerDependencies:
+      - '@algolia/client-search'
+      - '@types/node'
+      - '@types/react'
+      - '@vue/composition-api'
+      - async-validator
+      - axios
+      - change-case
+      - drauu
+      - fuse.js
+      - idb-keyval
+      - jwt-decode
+      - lightningcss
+      - markdown-it-mathjax3
+      - nprogress
+      - postcss
+      - qrcode
+      - react
+      - react-dom
+      - sass
+      - sass-embedded
+      - search-insights
+      - sortablejs
+      - stylus
+      - sugarss
+      - terser
+      - typescript
+      - universal-cookie
+
+  '@nolebase/vitepress-plugin-git-changelog@2.4.0(@algolia/client-search@4.24.0)(@types/node@22.3.0)(async-validator@4.2.5)(axios@1.7.4)(nprogress@0.2.0)(postcss@8.4.41)(qrcode@1.5.4)(sass@1.77.8)(search-insights@2.16.0)(sortablejs@1.15.2)(terser@5.31.3)(typescript@5.5.4)':
+    dependencies:
+      '@iconify-json/octicon': 1.1.57
+      '@nolebase/ui': 2.4.0(@algolia/client-search@4.24.0)(@types/node@22.3.0)(async-validator@4.2.5)(axios@1.7.4)(nprogress@0.2.0)(postcss@8.4.41)(qrcode@1.5.4)(sass@1.77.8)(search-insights@2.16.0)(sortablejs@1.15.2)(terser@5.31.3)(typescript@5.5.4)
+      colorette: 2.0.20
+      date-fns: 3.6.0
+      defu: 6.1.4
+      es-toolkit: 1.15.1
+      execa: 8.0.1
+      globby: 14.0.2
+      gray-matter: 4.0.3
+      less: 4.2.0
+      uncrypto: 0.1.3
+      vitepress: 1.3.2(@algolia/client-search@4.24.0)(@types/node@22.3.0)(async-validator@4.2.5)(axios@1.7.4)(less@4.2.0)(nprogress@0.2.0)(postcss@8.4.41)(qrcode@1.5.4)(sass@1.77.8)(search-insights@2.16.0)(sortablejs@1.15.2)(terser@5.31.3)(typescript@5.5.4)
+    transitivePeerDependencies:
+      - '@algolia/client-search'
+      - '@types/node'
+      - '@types/react'
+      - '@vue/composition-api'
+      - async-validator
+      - axios
+      - change-case
+      - drauu
+      - fuse.js
+      - idb-keyval
+      - jwt-decode
+      - lightningcss
+      - markdown-it-mathjax3
+      - nprogress
+      - postcss
+      - qrcode
+      - react
+      - react-dom
+      - sass
+      - sass-embedded
+      - search-insights
+      - sortablejs
+      - stylus
+      - sugarss
+      - terser
+      - typescript
+      - universal-cookie
+
   '@npmcli/fs@1.1.1':
     dependencies:
       '@gar/promisify': 1.1.3
@@ -12829,23 +12987,23 @@ snapshots:
       - encoding
       - supports-color
 
-  '@vite-pwa/vitepress@0.5.0(vite-plugin-pwa@0.20.1(vite@5.4.0(@types/node@22.3.0)(sass@1.77.8)(terser@5.31.3))(workbox-build@7.1.1)(workbox-window@7.1.0))':
+  '@vite-pwa/vitepress@0.5.0(vite-plugin-pwa@0.20.1(vite@5.4.0(@types/node@22.3.0)(less@4.2.0)(sass@1.77.8)(terser@5.31.3))(workbox-build@7.1.1)(workbox-window@7.1.0))':
     dependencies:
-      vite-plugin-pwa: 0.20.1(vite@5.4.0(@types/node@22.3.0)(sass@1.77.8)(terser@5.31.3))(workbox-build@7.1.1)(workbox-window@7.1.0)
+      vite-plugin-pwa: 0.20.1(vite@5.4.0(@types/node@22.3.0)(less@4.2.0)(sass@1.77.8)(terser@5.31.3))(workbox-build@7.1.1)(workbox-window@7.1.0)
 
-  '@vitejs/plugin-vue-jsx@4.0.1(vite@5.4.0(@types/node@22.3.0)(sass@1.77.8)(terser@5.31.3))(vue@3.4.37(typescript@5.5.4))':
+  '@vitejs/plugin-vue-jsx@4.0.1(vite@5.4.0(@types/node@22.3.0)(less@4.2.0)(sass@1.77.8)(terser@5.31.3))(vue@3.4.37(typescript@5.5.4))':
     dependencies:
       '@babel/core': 7.25.2
       '@babel/plugin-transform-typescript': 7.25.2(@babel/core@7.25.2)
       '@vue/babel-plugin-jsx': 1.2.2(@babel/core@7.25.2)
-      vite: 5.4.0(@types/node@22.3.0)(sass@1.77.8)(terser@5.31.3)
+      vite: 5.4.0(@types/node@22.3.0)(less@4.2.0)(sass@1.77.8)(terser@5.31.3)
       vue: 3.4.37(typescript@5.5.4)
     transitivePeerDependencies:
       - supports-color
 
-  '@vitejs/plugin-vue@5.1.2(vite@5.4.0(@types/node@22.3.0)(sass@1.77.8)(terser@5.31.3))(vue@3.4.37(typescript@5.5.4))':
+  '@vitejs/plugin-vue@5.1.2(vite@5.4.0(@types/node@22.3.0)(less@4.2.0)(sass@1.77.8)(terser@5.31.3))(vue@3.4.37(typescript@5.5.4))':
     dependencies:
-      vite: 5.4.0(@types/node@22.3.0)(sass@1.77.8)(terser@5.31.3)
+      vite: 5.4.0(@types/node@22.3.0)(less@4.2.0)(sass@1.77.8)(terser@5.31.3)
       vue: 3.4.37(typescript@5.5.4)
 
   '@vitest/expect@2.0.5':
@@ -13005,14 +13163,14 @@ snapshots:
     dependencies:
       '@vue/devtools-kit': 7.3.7
 
-  '@vue/devtools-core@7.3.8(vite@5.4.0(@types/node@22.3.0)(sass@1.77.8)(terser@5.31.3))(vue@3.4.37(typescript@5.5.4))':
+  '@vue/devtools-core@7.3.8(vite@5.4.0(@types/node@22.3.0)(less@4.2.0)(sass@1.77.8)(terser@5.31.3))(vue@3.4.37(typescript@5.5.4))':
     dependencies:
       '@vue/devtools-kit': 7.3.8
       '@vue/devtools-shared': 7.3.8
       mitt: 3.0.1
       nanoid: 3.3.7
       pathe: 1.1.2
-      vite-hot-client: 0.2.3(vite@5.4.0(@types/node@22.3.0)(sass@1.77.8)(terser@5.31.3))
+      vite-hot-client: 0.2.3(vite@5.4.0(@types/node@22.3.0)(less@4.2.0)(sass@1.77.8)(terser@5.31.3))
       vue: 3.4.37(typescript@5.5.4)
     transitivePeerDependencies:
       - vite
@@ -13882,6 +14040,10 @@ snapshots:
 
   cookie-es@1.2.2: {}
 
+  copy-anything@2.0.6:
+    dependencies:
+      is-what: 3.14.1
+
   copy-anything@3.0.5:
     dependencies:
       is-what: 4.1.16
@@ -14192,6 +14354,8 @@ snapshots:
     dependencies:
       '@babel/runtime': 7.25.0
 
+  date-fns@3.6.0: {}
+
   dayjs@1.11.12: {}
 
   db0@0.1.4: {}
@@ -14461,6 +14625,11 @@ snapshots:
 
   err-code@2.0.3: {}
 
+  errno@0.1.8:
+    dependencies:
+      prr: 1.0.1
+    optional: true
+
   error-ex@1.3.2:
     dependencies:
       is-arrayish: 0.2.1
@@ -14540,6 +14709,8 @@ snapshots:
       is-date-object: 1.0.5
       is-symbol: 1.0.4
 
+  es-toolkit@1.15.1: {}
+
   esbuild@0.19.12:
     optionalDependencies:
       '@esbuild/aix-ppc64': 0.19.12
@@ -14829,13 +15000,13 @@ snapshots:
     optionalDependencies:
       '@typescript-eslint/eslint-plugin': 8.1.0(@typescript-eslint/parser@8.1.0(eslint@9.9.0(jiti@1.21.6))(typescript@5.5.4))(eslint@9.9.0(jiti@1.21.6))(typescript@5.5.4)
 
-  eslint-plugin-vitest@0.5.4(@typescript-eslint/eslint-plugin@8.1.0(@typescript-eslint/parser@8.1.0(eslint@9.9.0(jiti@1.21.6))(typescript@5.5.4))(eslint@9.9.0(jiti@1.21.6))(typescript@5.5.4))(eslint@9.9.0(jiti@1.21.6))(typescript@5.5.4)(vitest@2.0.5(@types/node@22.3.0)(jsdom@24.1.1)(sass@1.77.8)(terser@5.31.3)):
+  eslint-plugin-vitest@0.5.4(@typescript-eslint/eslint-plugin@8.1.0(@typescript-eslint/parser@8.1.0(eslint@9.9.0(jiti@1.21.6))(typescript@5.5.4))(eslint@9.9.0(jiti@1.21.6))(typescript@5.5.4))(eslint@9.9.0(jiti@1.21.6))(typescript@5.5.4)(vitest@2.0.5(@types/node@22.3.0)(jsdom@24.1.1)(less@4.2.0)(sass@1.77.8)(terser@5.31.3)):
     dependencies:
       '@typescript-eslint/utils': 7.18.0(eslint@9.9.0(jiti@1.21.6))(typescript@5.5.4)
       eslint: 9.9.0(jiti@1.21.6)
     optionalDependencies:
       '@typescript-eslint/eslint-plugin': 8.1.0(@typescript-eslint/parser@8.1.0(eslint@9.9.0(jiti@1.21.6))(typescript@5.5.4))(eslint@9.9.0(jiti@1.21.6))(typescript@5.5.4)
-      vitest: 2.0.5(@types/node@22.3.0)(jsdom@24.1.1)(sass@1.77.8)(terser@5.31.3)
+      vitest: 2.0.5(@types/node@22.3.0)(jsdom@24.1.1)(less@4.2.0)(sass@1.77.8)(terser@5.31.3)
     transitivePeerDependencies:
       - supports-color
       - typescript
@@ -14994,6 +15165,10 @@ snapshots:
     dependencies:
       homedir-polyfill: 1.0.3
 
+  extend-shallow@2.0.1:
+    dependencies:
+      is-extendable: 0.1.1
+
   extendable-error@0.1.7: {}
 
   external-editor@3.1.0:
@@ -15396,6 +15571,13 @@ snapshots:
 
   graphemer@1.4.0: {}
 
+  gray-matter@4.0.3:
+    dependencies:
+      js-yaml: 3.14.1
+      kind-of: 6.0.3
+      section-matter: 1.0.0
+      strip-bom-string: 1.0.0
+
   gzip-size@7.0.0:
     dependencies:
       duplexer: 0.1.2
@@ -15566,6 +15748,9 @@ snapshots:
 
   ignore@5.3.1: {}
 
+  image-size@0.5.5:
+    optional: true
+
   immutable@4.3.7: {}
 
   import-fresh@3.3.0:
@@ -15669,6 +15854,8 @@ snapshots:
 
   is-docker@3.0.0: {}
 
+  is-extendable@0.1.1: {}
+
   is-extglob@2.1.1: {}
 
   is-fullwidth-code-point@3.0.0: {}
@@ -15775,6 +15962,8 @@ snapshots:
     dependencies:
       call-bind: 1.0.7
 
+  is-what@3.14.1: {}
+
   is-what@4.1.16: {}
 
   is-windows@1.0.2: {}
@@ -15942,6 +16131,20 @@ snapshots:
     dependencies:
       readable-stream: 2.3.8
 
+  less@4.2.0:
+    dependencies:
+      copy-anything: 2.0.6
+      parse-node-version: 1.0.1
+      tslib: 2.6.3
+    optionalDependencies:
+      errno: 0.1.8
+      graceful-fs: 4.2.11
+      image-size: 0.5.5
+      make-dir: 2.1.0
+      mime: 1.6.0
+      needle: 3.3.1
+      source-map: 0.6.1
+
   leven@3.1.0: {}
 
   levn@0.4.1:
@@ -16124,6 +16327,12 @@ snapshots:
     dependencies:
       '@jridgewell/sourcemap-codec': 1.5.0
 
+  make-dir@2.1.0:
+    dependencies:
+      pify: 4.0.1
+      semver: 5.7.2
+    optional: true
+
   make-dir@3.1.0:
     dependencies:
       semver: 6.3.1
@@ -16355,6 +16564,12 @@ snapshots:
 
   natural-compare@1.4.0: {}
 
+  needle@3.3.1:
+    dependencies:
+      iconv-lite: 0.6.3
+      sax: 1.4.1
+    optional: true
+
   nitropack@2.9.7(encoding@0.1.13):
     dependencies:
       '@cloudflare/kv-asset-handler': 0.3.4
@@ -16704,6 +16919,8 @@ snapshots:
 
   parse-ms@4.0.0: {}
 
+  parse-node-version@1.0.1: {}
+
   parse-passwd@1.0.0: {}
 
   parse5-htmlparser2-tree-adapter@7.0.0:
@@ -17307,6 +17524,9 @@ snapshots:
 
   proxy-from-env@1.1.0: {}
 
+  prr@1.0.1:
+    optional: true
+
   ps-tree@1.2.0:
     dependencies:
       event-stream: 3.3.4
@@ -17641,6 +17861,9 @@ snapshots:
       immutable: 4.3.7
       source-map-js: 1.2.0
 
+  sax@1.4.1:
+    optional: true
+
   saxes@6.0.0:
     dependencies:
       xmlchars: 2.2.0
@@ -17659,6 +17882,11 @@ snapshots:
 
   search-insights@2.16.0: {}
 
+  section-matter@1.0.0:
+    dependencies:
+      extend-shallow: 2.0.1
+      kind-of: 6.0.3
+
   seemly@0.3.8: {}
 
   semver-compare@1.0.0: {}
@@ -17977,6 +18205,8 @@ snapshots:
     dependencies:
       ansi-regex: 6.0.1
 
+  strip-bom-string@1.0.0: {}
+
   strip-bom@3.0.0: {}
 
   strip-comments@2.0.1: {}
@@ -18638,17 +18868,17 @@ snapshots:
       evtd: 0.2.4
       vue: 3.4.37(typescript@5.5.4)
 
-  vite-hot-client@0.2.3(vite@5.4.0(@types/node@22.3.0)(sass@1.77.8)(terser@5.31.3)):
+  vite-hot-client@0.2.3(vite@5.4.0(@types/node@22.3.0)(less@4.2.0)(sass@1.77.8)(terser@5.31.3)):
     dependencies:
-      vite: 5.4.0(@types/node@22.3.0)(sass@1.77.8)(terser@5.31.3)
+      vite: 5.4.0(@types/node@22.3.0)(less@4.2.0)(sass@1.77.8)(terser@5.31.3)
 
-  vite-node@2.0.5(@types/node@22.3.0)(sass@1.77.8)(terser@5.31.3):
+  vite-node@2.0.5(@types/node@22.3.0)(less@4.2.0)(sass@1.77.8)(terser@5.31.3):
     dependencies:
       cac: 6.7.14
       debug: 4.3.6
       pathe: 1.1.2
       tinyrainbow: 1.2.0
-      vite: 5.4.0(@types/node@22.3.0)(sass@1.77.8)(terser@5.31.3)
+      vite: 5.4.0(@types/node@22.3.0)(less@4.2.0)(sass@1.77.8)(terser@5.31.3)
     transitivePeerDependencies:
       - '@types/node'
       - less
@@ -18660,16 +18890,16 @@ snapshots:
       - supports-color
       - terser
 
-  vite-plugin-compression@0.5.1(vite@5.4.0(@types/node@22.3.0)(sass@1.77.8)(terser@5.31.3)):
+  vite-plugin-compression@0.5.1(vite@5.4.0(@types/node@22.3.0)(less@4.2.0)(sass@1.77.8)(terser@5.31.3)):
     dependencies:
       chalk: 4.1.2
       debug: 4.3.6
       fs-extra: 10.1.0
-      vite: 5.4.0(@types/node@22.3.0)(sass@1.77.8)(terser@5.31.3)
+      vite: 5.4.0(@types/node@22.3.0)(less@4.2.0)(sass@1.77.8)(terser@5.31.3)
     transitivePeerDependencies:
       - supports-color
 
-  vite-plugin-dts@4.0.3(@types/node@22.3.0)(rollup@4.20.0)(typescript@5.5.4)(vite@5.4.0(@types/node@22.3.0)(sass@1.77.8)(terser@5.31.3)):
+  vite-plugin-dts@4.0.3(@types/node@22.3.0)(rollup@4.20.0)(typescript@5.5.4)(vite@5.4.0(@types/node@22.3.0)(less@4.2.0)(sass@1.77.8)(terser@5.31.3)):
     dependencies:
       '@microsoft/api-extractor': 7.47.4(@types/node@22.3.0)
       '@rollup/pluginutils': 5.1.0(rollup@4.20.0)
@@ -18683,13 +18913,13 @@ snapshots:
       typescript: 5.5.4
       vue-tsc: 2.0.29(typescript@5.5.4)
     optionalDependencies:
-      vite: 5.4.0(@types/node@22.3.0)(sass@1.77.8)(terser@5.31.3)
+      vite: 5.4.0(@types/node@22.3.0)(less@4.2.0)(sass@1.77.8)(terser@5.31.3)
     transitivePeerDependencies:
       - '@types/node'
       - rollup
       - supports-color
 
-  vite-plugin-html@3.2.2(vite@5.4.0(@types/node@22.3.0)(sass@1.77.8)(terser@5.31.3)):
+  vite-plugin-html@3.2.2(vite@5.4.0(@types/node@22.3.0)(less@4.2.0)(sass@1.77.8)(terser@5.31.3)):
     dependencies:
       '@rollup/pluginutils': 4.2.1
       colorette: 2.0.20
@@ -18703,9 +18933,9 @@ snapshots:
       html-minifier-terser: 6.1.0
       node-html-parser: 5.4.2
       pathe: 0.2.0
-      vite: 5.4.0(@types/node@22.3.0)(sass@1.77.8)(terser@5.31.3)
+      vite: 5.4.0(@types/node@22.3.0)(less@4.2.0)(sass@1.77.8)(terser@5.31.3)
 
-  vite-plugin-inspect@0.8.5(rollup@4.20.0)(vite@5.4.0(@types/node@22.3.0)(sass@1.77.8)(terser@5.31.3)):
+  vite-plugin-inspect@0.8.5(rollup@4.20.0)(vite@5.4.0(@types/node@22.3.0)(less@4.2.0)(sass@1.77.8)(terser@5.31.3)):
     dependencies:
       '@antfu/utils': 0.7.10
       '@rollup/pluginutils': 5.1.0(rollup@4.20.0)
@@ -18716,46 +18946,46 @@ snapshots:
       perfect-debounce: 1.0.0
       picocolors: 1.0.1
       sirv: 2.0.4
-      vite: 5.4.0(@types/node@22.3.0)(sass@1.77.8)(terser@5.31.3)
+      vite: 5.4.0(@types/node@22.3.0)(less@4.2.0)(sass@1.77.8)(terser@5.31.3)
     transitivePeerDependencies:
       - rollup
       - supports-color
 
-  vite-plugin-lib-inject-css@2.1.1(vite@5.4.0(@types/node@22.3.0)(sass@1.77.8)(terser@5.31.3)):
+  vite-plugin-lib-inject-css@2.1.1(vite@5.4.0(@types/node@22.3.0)(less@4.2.0)(sass@1.77.8)(terser@5.31.3)):
     dependencies:
       '@ast-grep/napi': 0.22.6
       magic-string: 0.30.11
       picocolors: 1.0.1
-      vite: 5.4.0(@types/node@22.3.0)(sass@1.77.8)(terser@5.31.3)
+      vite: 5.4.0(@types/node@22.3.0)(less@4.2.0)(sass@1.77.8)(terser@5.31.3)
 
-  vite-plugin-pwa@0.20.1(vite@5.4.0(@types/node@22.3.0)(sass@1.77.8)(terser@5.31.3))(workbox-build@7.1.1)(workbox-window@7.1.0):
+  vite-plugin-pwa@0.20.1(vite@5.4.0(@types/node@22.3.0)(less@4.2.0)(sass@1.77.8)(terser@5.31.3))(workbox-build@7.1.1)(workbox-window@7.1.0):
     dependencies:
       debug: 4.3.6
       pretty-bytes: 6.1.1
       tinyglobby: 0.2.2
-      vite: 5.4.0(@types/node@22.3.0)(sass@1.77.8)(terser@5.31.3)
+      vite: 5.4.0(@types/node@22.3.0)(less@4.2.0)(sass@1.77.8)(terser@5.31.3)
       workbox-build: 7.1.1
       workbox-window: 7.1.0
     transitivePeerDependencies:
       - supports-color
 
-  vite-plugin-vue-devtools@7.3.8(rollup@4.20.0)(vite@5.4.0(@types/node@22.3.0)(sass@1.77.8)(terser@5.31.3))(vue@3.4.37(typescript@5.5.4)):
+  vite-plugin-vue-devtools@7.3.8(rollup@4.20.0)(vite@5.4.0(@types/node@22.3.0)(less@4.2.0)(sass@1.77.8)(terser@5.31.3))(vue@3.4.37(typescript@5.5.4)):
     dependencies:
-      '@vue/devtools-core': 7.3.8(vite@5.4.0(@types/node@22.3.0)(sass@1.77.8)(terser@5.31.3))(vue@3.4.37(typescript@5.5.4))
+      '@vue/devtools-core': 7.3.8(vite@5.4.0(@types/node@22.3.0)(less@4.2.0)(sass@1.77.8)(terser@5.31.3))(vue@3.4.37(typescript@5.5.4))
       '@vue/devtools-kit': 7.3.8
       '@vue/devtools-shared': 7.3.8
       execa: 8.0.1
       sirv: 2.0.4
-      vite: 5.4.0(@types/node@22.3.0)(sass@1.77.8)(terser@5.31.3)
-      vite-plugin-inspect: 0.8.5(rollup@4.20.0)(vite@5.4.0(@types/node@22.3.0)(sass@1.77.8)(terser@5.31.3))
-      vite-plugin-vue-inspector: 5.1.3(vite@5.4.0(@types/node@22.3.0)(sass@1.77.8)(terser@5.31.3))
+      vite: 5.4.0(@types/node@22.3.0)(less@4.2.0)(sass@1.77.8)(terser@5.31.3)
+      vite-plugin-inspect: 0.8.5(rollup@4.20.0)(vite@5.4.0(@types/node@22.3.0)(less@4.2.0)(sass@1.77.8)(terser@5.31.3))
+      vite-plugin-vue-inspector: 5.1.3(vite@5.4.0(@types/node@22.3.0)(less@4.2.0)(sass@1.77.8)(terser@5.31.3))
     transitivePeerDependencies:
       - '@nuxt/kit'
       - rollup
       - supports-color
       - vue
 
-  vite-plugin-vue-inspector@5.1.3(vite@5.4.0(@types/node@22.3.0)(sass@1.77.8)(terser@5.31.3)):
+  vite-plugin-vue-inspector@5.1.3(vite@5.4.0(@types/node@22.3.0)(less@4.2.0)(sass@1.77.8)(terser@5.31.3)):
     dependencies:
       '@babel/core': 7.25.2
       '@babel/plugin-proposal-decorators': 7.24.7(@babel/core@7.25.2)
@@ -18766,11 +18996,11 @@ snapshots:
       '@vue/compiler-dom': 3.4.37
       kolorist: 1.8.0
       magic-string: 0.30.11
-      vite: 5.4.0(@types/node@22.3.0)(sass@1.77.8)(terser@5.31.3)
+      vite: 5.4.0(@types/node@22.3.0)(less@4.2.0)(sass@1.77.8)(terser@5.31.3)
     transitivePeerDependencies:
       - supports-color
 
-  vite@5.4.0(@types/node@22.3.0)(sass@1.77.8)(terser@5.31.3):
+  vite@5.4.0(@types/node@22.3.0)(less@4.2.0)(sass@1.77.8)(terser@5.31.3):
     dependencies:
       esbuild: 0.21.5
       postcss: 8.4.41
@@ -18778,17 +19008,18 @@ snapshots:
     optionalDependencies:
       '@types/node': 22.3.0
       fsevents: 2.3.3
+      less: 4.2.0
       sass: 1.77.8
       terser: 5.31.3
 
-  vitepress@1.3.2(@algolia/client-search@4.24.0)(@types/node@22.3.0)(async-validator@4.2.5)(axios@1.7.4)(nprogress@0.2.0)(postcss@8.4.41)(qrcode@1.5.4)(sass@1.77.8)(search-insights@2.16.0)(sortablejs@1.15.2)(terser@5.31.3)(typescript@5.5.4):
+  vitepress@1.3.2(@algolia/client-search@4.24.0)(@types/node@22.3.0)(async-validator@4.2.5)(axios@1.7.4)(less@4.2.0)(nprogress@0.2.0)(postcss@8.4.41)(qrcode@1.5.4)(sass@1.77.8)(search-insights@2.16.0)(sortablejs@1.15.2)(terser@5.31.3)(typescript@5.5.4):
     dependencies:
       '@docsearch/css': 3.6.1
       '@docsearch/js': 3.6.1(@algolia/client-search@4.24.0)(search-insights@2.16.0)
       '@shikijs/core': 1.12.1
       '@shikijs/transformers': 1.12.1
       '@types/markdown-it': 14.1.2
-      '@vitejs/plugin-vue': 5.1.2(vite@5.4.0(@types/node@22.3.0)(sass@1.77.8)(terser@5.31.3))(vue@3.4.37(typescript@5.5.4))
+      '@vitejs/plugin-vue': 5.1.2(vite@5.4.0(@types/node@22.3.0)(less@4.2.0)(sass@1.77.8)(terser@5.31.3))(vue@3.4.37(typescript@5.5.4))
       '@vue/devtools-api': 7.3.7
       '@vue/shared': 3.4.37
       '@vueuse/core': 10.11.1(vue@3.4.37(typescript@5.5.4))
@@ -18797,7 +19028,7 @@ snapshots:
       mark.js: 8.11.1
       minisearch: 7.1.0
       shiki: 1.12.1
-      vite: 5.4.0(@types/node@22.3.0)(sass@1.77.8)(terser@5.31.3)
+      vite: 5.4.0(@types/node@22.3.0)(less@4.2.0)(sass@1.77.8)(terser@5.31.3)
       vue: 3.4.37(typescript@5.5.4)
     optionalDependencies:
       postcss: 8.4.41
@@ -18829,7 +19060,7 @@ snapshots:
       - typescript
       - universal-cookie
 
-  vitest@2.0.5(@types/node@22.3.0)(jsdom@24.1.1)(sass@1.77.8)(terser@5.31.3):
+  vitest@2.0.5(@types/node@22.3.0)(jsdom@24.1.1)(less@4.2.0)(sass@1.77.8)(terser@5.31.3):
     dependencies:
       '@ampproject/remapping': 2.3.0
       '@vitest/expect': 2.0.5
@@ -18847,8 +19078,8 @@ snapshots:
       tinybench: 2.9.0
       tinypool: 1.0.0
       tinyrainbow: 1.2.0
-      vite: 5.4.0(@types/node@22.3.0)(sass@1.77.8)(terser@5.31.3)
-      vite-node: 2.0.5(@types/node@22.3.0)(sass@1.77.8)(terser@5.31.3)
+      vite: 5.4.0(@types/node@22.3.0)(less@4.2.0)(sass@1.77.8)(terser@5.31.3)
+      vite-node: 2.0.5(@types/node@22.3.0)(less@4.2.0)(sass@1.77.8)(terser@5.31.3)
       why-is-node-running: 2.3.0
     optionalDependencies:
       '@types/node': 22.3.0