feat(plugin-md-power): add ::: encrypt container, close #815 (#831)

* feat(plugin-md-power): add `::: encrypt` container

* chore: tweak

* chore: tweak

* chore: tweak
This commit is contained in:
pengzhanbo 2026-02-12 23:55:21 +08:00 committed by GitHub
parent 78a2859398
commit b1f996cb0e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
41 changed files with 1232 additions and 194 deletions

View File

@ -57,6 +57,7 @@ export const theme: Theme = plumeTheme({
codeSandbox: true, codeSandbox: true,
jsfiddle: true, jsfiddle: true,
demo: true, demo: true,
encrypt: true,
npmTo: ['pnpm', 'yarn', 'npm'], npmTo: ['pnpm', 'yarn', 'npm'],
repl: { repl: {
go: true, go: true,

View File

@ -7,19 +7,18 @@ permalink: /en/guide/features/encryption/
## Encryption ## Encryption
This theme supports multiple flexible encryption methods, including **full-site encryption** and **partial encryption**. In this topic, various flexible encryption methods such as **full-site encryption** and **partial encryption** are supported.
::: warning Note ::: warning Note
Due to the inherent limitations of `vuepress` as a static site generator, Due to the limitations of `vuepress` as a static site, **encryption** only makes the content *appear* invisible.
the **encryption** only makes content *appear* invisible and excludes the content from being pre-rendered During compilation, the content is not pre-rendered into the `html`,
into `html` during compilation. However, the content can still be accessed from the site's source files. but it can still be retrieved from the site's source files.
Therefore, the **encryption** feature should not be considered as completely secure or reliable.
Therefore, the **encryption** feature should not be considered **secure and reliable**.
Avoid using the **encryption feature** for content that requires **strict confidentiality**. Avoid using the **encryption feature** for content that requires **strict confidentiality**.
::: :::
**Unlocked articles are only visible within the current session.** **Unlocked articles are only visible during the current session.**
## Enabling Encryption ## Enabling Encryption
@ -40,8 +39,8 @@ export default defineUserConfig({
## Full-Site Encryption ## Full-Site Encryption
In some cases, you may need to encrypt the entire site. Configure full-site encryption using the `encrypt. In some cases, you may need to encrypt the entire site.
global` option, then set one or more passwords using the `encrypt.admin` option. You can configure full-site encryption using the `encrypt.global` option and set one or more passwords with `encrypt.admin`.
```ts title=".vuepress/config.ts" ```ts title=".vuepress/config.ts"
export default defineUserConfig({ export default defineUserConfig({
@ -56,22 +55,23 @@ export default defineUserConfig({
## Partial Encryption ## Partial Encryption
In most cases, you may only need to encrypt specific articles, directories, etc. Configure partial encryption using the `encrypt.rules` option. In most cases, you may only need to encrypt a specific article, directory, etc.
You can configure partial encryption using the `encrypt.rules` option.
```ts title=".vuepress/config.ts" ```ts title=".vuepress/config.ts"
export default defineUserConfig({ export default defineUserConfig({
theme: plumeTheme({ theme: plumeTheme({
encrypt: { encrypt: {
rules: { rules: {
// Can be relative path to md file - encrypts this file // Can be the relative path of an MD file to encrypt that file
'前端/基础.md': '123456', '前端/基础.md': '123456',
// Can be directory path - encrypts all articles under this directory // Can be a directory path to encrypt all articles under that directory
'/notes/vuepress-theme-plume/': '123456', '/notes/vuepress-theme-plume/': '123456',
// Can be request path - encrypts all articles under this access path // Can be a request path to encrypt all articles under that path
'/vuepress-theme-plume/': '123456', '/vuepress-theme-plume/': '123456',
// Can be specific page request path - encrypts this page // Can be a specific page's request path to encrypt that page
'/article/f8dnci3/': '123456', '/article/f8dnci3/': '123456',
// If starting with `^`, pages matching this regex will also be encrypted // If prefixed with `^`, pages matching the regex will also be encrypted
'^/(a|b)/': '123456', '^/(a|b)/': '123456',
} }
} }
@ -79,19 +79,20 @@ export default defineUserConfig({
}) })
``` ```
The **keys** in `encrypt.rules` serve as matching rules, and the **values** serve as passwords for those rules. You can set one or multiple passwords. The **key** in `encrypt.rules` serves as the matching rule,
and the **value** is the corresponding password (or multiple passwords) for that rule.
:::tip Notes :::tip Notes
- Passwords must be plain strings. - Passwords must be plain strings.
- If an entire directory is encrypted, unlocking applies to the entire directory, not individual articles within it. - If encrypting an entire directory, unlocking applies to the entire directory, not individual articles within it.
- `encrypt.admin` can also be used to unlock **partially encrypted** pages. - `encrypt.admin` can also be used to unlock **partially encrypted** pages.
- After unlocking with `encrypt.admin`, the user is considered an administrator and other locked pages are unlocked by default. - After unlocking with `encrypt.admin`, the user is considered an admin, and all other locked pages are unlocked by default.
::: :::
### Frontmatter ### Frontmatter
Use the `password` field in Markdown file `Frontmatter` to set article passwords. In the `Frontmatter` of a Markdown file, you can set the article's password using the `password` field.
```md ```md
--- ---
@ -100,7 +101,7 @@ password: 123456
--- ---
``` ```
You can also add the `passwordHint` option to set password hint information. You can also add the `passwordHint` option to provide a password hint.
```md ```md
--- ---
@ -114,9 +115,9 @@ passwordHint: The password is 123456
Click to visit [Encrypted Article, Password: 123456](/article/enx7c9s/) Click to visit [Encrypted Article, Password: 123456](/article/enx7c9s/)
## Related Configuration ## Related Configurations
The following configurations support use in [multilingual configuration](../../config/locales.md). The following configurations can be used in [multilingual settings](../../config/locales.md).
### encryptGlobalText ### encryptGlobalText
@ -124,7 +125,7 @@ The following configurations support use in [multilingual configuration](../../c
- **Default**: `'Only password can access this site'` - **Default**: `'Only password can access this site'`
- **Description**: - **Description**:
Prompt message for full-site encryption. Supports HTML. Useful if you want to provide contact information for visitors to obtain passwords. The prompt message for full-site encryption. Supports HTML. Useful if you want to provide contact information for visitors to obtain the password.
### encryptPageText ### encryptPageText
@ -132,19 +133,19 @@ The following configurations support use in [multilingual configuration](../../c
- **Default**: `'Only password can access this page'` - **Default**: `'Only password can access this page'`
- **Description**: - **Description**:
Prompt message for partial encryption. Supports HTML. Useful if you want to provide contact information for visitors to obtain passwords. The prompt message for partial encryption. Supports HTML. Useful if you want to provide contact information for visitors to obtain the password.
### encryptButtonText ### encryptButtonText
- **Type**: `string` - **Type**: `string`
- **Default**: `'Confirm'` - **Default**: `'Confirm'`
- **Description**: Text for the confirmation button - **Description**: The text for the confirmation button.
### encryptPlaceholder ### encryptPlaceholder
- **Type**: `string` - **Type**: `string`
- **Default**: `'Enter password'` - **Default**: `'Enter password'`
- **Description**: Placeholder text for the password input field - **Description**: The placeholder text for the password input field.
### Example ### Example

View File

@ -111,3 +111,54 @@ This component relies entirely on the `@vuepress/plugin-llms` plugin and can onl
Therefore, the functionality provided by this component **is only available in the built production package**. Therefore, the functionality provided by this component **is only available in the built production package**.
::: :::
## Markup Extensions
### `<llm-only>`
You can add content in a file that is visible to LLMs but not to humans, which helps set special instructions,
such as "Refer to basic-queries for demos," "Do not execute...", "Always use... in cases of...", etc.
To do this, wrap the content with the `<llm-only>` tag.
```md
<llm-only>
## Section for LLMs
This content appears only in the generated LLM file and will not include the `<llm-only>` tag itself.
</llm-only>
```
You can also use the `<llm-only>` tag inline, but note that only one `<llm-only>` tag can be included per line;
otherwise, it will cause a parsing error.
```md
Check the plugin API guide for documentation on creating plugins.
<llm-only>For LLMs only</llm-only>
```
### `<llm-exclude>`
You can add content in a file that is visible to humans but not to LLMs, which is the opposite of `<llm-only>`:
```md
<llm-exclude>
## Section for humans
This content will not appear in the files generated for LLMs.
</llm-exclude>
```
You can also use the `<llm-exclude>` tag inline, but note that only one `<llm-only>` tag can be included per line;
otherwise, it will cause a parsing error.
```md
Check the plugin API guide for documentation on creating plugins.
<llm-exclude>For humans only</llm-exclude>
```

View File

@ -7,7 +7,7 @@ permalink: /guide/features/encryption/
## 加密 ## 加密
在本主题中,支持 **全站加密****部分加密** 等多种灵活的加密方式。 在本主题中,支持 **全站加密** **部分页面加密** **部分内容加密** 等多种灵活的加密方式。
::: warning 提示 ::: warning 提示
由于 `vuepress` 是静态站点,其自身限制的原因,**加密** 仅仅只是 看起来 看不到内容, 由于 `vuepress` 是静态站点,其自身限制的原因,**加密** 仅仅只是 看起来 看不到内容,
@ -53,7 +53,7 @@ export default defineUserConfig({
}) })
``` ```
## 部分加密 ## 部分页面加密
大多数情况下,你可能只需需要 加密 某一篇文章、某一个目录 等。 大多数情况下,你可能只需需要 加密 某一篇文章、某一个目录 等。
因此,你可以通过 `encrypt.rules` 选项配置部分加密。 因此,你可以通过 `encrypt.rules` 选项配置部分加密。
@ -110,10 +110,112 @@ passwordHint: 密码是 123456
--- ---
``` ```
## 示例 ### 示例
点击访问 [加密文章密码123456](/article/enx7c9s/) 点击访问 [加密文章密码123456](/article/enx7c9s/)
## 部分内容加密
### 配置
部分内容加密通过 `::: encrypt` 容器实现,需要配置 `markdown.encrypt` 选项:
```ts title=".vuepress/config.ts"
export default defineUserConfig({
theme: plumeTheme({
markdown: {
encrypt: true, // [!code ++]
}
})
})
```
还可以给 `::: encrypt` 容器设置统一的默认密码:
```ts title=".vuepress/config.ts"
export default defineUserConfig({
theme: plumeTheme({
markdown: {
encrypt: {
password: 123456, // [!code ++]
}
}
})
})
```
### 使用
使用 `::: encrypt` 容器,将需要加密的内容包裹起来。
可以在容器中添加 `password` / `pwd` 属性,设置该容器的密码。
如果没有设置密码,将使用默认密码。
还可以在容器上添加 `hint` 属性,设置密码提示信息。
```md /password="123456"/
::: encrypt password="123456" hint="密码是连续的 6 位数"
这是加密的内容
:::
```
::: info 密码仅有一个生效,不支持同时设置多个密码。
:::
### 示例
**输入:**
```md
::: encrypt password="123456"
这是加密的内容
:::
```
**输出:**
::: encrypt password="123456"
这是加密的内容
:::
**输入:**
```md
::: encrypt password="654321" hint="密码是连续的 6 位数"
这是加密的内容2
:::
```
**输出:**
::: encrypt password="654321" hint="密码是连续的 6 位数"
这是加密的内容2
:::
::: warning 使用限制
**对于被加密的内容,可以使用:**
- 所有标准的 markdown 语法
- 主题提供的 大多数扩展语法,但不包括:
- `@[demo]()` 从目录中引入的代码示例
- `@[code]()` 从目录中引入的代码片段
- `@[code-tree]()` 从目录中引入的代码树
- 主题提供的 全局 vue 组件
- 用户自定义的 全局 vue 组件
- 被加密的内容,不能包含可执行的脚本,如有特殊交互,请通过组件实现。
**网络环境要求:**
部分内容加密采用 [Crypto API](https://developer.mozilla.org/en-US/docs/Web/API/Crypto) 实现,
因此,在 **非 HTTPS 环境** 下,将无法正常工作。
:::
::: details 如果你是技术开发者,你可能需要知道的内容
原始 markdown 内容首先进过 markdown 渲染为 HTML 内容后,再进行加密;传输到客户端,再进行解密渲染。
解密后的内容会被包装为一个动态的 vue 组件html 作为 template 传给该动态组件,因此,涉及到运行时编译 template
的内容。这导致了如果启用部分内容加密功能,那么就需要将 vue 切换到 `esm-bundler` 版本,以支持运行时编译,
这会比默认的 `runtime-only` 版本性能差一些,体积也会增加。
:::
## 相关配置 ## 相关配置
以下配置支持在 [多语言配置](../../config/locales.md) 中使用。 以下配置支持在 [多语言配置](../../config/locales.md) 中使用。

View File

@ -103,3 +103,52 @@ export default defineClientConfig({
因此,此组件提供的功能 **仅在构建后的生产包中才可用** 因此,此组件提供的功能 **仅在构建后的生产包中才可用**
::: :::
## 扩展标记 (Markup)
### `<llm-only>`
你可以在文件中添加对 LLM 可见但对人类不可见的内容,这有助于设置特殊指令,
例如 “参考 basic-queries 获取演示”、“切勿执行……”、“在……情况下始终使用……”等。
为此,需要使用 `<llm-only>` 标签来包裹内容。
```md
<llm-only>
## Section for LLMs
此内容仅出现在生成的LLM文件中不会包含 `<llm-only>` 标签本身。
</llm-only>
```
也可以在单行中使用 `<llm-only>` 标签,但请注意单行时仅能包含一个 `<llm-only>` 标签,否则会导致解析错误。
```md
查看插件API指南了解创建插件的相关文档。
<llm-only>仅限 LLM 阅读</llm-only>
```
### `<llm-exclude>`
你可以在文件中添加对人类可见但对LLM不可见的内容这与 `<llm-only>` 的作用相反:
```md
<llm-exclude>
## Section for humans
此内容将不会出现在为 LLMs 生成的文件中
</llm-exclude>
```
也可以在单行中使用 `<llm-exclude>` 标签,但请注意单行时仅能包含一个 `<llm-only>` 标签,否则会导致解析错误。
```md
查看插件API指南了解创建插件的相关文档。
<llm-exclude>仅限人类阅读</llm-exclude>
```

View File

@ -0,0 +1,248 @@
<script setup lang="ts">
import snippets from '@internal/encrypt-snippets'
import { decodeData } from '@vuepress/helper/client'
import { useIntersectionObserver } from '@vueuse/core'
import { computed, defineComponent, h, ref, useTemplateRef } from 'vue'
import { ClientOnly, onContentUpdated } from 'vuepress/client'
import { useDecrypt } from '../composables/decrypt.js'
import { ENCRYPT_LOCALES } from '../options.js'
const { data, hint, pathLocale } = defineProps<{
data: string
pathLocale: string
hint?: string
}>()
const config = computed<{
hash: string
salt: number[]
iv: number[]
}>(() => JSON.parse(decodeData(data)))
const locale = computed(() => ENCRYPT_LOCALES[pathLocale] || {})
const { decrypt } = useDecrypt(config)
const el = useTemplateRef<HTMLDivElement>('el')
const password = ref('')
const content = ref('')
const errorCode = ref<0 | 1 | 2>(0) // 0: no error, 1: wrong password 2: no content
const loading = ref(false)
// web encrypt should always use https
const isHttps = computed(() => {
if (__VUEPRESS_SSR__)
return false
if (__VUEPRESS_DEV__)
return true
return window.location.protocol === 'https:'
})
let rawContent = ''
async function load(): Promise<[null, string] | [2, null]> {
if (rawContent)
return [null, rawContent]
const loader = snippets[config.value.hash]
if (loader) {
try {
return [null, rawContent = (await loader()).default]
}
catch {
return [2, null]
}
}
return [2, null]
}
async function onDecrypt() {
if (!password.value || loading.value)
return
loading.value = true
errorCode.value = 0
const [code, rawContent] = await load()
if (typeof code === 'number') {
errorCode.value = code
return
}
try {
content.value = (await decrypt(password.value, rawContent))!
}
catch {
errorCode.value = 1
}
loading.value = false
}
useIntersectionObserver(el, ([entry]) => {
if (entry?.isIntersecting)
load()
})
onContentUpdated((reason) => {
if (reason === 'updated') {
rawContent = ''
content.value = ''
errorCode.value = 0
}
})
const DecryptedContent = defineComponent({
name: 'DecryptedContent',
props: { content: String },
render() {
const template = `<div>${this.content}</div>`
return h({ template })
},
})
</script>
<template>
<ClientOnly>
<div v-if="!content" ref="el" class="vp-encrypt-snippet">
<div class="snippet-hint">
<span class="vpi-lock" />
<span>{{ hint || locale.hint || 'The content is encrypted, please unlock to view.' }}</span>
</div>
<div v-if="!isHttps" class="snippet-warning">
<strong>{{ locale.warningTitle || '🚨 Security Warning:' }}</strong>
{{ locale.warningText || 'Your connection is not encrypted with HTTPS, posing a risk of content leakage and preventing access to encrypted content.' }}
</div>
<div v-else class="snippet-form" :class="{ error: errorCode === 1 }">
<label for="password">
<input
v-model="password" name="password" type="password"
:placeholder="locale.placeholder || 'Enter password'"
@keydown.enter="onDecrypt"
@input="errorCode = 0"
>
</label>
<button type="button" :disabled="!password" @click="onDecrypt">
<span :class="loading ? 'vpi-loading' : 'vpi-unlock'" />
</button>
<p v-if="errorCode === 1" class="snippet-error">
{{ locale.incPwd || 'Incorrect password' }}
</p>
<p v-if="errorCode === 2" class="snippet-error">
{{ locale.noContent || 'Unlocked, but content failed to load, please try again later.' }}
</p>
</div>
</div>
<DecryptedContent v-else :content="content" class="decrypted-content" />
</ClientOnly>
</template>
<style>
.vp-encrypt-snippet {
padding: 16px 20px;
background-color: var(--vp-c-important-soft);
border-radius: 8px;
}
.vp-encrypt-snippet .snippet-hint {
display: flex;
gap: 12px;
align-items: center;
justify-content: center;
color: var(--vp-c-important-1);
}
.vp-encrypt-snippet .snippet-warning {
font-size: 14px;
color: var(--vp-c-text-2);
text-align: center;
}
.vp-encrypt-snippet .snippet-form {
position: relative;
display: flex;
gap: 12px;
align-items: center;
width: 100%;
max-width: 320px;
height: 36px;
padding-right: 4px;
padding-left: 12px;
margin: 12px auto 8px;
background: var(--vp-c-bg);
border: solid 1px var(--vp-c-important-2);
border-radius: 18px;
transition: border-color var(--vp-t-color);
}
.vp-encrypt-snippet .snippet-form.error {
border-color: var(--vp-c-caution-1);
}
.vp-encrypt-snippet .snippet-form label {
flex: 1;
}
.vp-encrypt-snippet .snippet-form input {
width: 100%;
color: var(--vp-c-important-1);
}
.vp-encrypt-snippet .snippet-form button {
display: flex;
align-items: center;
justify-content: center;
width: 28px;
height: 28px;
font-size: 14px;
color: var(--vp-c-important-1);
cursor: pointer;
border: solid 2px var(--vp-c-important-1);
border-radius: 50%;
transition: var(--vp-t-color);
transition-property: color, border-color;
}
.vp-encrypt-snippet .snippet-form button[disabled] {
color: var(--vp-c-text-3);
border-color: var(--vp-c-text-3);
}
.vp-encrypt-snippet .snippet-form button:not([disabled]):hover {
color: var(--vp-c-important-3);
border-color: var(--vp-c-important-3);
}
.vp-encrypt-snippet .snippet-form button .vpi-loading {
font-size: 24px;
}
.vp-encrypt-snippet .snippet-form .snippet-error {
position: absolute;
top: 100%;
left: 0;
width: 100%;
padding-left: 12px;
margin: 0;
font-size: 12px;
color: var(--vp-c-caution-1);
}
.decrypted-content {
background-color: transparent;
animation: fade-scale 800ms ease-in 8 alternate;
}
@keyframes fade-scale {
0% {
background-color: transparent;
}
100% {
background-color: var(--vp-c-green-soft);
}
}
.vpi-unlock {
--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='26' height='26' viewBox='0 0 26 26'%3E%3Cpath fill='%23000' d='M7 0C4.79 0 2.878.917 1.687 2.406C.498 3.896 0 5.826 0 7.906V11h3V7.906c0-1.58.389-2.82 1.031-3.625C4.674 3.477 5.541 3 7 3c1.463 0 2.328.45 2.969 1.25c.64.8 1.031 2.06 1.031 3.656V9h3V7.906c0-2.092-.527-4.044-1.719-5.531C11.09.888 9.206 0 7 0m2 10c-1.656 0-3 1.344-3 3v10c0 1.656 1.344 3 3 3h14c1.656 0 3-1.344 3-3V13c0-1.656-1.344-3-3-3zm7 5a2 2 0 0 1 2 2c0 .738-.404 1.372-1 1.719V21c0 .551-.449 1-1 1s-1-.449-1-1v-2.281c-.596-.347-1-.98-1-1.719a2 2 0 0 1 2-2'/%3E%3C/svg%3E");
}
</style>

View File

@ -0,0 +1,62 @@
import type { ComputedRef } from 'vue'
export function useDecrypt(
config: ComputedRef<{ salt: number[], iv: number[] }>,
) {
const toUnit8Array = (raw: number[]) => Uint8Array.from(raw)
return {
decrypt: async (password: string, text: string) => {
if (!password)
return
const keyMaterial = await getKeyMaterial(password)
const key = await getCryptoDeriveKey(keyMaterial, toUnit8Array(config.value.salt))
const ciphertextData = Uint8Array.from(text, c => c.charCodeAt(0))
const decrypted = await window.crypto.subtle.decrypt(
{
name: 'AES-CBC',
iv: toUnit8Array(config.value.iv),
},
key,
ciphertextData,
)
return new TextDecoder().decode(decrypted)
},
}
}
function getKeyMaterial(password: string) {
const enc = new TextEncoder()
return window.crypto.subtle.importKey(
'raw',
enc.encode(password),
'PBKDF2',
false,
['deriveBits', 'deriveKey'],
)
}
/**
* crypto
*/
function getCryptoDeriveKey(keyMaterial: CryptoKey, salt: BufferSource) {
return window.crypto.subtle.deriveKey(
{
name: 'PBKDF2',
salt,
iterations: 100000,
hash: 'SHA-256',
},
keyMaterial,
{
name: 'AES-CBC',
length: 256,
},
true,
['encrypt', 'decrypt'],
)
}

View File

@ -1,5 +1,13 @@
import type { LocaleConfig } from 'vuepress'
import type { EncryptSnippetLocale } from '../shared/encrypt.js'
import type { MarkdownPowerPluginOptions } from '../shared/index.js' import type { MarkdownPowerPluginOptions } from '../shared/index.js'
declare const __MD_POWER_INJECT_OPTIONS__: MarkdownPowerPluginOptions
declare const __MD_POWER_DASHJS_INSTALLED__: boolean
declare const __MD_POWER_HLSJS_INSTALLED__: boolean
declare const __MD_POWER_MPEGTSJS_INSTALLED__: boolean
declare const __MD_POWER_ENCRYPT_LOCALES__: LocaleConfig<EncryptSnippetLocale>
export const pluginOptions: MarkdownPowerPluginOptions = __MD_POWER_INJECT_OPTIONS__ export const pluginOptions: MarkdownPowerPluginOptions = __MD_POWER_INJECT_OPTIONS__
export const installed: { export const installed: {
@ -33,3 +41,5 @@ export const INJECT_TIMELINE_KEY: symbol = Symbol(
export const INJECT_COLLAPSE_KEY: symbol = Symbol( export const INJECT_COLLAPSE_KEY: symbol = Symbol(
__VUEPRESS_DEV__ ? 'collapse' : '', __VUEPRESS_DEV__ ? 'collapse' : '',
) )
export const ENCRYPT_LOCALES = __MD_POWER_ENCRYPT_LOCALES__

View File

@ -1,5 +1,3 @@
import type { ReplEditorData } from '../shared/repl.js'
declare module '*.vue' { declare module '*.vue' {
import type { ComponentOptions } from 'vue' import type { ComponentOptions } from 'vue'
@ -8,16 +6,13 @@ declare module '*.vue' {
} }
declare module '@internal/md-power/replEditorData' { declare module '@internal/md-power/replEditorData' {
import type { ReplEditorData } from '../shared/repl.js'
const res: ReplEditorData const res: ReplEditorData
export default res export default res
} }
declare global { declare module '@internal/encrypt-snippets' {
const res: Record<string, () => Promise<{ default: string }>>
const __MD_POWER_INJECT_OPTIONS__: MarkdownPowerPluginOptions export default res
const __MD_POWER_DASHJS_INSTALLED__: boolean
const __MD_POWER_HLSJS_INSTALLED__: boolean
const __MD_POWER_MPEGTSJS_INSTALLED__: boolean
} }

View File

@ -0,0 +1,80 @@
import type { App } from 'vuepress/core'
import type { Markdown } from 'vuepress/markdown'
import type { EncryptSnippetOptions } from '../../shared/encrypt'
import { getRandomValues } from 'node:crypto'
import { debounce } from '@pengzhanbo/utils'
import { encodeData, ensureLeadingSlash } from '@vuepress/helper'
import { colors, fs, hash } from 'vuepress/utils'
import { cleanMarkdownEnv } from '../utils/cleanMarkdownEnv'
import { encryptContent } from '../utils/encryptContent'
import { logger } from '../utils/logger'
import { createContainerSyntaxPlugin } from './createContainer'
interface EncryptOptions {
password: string
salt: Uint8Array
iv: Uint8Array
}
export function encryptPlugin(app: App, md: Markdown, options: EncryptSnippetOptions): void {
const encrypted: Set<string> = new Set()
const entryFile = 'internal/encrypt-snippets/index.js'
const writeTemp = async (
hash: string,
content: string,
options: EncryptOptions,
) => {
const encrypted = await encryptContent(content, options)
await app.writeTemp(`internal/encrypt-snippets/${hash}.js`, `export default ${JSON.stringify(encrypted)}`)
}
const writeEntry = debounce(150, async () => {
let content = `export default {\n`
for (const hash of encrypted) {
content += ` '${hash}': () => import('./${hash}.js' /* webpackChunkName: "snippet-${hash}" */),\n`
}
content += '\n}\n'
app.writeTemp(entryFile, content)
})
if (!fs.existsSync(app.dir.temp(entryFile))) {
// 初始化
app.writeTemp(entryFile, 'export default {}\n')
}
const localKeys = Object.keys(app.options.locales || {}).filter(key => key !== '/')
const getLocale = (relativePath: string) => {
const relative = ensureLeadingSlash(relativePath)
return localKeys.find(key => relative.startsWith(key)) || '/'
}
createContainerSyntaxPlugin(md, 'encrypt', (tokens, index, _, env) => {
const { meta, content } = tokens[index]
const { password, pwd, hint } = meta as { password?: string, pwd?: string, hint?: string }
const rendered = md.render(content, cleanMarkdownEnv(env))
const _pwd = password || pwd || options.password
if (!_pwd) {
logger.warn(`${colors.cyan('[encrypt snippet]')} ${colors.green('::: encrypt')} container missing password. ${colors.gray(`(${env.filePathRelative})`)}`)
return rendered
}
const contentHash = hash(content)
encrypted.add(contentHash)
const salt = getRandomValues(new Uint8Array(16))
const iv = getRandomValues(new Uint8Array(16))
writeEntry()
writeTemp(contentHash, rendered, { salt, iv, password: String(_pwd) })
const data = encodeData(JSON.stringify({
hash: contentHash,
salt: Array.from(salt),
iv: Array.from(iv),
}))
return `<VPEncryptSnippet data="${data}" hint="${hint || ''}" path-locale="${getLocale(env.filePathRelative)}" />`
})
}

View File

@ -9,6 +9,7 @@ import { codeTabs } from './codeTabs.js'
import { codeTreePlugin } from './codeTree.js' import { codeTreePlugin } from './codeTree.js'
import { collapsePlugin } from './collapse.js' import { collapsePlugin } from './collapse.js'
import { demoWrapperPlugin } from './demoWrapper.js' import { demoWrapperPlugin } from './demoWrapper.js'
import { encryptPlugin } from './encrypt.js'
import { fieldPlugin } from './field.js' import { fieldPlugin } from './field.js'
import { fileTreePlugin } from './fileTree.js' import { fileTreePlugin } from './fileTree.js'
import { langReplPlugin } from './langRepl.js' import { langReplPlugin } from './langRepl.js'
@ -39,6 +40,11 @@ export async function containerPlugin(
// ::: card / card-grid // ::: card / card-grid
cardPlugin(md) cardPlugin(md)
if (options.encrypt) {
// ::: encrypt password="xxx"
encryptPlugin(app, md, typeof options.encrypt === 'boolean' ? {} : options.encrypt)
}
if (options.npmTo) { if (options.npmTo) {
// ::: npm-to // ::: npm-to
npmToPlugins(md, typeof options.npmTo === 'boolean' ? {} : options.npmTo) npmToPlugins(md, typeof options.npmTo === 'boolean' ? {} : options.npmTo)

View File

@ -0,0 +1,12 @@
import type { MDPowerLocaleData } from '../../shared/locale'
export const deLocale: MDPowerLocaleData = {
encrypt: {
hint: 'Der Inhalt ist verschlüsselt, bitte entsperren Sie ihn, um ihn anzuzeigen.',
placeholder: 'Passwort eingeben',
incPwd: 'Falsches Passwort',
noContent: 'Entsperrt, aber der Inhalt konnte nicht geladen werden. Bitte versuchen Sie es später erneut.',
warningTitle: '🚨 Sicherheitswarnung:',
warningText: 'Ihre Verbindung ist nicht mit HTTPS verschlüsselt, was ein Risiko für Inhaltslecks darstellt und den Zugriff auf verschlüsselte Inhalte verhindert.',
},
}

View File

@ -0,0 +1,12 @@
import type { MDPowerLocaleData } from '../../shared/locale'
export const enLocale: MDPowerLocaleData = {
encrypt: {
hint: 'The content is encrypted, please unlock to view.',
placeholder: 'Enter password',
incPwd: 'Incorrect password',
noContent: 'Unlocked, but content failed to load, please try again later.',
warningTitle: '🚨 Security Warning:',
warningText: 'Your connection is not encrypted with HTTPS, posing a risk of content leakage and preventing access to encrypted content.',
},
}

View File

@ -0,0 +1,12 @@
import type { MDPowerLocaleData } from '../../shared/locale'
export const frLocale: MDPowerLocaleData = {
encrypt: {
hint: 'Le contenu est chiffré, veuillez déverrouiller pour afficher.',
placeholder: 'Entrez le mot de passe',
incPwd: 'Mot de passe incorrect',
noContent: 'Déverrouillé, mais le contenu n\'a pas pu être chargé, veuillez réessayer plus tard.',
warningTitle: '🚨 Avertissement de sécurité :',
warningText: 'Votre connexion n\'est pas chiffrée avec HTTPS, ce qui présente un risque de fuite de contenu et empêche l\'accès au contenu chiffré.',
},
}

View File

@ -0,0 +1,21 @@
import type { DefaultLocaleInfo } from '@vuepress/helper'
import type { MDPowerLocaleData } from '../../shared/locale'
import { deLocale } from './de'
import { enLocale } from './en'
import { frLocale } from './fr'
import { jaLocale } from './ja'
import { koLocale } from './ko'
import { ruLocale } from './ru'
import { zhLocale } from './zh'
import { zhTWLocale } from './zh-tw'
export const LOCALE_OPTIONS: DefaultLocaleInfo<MDPowerLocaleData> = [
[['en', 'en-US'], enLocale],
[['zh', 'zh-CN', 'zh-Hans', 'zh-Hant'], zhLocale],
[['zh-TW'], zhTWLocale],
[['de', 'de-DE'], deLocale],
[['fr', 'fr-FR'], frLocale],
[['ru', 'ru-RU'], ruLocale],
[['ja', 'ja-JP'], jaLocale],
[['ko', 'ko-KR'], koLocale],
]

View File

@ -0,0 +1,12 @@
import type { MDPowerLocaleData } from '../../shared/locale'
export const jaLocale: MDPowerLocaleData = {
encrypt: {
hint: 'コンテンツは暗号化されています。閲覧するにはロックを解除してください。',
placeholder: 'パスワードを入力',
incPwd: 'パスワードが間違っています',
noContent: 'ロックは解除されましたが、コンテンツの読み込みに失敗しました。後ほど再度お試しください。',
warningTitle: '🚨 セキュリティ警告:',
warningText: '接続がHTTPSで暗号化されていないため、コンテンツの漏洩リスクがあり、暗号化されたコンテンツへのアクセスができません。',
},
}

View File

@ -0,0 +1,12 @@
import type { MDPowerLocaleData } from '../../shared/locale'
export const koLocale: MDPowerLocaleData = {
encrypt: {
hint: '내용이 암호화되어 있습니다. 잠금 해제 후 확인하세요.',
placeholder: '비밀번호 입력',
incPwd: '잘못된 비밀번호',
noContent: '잠금이 해제되었지만 내용을 불러오지 못했습니다. 나중에 다시 시도해 주세요.',
warningTitle: '🚨 보안 경고:',
warningText: '연결이 HTTPS로 암호화되지 않아 내용 유출 위험이 있으며, 암호화된 콘텐츠에 접근할 수 없습니다.',
},
}

View File

@ -0,0 +1,12 @@
import type { MDPowerLocaleData } from '../../shared/locale'
export const ruLocale: MDPowerLocaleData = {
encrypt: {
hint: 'Контент зашифрован, разблокируйте для просмотра.',
placeholder: 'Введите пароль',
incPwd: 'Неверный пароль',
noContent: 'Разблокировано, но не удалось загрузить содержимое. Повторите попытку позже.',
warningTitle: '🚨 Предупреждение безопасности:',
warningText: 'Ваше соединение не защищено HTTPS, что создает риск утечки данных и блокирует доступ к зашифрованному контенту.',
},
}

View File

@ -0,0 +1,12 @@
import type { MDPowerLocaleData } from '../../shared/locale'
export const zhTWLocale: MDPowerLocaleData = {
encrypt: {
hint: '內容已加密,請解鎖後查看。',
placeholder: '輸入密碼',
incPwd: '密碼錯誤',
noContent: '已解鎖,但內容載入失敗,請稍後再試。',
warningTitle: '🚨 安全警告:',
warningText: '您的連線未使用 HTTPS 加密,可能導致內容洩露風險,無法存取加密內容。',
},
}

View File

@ -0,0 +1,12 @@
import type { MDPowerLocaleData } from '../../shared/locale'
export const zhLocale: MDPowerLocaleData = {
encrypt: {
hint: '内容已加密,请解锁后查看。',
placeholder: '输入密码',
incPwd: '密码错误',
noContent: '已解锁,但内容加载失败,请稍后再试。',
warningTitle: '🚨 安全警告:',
warningText: '您的连接未使用HTTPS加密存在内容泄露风险无法访问加密内容。',
},
}

View File

@ -22,7 +22,14 @@ export function markdownPowerPlugin(
clientConfigFile: app => prepareConfigFile(app, options), clientConfigFile: app => prepareConfigFile(app, options),
define: provideData(options), define: app => provideData(app, options),
alias: (_, isServer) => {
if (!isServer) {
return { ...options.encrypt ? { '/^vue$/': 'vue/dist/vue.esm-bundler.js' } : undefined }
}
return {}
},
extendsBundlerOptions(bundlerOptions, app) { extendsBundlerOptions(bundlerOptions, app) {
if (options.repl) { if (options.repl) {

View File

@ -21,6 +21,11 @@ export async function prepareConfigFile(app: App, options: MarkdownPowerPluginOp
imports.add(`import CodeTabs from '${CLIENT_FOLDER}components/CodeTabs.vue'`) imports.add(`import CodeTabs from '${CLIENT_FOLDER}components/CodeTabs.vue'`)
enhances.add(`app.component('CodeTabs', CodeTabs)`) enhances.add(`app.component('CodeTabs', CodeTabs)`)
if (options.encrypt) {
imports.add(`import VPEncryptSnippet from '${CLIENT_FOLDER}components/VPEncryptSnippet.vue'`)
enhances.add(`app.component('VPEncryptSnippet', VPEncryptSnippet)`)
}
if (options.pdf) { if (options.pdf) {
imports.add(`import PDFViewer from '${CLIENT_FOLDER}components/PDFViewer.vue'`) imports.add(`import PDFViewer from '${CLIENT_FOLDER}components/PDFViewer.vue'`)
enhances.add(`app.component('PDFViewer', PDFViewer)`) enhances.add(`app.component('PDFViewer', PDFViewer)`)

View File

@ -1,19 +1,44 @@
import type { App, LocaleConfig } from 'vuepress'
import type { MarkdownPowerPluginOptions } from '../shared/index.js' import type { MarkdownPowerPluginOptions } from '../shared/index.js'
import type { MDPowerLocaleData } from '../shared/locale.js'
import { getFullLocaleConfig } from '@vuepress/helper'
import { isPackageExists } from 'local-pkg' import { isPackageExists } from 'local-pkg'
import { LOCALE_OPTIONS } from './locales/index.js'
export function provideData(options: MarkdownPowerPluginOptions): Record<string, unknown> { export function provideData(app: App, options: MarkdownPowerPluginOptions): Record<string, unknown> {
const mardownOptions = { const markdownOptions = {
plot: options.plot, plot: options.plot,
pdf: options.pdf, pdf: options.pdf,
} }
const locales = getFullLocaleConfig({
app,
name: 'vuepress-plugin-md-power',
default: LOCALE_OPTIONS,
config: options.locales,
})
const icon = options.icon ?? { provider: 'iconify' } const icon = options.icon ?? { provider: 'iconify' }
return { return {
__MD_POWER_INJECT_OPTIONS__: mardownOptions, __MD_POWER_INJECT_OPTIONS__: markdownOptions,
__MD_POWER_DASHJS_INSTALLED__: isPackageExists('dashjs'), __MD_POWER_DASHJS_INSTALLED__: isPackageExists('dashjs'),
__MD_POWER_HLSJS_INSTALLED__: isPackageExists('hls.js'), __MD_POWER_HLSJS_INSTALLED__: isPackageExists('hls.js'),
__MD_POWER_MPEGTSJS_INSTALLED__: isPackageExists('mpegts.js'), __MD_POWER_MPEGTSJS_INSTALLED__: isPackageExists('mpegts.js'),
__MD_POWER_ICON_PROVIDER__: icon.provider || 'iconify', __MD_POWER_ICON_PROVIDER__: icon.provider || 'iconify',
__MD_POWER_ICON_PREFIX__: icon.prefix || '', __MD_POWER_ICON_PREFIX__: icon.prefix || '',
__MD_POWER_ENCRYPT_LOCALES__: options.encrypt ? findLocales(locales, 'encrypt') : {},
} }
} }
function findLocales<
T extends MDPowerLocaleData,
K extends keyof T,
>(locales: LocaleConfig<T>, key: K): Record<string, T[K]> {
const res: Record<string, T[K]> = {}
for (const [locale, value] of Object.entries(locales)) {
res[locale] = value[key] ?? {} as T[K]
}
return res
}

View File

@ -0,0 +1,60 @@
import { webcrypto } from 'node:crypto'
/**
* @see https://developer.mozilla.org/zh-CN/docs/Web/API/SubtleCrypto/deriveKey#pbkdf2_2
* @param password
*/
function getKeyMaterial(password: string) {
const enc = new TextEncoder()
return webcrypto.subtle.importKey(
'raw',
enc.encode(password),
'PBKDF2',
false,
['deriveBits', 'deriveKey'],
)
}
function getCryptoDeriveKey(keyMaterial: CryptoKey | webcrypto.CryptoKey, salt: Uint8Array) {
return webcrypto.subtle.deriveKey(
{
name: 'PBKDF2',
salt: salt as unknown as ArrayBuffer,
iterations: 100000,
hash: 'SHA-256',
},
keyMaterial,
{
name: 'AES-CBC',
length: 256,
},
true,
['encrypt', 'decrypt'],
)
}
/**
* @see https://github.com/mdn/dom-examples/blob/main/web-crypto/encrypt-decrypt/aes-cbc.js
* @param content
*/
export async function encryptContent(content: string, options: {
password: string
iv: Uint8Array
salt: Uint8Array
}) {
const { password, iv, salt } = options
const keyMaterial = await getKeyMaterial(password)
const key = await getCryptoDeriveKey(keyMaterial, salt)
const enc = new TextEncoder()
const cipherTextData = await webcrypto.subtle.encrypt(
{
name: 'AES-CBC',
iv: iv as unknown as ArrayBuffer,
},
key,
enc.encode(content),
)
return String.fromCharCode(...new Uint8Array(cipherTextData))
}

View File

@ -0,0 +1,36 @@
import type { LocaleData } from 'vuepress'
export interface EncryptSnippetLocale extends LocaleData {
/**
* @default 'The content is encrypted, please unlock to view.''
*/
hint?: string
/**
* @default 'Enter password'
*/
placeholder?: string
/**
* @default 'Incorrect password'
*/
incPwd?: string
/**
* @default 'Unlocked, but content failed to load, please try again later.'
*/
noContent?: string
/**
* @default '🚨 Security Warning:'
*/
warningTitle?: string
/**
* @default 'Your connection is not encrypted with HTTPS, posing a risk of content leakage and preventing access to encrypted content.'
*/
warningText?: string
}
export interface EncryptSnippetOptions {
/**
* default password
*/
password?: string
}

View File

@ -0,0 +1,6 @@
import type { LocaleData } from 'vuepress'
import type { EncryptSnippetLocale } from './encrypt'
export interface MDPowerLocaleData extends LocaleData {
encrypt?: EncryptSnippetLocale
}

View File

@ -1,9 +1,12 @@
import type { LocaleConfig } from 'vuepress'
import type { CanIUseOptions } from './caniuse.js' import type { CanIUseOptions } from './caniuse.js'
import type { CodeTabsOptions } from './codeTabs.js' import type { CodeTabsOptions } from './codeTabs.js'
import type { CodeTreeOptions } from './codeTree.js' import type { CodeTreeOptions } from './codeTree.js'
import type { EncryptSnippetOptions } from './encrypt.js'
import type { MarkdownEnvPreset } from './env.js' import type { MarkdownEnvPreset } from './env.js'
import type { FileTreeOptions } from './fileTree.js' import type { FileTreeOptions } from './fileTree.js'
import type { IconOptions } from './icon.js' import type { IconOptions } from './icon.js'
import type { MDPowerLocaleData } from './locale.js'
import type { MarkOptions } from './mark.js' import type { MarkOptions } from './mark.js'
import type { NpmToOptions } from './npmTo.js' import type { NpmToOptions } from './npmTo.js'
import type { PDFOptions } from './pdf.js' import type { PDFOptions } from './pdf.js'
@ -55,6 +58,13 @@ export interface MarkdownPowerPluginOptions {
* @default 'eager' * @default 'eager'
*/ */
mark?: MarkOptions mark?: MarkOptions
/**
*
*
* @default false
*/
encrypt?: boolean | EncryptSnippetOptions
/** /**
* *
*/ */
@ -310,4 +320,6 @@ export interface MarkdownPowerPluginOptions {
* @default false * @default false
*/ */
imageSize?: boolean | 'local' | 'all' imageSize?: boolean | 'local' | 'all'
locales?: LocaleConfig<MDPowerLocaleData>
} }

View File

@ -4,7 +4,7 @@ import { argv } from '../../scripts/tsdown-args.mjs'
/** @import {Options} from 'tsdown' */ /** @import {Options} from 'tsdown' */
const config = [ const config = [
{ dir: 'composables', files: ['codeRepl.ts', 'pdf.ts', 'rustRepl.ts', 'size.ts', 'audio.ts', 'demo.ts', 'mark.ts'] }, { dir: 'composables', files: ['codeRepl.ts', 'pdf.ts', 'rustRepl.ts', 'size.ts', 'audio.ts', 'demo.ts', 'mark.ts', 'decrypt.ts'] },
{ dir: 'utils', files: ['http.ts', 'link.ts', 'sleep.ts'] }, { dir: 'utils', files: ['http.ts', 'link.ts', 'sleep.ts'] },
{ dir: '', files: ['index.ts', 'options.ts'] }, { dir: '', files: ['index.ts', 'options.ts'] },
] ]

359
pnpm-lock.yaml generated
View File

@ -213,11 +213,11 @@ catalogs:
specifier: ^3.1.0 specifier: ^3.1.0
version: 3.1.0 version: 3.1.0
'@vueuse/core': '@vueuse/core':
specifier: ^14.1.0 specifier: ^14.2.0
version: 14.1.0 version: 14.2.1
'@vueuse/integrations': '@vueuse/integrations':
specifier: ^14.1.0 specifier: ^14.2.0
version: 14.1.0 version: 14.2.1
cac: cac:
specifier: ^6.7.14 specifier: ^6.7.14
version: 6.7.14 version: 6.7.14
@ -400,7 +400,7 @@ overrides:
chokidar: 5.0.0 chokidar: 5.0.0
esbuild: ^0.27.2 esbuild: ^0.27.2
sass-embedded: ^1.97.2 sass-embedded: ^1.97.2
vite: ^8.0.0-beta.8 vite: ^8.0.0-beta.10
vue-router: ^4.6.4 vue-router: ^4.6.4
patchedDependencies: patchedDependencies:
@ -688,7 +688,7 @@ importers:
version: 2.0.0-rc.122(typescript@5.9.3)(vuepress@2.0.0-rc.26(@vuepress/bundler-vite@2.0.0-rc.26(@types/node@25.0.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(sass-embedded@1.97.2)(sass@1.97.2)(stylus@0.64.0)(typescript@5.9.3)(yaml@2.8.2))(typescript@5.9.3)(vue@3.5.27(typescript@5.9.3))) version: 2.0.0-rc.122(typescript@5.9.3)(vuepress@2.0.0-rc.26(@vuepress/bundler-vite@2.0.0-rc.26(@types/node@25.0.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(sass-embedded@1.97.2)(sass@1.97.2)(stylus@0.64.0)(typescript@5.9.3)(yaml@2.8.2))(typescript@5.9.3)(vue@3.5.27(typescript@5.9.3)))
'@vueuse/core': '@vueuse/core':
specifier: catalog:prod specifier: catalog:prod
version: 14.1.0(vue@3.5.27(typescript@5.9.3)) version: 14.2.1(vue@3.5.27(typescript@5.9.3))
chokidar: chokidar:
specifier: 5.0.0 specifier: 5.0.0
version: 5.0.0 version: 5.0.0
@ -773,10 +773,10 @@ importers:
version: 2.0.0-rc.122(typescript@5.9.3)(vuepress@2.0.0-rc.26(@vuepress/bundler-vite@2.0.0-rc.26(@types/node@25.0.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(sass-embedded@1.97.2)(sass@1.97.2)(stylus@0.64.0)(typescript@5.9.3)(yaml@2.8.2))(typescript@5.9.3)(vue@3.5.27(typescript@5.9.3))) version: 2.0.0-rc.122(typescript@5.9.3)(vuepress@2.0.0-rc.26(@vuepress/bundler-vite@2.0.0-rc.26(@types/node@25.0.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(sass-embedded@1.97.2)(sass@1.97.2)(stylus@0.64.0)(typescript@5.9.3)(yaml@2.8.2))(typescript@5.9.3)(vue@3.5.27(typescript@5.9.3)))
'@vueuse/core': '@vueuse/core':
specifier: catalog:prod specifier: catalog:prod
version: 14.1.0(vue@3.5.27(typescript@5.9.3)) version: 14.2.1(vue@3.5.27(typescript@5.9.3))
'@vueuse/integrations': '@vueuse/integrations':
specifier: catalog:prod specifier: catalog:prod
version: 14.1.0(axios@1.13.2)(change-case@5.4.4)(focus-trap@7.8.0)(qrcode@1.5.4)(vue@3.5.27(typescript@5.9.3)) version: 14.2.1(axios@1.13.2)(change-case@5.4.4)(focus-trap@7.8.0)(qrcode@1.5.4)(vue@3.5.27(typescript@5.9.3))
chokidar: chokidar:
specifier: 5.0.0 specifier: 5.0.0
version: 5.0.0 version: 5.0.0
@ -872,7 +872,7 @@ importers:
version: 2.0.0-rc.122(typescript@5.9.3)(vuepress@2.0.0-rc.26(@vuepress/bundler-vite@2.0.0-rc.26(@types/node@25.0.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(sass-embedded@1.97.2)(sass@1.97.2)(stylus@0.64.0)(typescript@5.9.3)(yaml@2.8.2))(typescript@5.9.3)(vue@3.5.27(typescript@5.9.3))) version: 2.0.0-rc.122(typescript@5.9.3)(vuepress@2.0.0-rc.26(@vuepress/bundler-vite@2.0.0-rc.26(@types/node@25.0.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(sass-embedded@1.97.2)(sass@1.97.2)(stylus@0.64.0)(typescript@5.9.3)(yaml@2.8.2))(typescript@5.9.3)(vue@3.5.27(typescript@5.9.3)))
'@vuepress/plugin-shiki': '@vuepress/plugin-shiki':
specifier: catalog:vuepress specifier: catalog:vuepress
version: 2.0.0-rc.122(@vuepress/shiki-twoslash@2.0.0-rc.122(typescript@5.9.3)(vue@3.5.27(typescript@5.9.3))(vuepress@2.0.0-rc.26(@vuepress/bundler-vite@2.0.0-rc.26(@types/node@25.0.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(sass-embedded@1.97.2)(sass@1.97.2)(stylus@0.64.0)(typescript@5.9.3)(yaml@2.8.2))(typescript@5.9.3)(vue@3.5.27(typescript@5.9.3))))(@vueuse/core@14.1.0(vue@3.5.27(typescript@5.9.3)))(typescript@5.9.3)(vuepress@2.0.0-rc.26(@vuepress/bundler-vite@2.0.0-rc.26(@types/node@25.0.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(sass-embedded@1.97.2)(sass@1.97.2)(stylus@0.64.0)(typescript@5.9.3)(yaml@2.8.2))(typescript@5.9.3)(vue@3.5.27(typescript@5.9.3))) version: 2.0.0-rc.122(@vuepress/shiki-twoslash@2.0.0-rc.122(typescript@5.9.3)(vue@3.5.27(typescript@5.9.3))(vuepress@2.0.0-rc.26(@vuepress/bundler-vite@2.0.0-rc.26(@types/node@25.0.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(sass-embedded@1.97.2)(sass@1.97.2)(stylus@0.64.0)(typescript@5.9.3)(yaml@2.8.2))(typescript@5.9.3)(vue@3.5.27(typescript@5.9.3))))(@vueuse/core@14.2.1(vue@3.5.27(typescript@5.9.3)))(typescript@5.9.3)(vuepress@2.0.0-rc.26(@vuepress/bundler-vite@2.0.0-rc.26(@types/node@25.0.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(sass-embedded@1.97.2)(sass@1.97.2)(stylus@0.64.0)(typescript@5.9.3)(yaml@2.8.2))(typescript@5.9.3)(vue@3.5.27(typescript@5.9.3)))
'@vuepress/plugin-sitemap': '@vuepress/plugin-sitemap':
specifier: catalog:vuepress specifier: catalog:vuepress
version: 2.0.0-rc.122(typescript@5.9.3)(vuepress@2.0.0-rc.26(@vuepress/bundler-vite@2.0.0-rc.26(@types/node@25.0.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(sass-embedded@1.97.2)(sass@1.97.2)(stylus@0.64.0)(typescript@5.9.3)(yaml@2.8.2))(typescript@5.9.3)(vue@3.5.27(typescript@5.9.3))) version: 2.0.0-rc.122(typescript@5.9.3)(vuepress@2.0.0-rc.26(@vuepress/bundler-vite@2.0.0-rc.26(@types/node@25.0.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(sass-embedded@1.97.2)(sass@1.97.2)(stylus@0.64.0)(typescript@5.9.3)(yaml@2.8.2))(typescript@5.9.3)(vue@3.5.27(typescript@5.9.3)))
@ -884,7 +884,7 @@ importers:
version: 2.0.0-rc.122(typescript@5.9.3)(vue@3.5.27(typescript@5.9.3))(vuepress@2.0.0-rc.26(@vuepress/bundler-vite@2.0.0-rc.26(@types/node@25.0.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(sass-embedded@1.97.2)(sass@1.97.2)(stylus@0.64.0)(typescript@5.9.3)(yaml@2.8.2))(typescript@5.9.3)(vue@3.5.27(typescript@5.9.3))) version: 2.0.0-rc.122(typescript@5.9.3)(vue@3.5.27(typescript@5.9.3))(vuepress@2.0.0-rc.26(@vuepress/bundler-vite@2.0.0-rc.26(@types/node@25.0.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(sass-embedded@1.97.2)(sass@1.97.2)(stylus@0.64.0)(typescript@5.9.3)(yaml@2.8.2))(typescript@5.9.3)(vue@3.5.27(typescript@5.9.3)))
'@vueuse/core': '@vueuse/core':
specifier: catalog:prod specifier: catalog:prod
version: 14.1.0(vue@3.5.27(typescript@5.9.3)) version: 14.2.1(vue@3.5.27(typescript@5.9.3))
chokidar: chokidar:
specifier: 5.0.0 specifier: 5.0.0
version: 5.0.0 version: 5.0.0
@ -1956,8 +1956,8 @@ packages:
resolution: {integrity: sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==} resolution: {integrity: sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==}
engines: {node: '>=8.0.0'} engines: {node: '>=8.0.0'}
'@oxc-project/runtime@0.108.0': '@oxc-project/runtime@0.113.0':
resolution: {integrity: sha512-J1cESY4anMO4i9KtCPmCfQAzAR00Uw4SWsDPFP10CIwDMugkh34UrTKByuYKuPaHy0XAk8LlJiZJq2OLMfbuIQ==} resolution: {integrity: sha512-apRWH/gXeAsl/sQiblIZnLu7f8P/C9S2fJIicuHV9KOK9J7Hv1JPyTwB8WAcOrDBfjs+cbzjMOGe9UR2ue4ZQg==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
'@oxc-project/types@0.107.0': '@oxc-project/types@0.107.0':
@ -1966,6 +1966,9 @@ packages:
'@oxc-project/types@0.108.0': '@oxc-project/types@0.108.0':
resolution: {integrity: sha512-7lf13b2IA/kZO6xgnIZA88sq3vwrxWk+2vxf6cc+omwYCRTiA5e63Beqf3fz/v8jEviChWWmFYBwzfSeyrsj7Q==} resolution: {integrity: sha512-7lf13b2IA/kZO6xgnIZA88sq3vwrxWk+2vxf6cc+omwYCRTiA5e63Beqf3fz/v8jEviChWWmFYBwzfSeyrsj7Q==}
'@oxc-project/types@0.113.0':
resolution: {integrity: sha512-Tp3XmgxwNQ9pEN9vxgJBAqdRamHibi76iowQ38O2I4PMpcvNRQNVsU2n1x1nv9yh0XoTrGFzf7cZSGxmixxrhA==}
'@parcel/watcher-android-arm64@2.5.1': '@parcel/watcher-android-arm64@2.5.1':
resolution: {integrity: sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==} resolution: {integrity: sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==}
engines: {node: '>= 10.0.0'} engines: {node: '>= 10.0.0'}
@ -2170,6 +2173,12 @@ packages:
cpu: [arm64] cpu: [arm64]
os: [android] os: [android]
'@rolldown/binding-android-arm64@1.0.0-rc.4':
resolution: {integrity: sha512-vRq9f4NzvbdZavhQbjkJBx7rRebDKYR9zHfO/Wg486+I7bSecdUapzCm5cyXoK+LHokTxgSq7A5baAXUZkIz0w==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64]
os: [android]
'@rolldown/binding-darwin-arm64@1.0.0-beta.59': '@rolldown/binding-darwin-arm64@1.0.0-beta.59':
resolution: {integrity: sha512-hqGXRc162qCCIOAcHN2Cw4eXiVTwYsMFLOhAy1IG2CxY+dwc/l4Ga+dLPkLor3Ikqy5WDn+7kxHbbh6EmshEpQ==} resolution: {integrity: sha512-hqGXRc162qCCIOAcHN2Cw4eXiVTwYsMFLOhAy1IG2CxY+dwc/l4Ga+dLPkLor3Ikqy5WDn+7kxHbbh6EmshEpQ==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
@ -2182,6 +2191,12 @@ packages:
cpu: [arm64] cpu: [arm64]
os: [darwin] os: [darwin]
'@rolldown/binding-darwin-arm64@1.0.0-rc.4':
resolution: {integrity: sha512-kFgEvkWLqt3YCgKB5re9RlIrx9bRsvyVUnaTakEpOPuLGzLpLapYxE9BufJNvPg8GjT6mB1alN4yN1NjzoeM8Q==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64]
os: [darwin]
'@rolldown/binding-darwin-x64@1.0.0-beta.59': '@rolldown/binding-darwin-x64@1.0.0-beta.59':
resolution: {integrity: sha512-ezvvGuhteE15JmMhJW0wS7BaXmhwLy1YHeEwievYaPC1PgGD86wgBKfOpHr9tSKllAXbCe0BeeMvasscWLhKdA==} resolution: {integrity: sha512-ezvvGuhteE15JmMhJW0wS7BaXmhwLy1YHeEwievYaPC1PgGD86wgBKfOpHr9tSKllAXbCe0BeeMvasscWLhKdA==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
@ -2194,6 +2209,12 @@ packages:
cpu: [x64] cpu: [x64]
os: [darwin] os: [darwin]
'@rolldown/binding-darwin-x64@1.0.0-rc.4':
resolution: {integrity: sha512-JXmaOJGsL/+rsmMfutcDjxWM2fTaVgCHGoXS7nE8Z3c9NAYjGqHvXrAhMUZvMpHS/k7Mg+X7n/MVKb7NYWKKww==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64]
os: [darwin]
'@rolldown/binding-freebsd-x64@1.0.0-beta.59': '@rolldown/binding-freebsd-x64@1.0.0-beta.59':
resolution: {integrity: sha512-4fhKVJiEYVd5n6no/mrL3LZ9kByfCGwmONOrdtvx8DJGDQhehH/q3RfhG3V/4jGKhpXgbDjpIjkkFdybCTcgew==} resolution: {integrity: sha512-4fhKVJiEYVd5n6no/mrL3LZ9kByfCGwmONOrdtvx8DJGDQhehH/q3RfhG3V/4jGKhpXgbDjpIjkkFdybCTcgew==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
@ -2206,6 +2227,12 @@ packages:
cpu: [x64] cpu: [x64]
os: [freebsd] os: [freebsd]
'@rolldown/binding-freebsd-x64@1.0.0-rc.4':
resolution: {integrity: sha512-ep3Catd6sPnHTM0P4hNEvIv5arnDvk01PfyJIJ+J3wVCG1eEaPo09tvFqdtcaTrkwQy0VWR24uz+cb4IsK53Qw==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64]
os: [freebsd]
'@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.59': '@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.59':
resolution: {integrity: sha512-T3Y52sW6JAhvIqArBw+wtjNU1Ieaz4g0NBxyjSJoW971nZJBZygNlSYx78G4cwkCmo1dYTciTPDOnQygLV23pA==} resolution: {integrity: sha512-T3Y52sW6JAhvIqArBw+wtjNU1Ieaz4g0NBxyjSJoW971nZJBZygNlSYx78G4cwkCmo1dYTciTPDOnQygLV23pA==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
@ -2218,6 +2245,12 @@ packages:
cpu: [arm] cpu: [arm]
os: [linux] os: [linux]
'@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.4':
resolution: {integrity: sha512-LwA5ayKIpnsgXJEwWc3h8wPiS33NMIHd9BhsV92T8VetVAbGe2qXlJwNVDGHN5cOQ22R9uYvbrQir2AB+ntT2w==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm]
os: [linux]
'@rolldown/binding-linux-arm64-gnu@1.0.0-beta.59': '@rolldown/binding-linux-arm64-gnu@1.0.0-beta.59':
resolution: {integrity: sha512-NIW40jQDSQap2KDdmm9z3B/4OzWJ6trf8dwx3FD74kcQb3v34ThsBFTtzE5KjDuxnxgUlV+DkAu+XgSMKrgufw==} resolution: {integrity: sha512-NIW40jQDSQap2KDdmm9z3B/4OzWJ6trf8dwx3FD74kcQb3v34ThsBFTtzE5KjDuxnxgUlV+DkAu+XgSMKrgufw==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
@ -2232,6 +2265,13 @@ packages:
os: [linux] os: [linux]
libc: [glibc] libc: [glibc]
'@rolldown/binding-linux-arm64-gnu@1.0.0-rc.4':
resolution: {integrity: sha512-AC1WsGdlV1MtGay/OQ4J9T7GRadVnpYRzTcygV1hKnypbYN20Yh4t6O1Sa2qRBMqv1etulUknqXjc3CTIsBu6A==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64]
os: [linux]
libc: [glibc]
'@rolldown/binding-linux-arm64-musl@1.0.0-beta.59': '@rolldown/binding-linux-arm64-musl@1.0.0-beta.59':
resolution: {integrity: sha512-CCKEk+H+8c0WGe/8n1E20n85Tq4Pv+HNAbjP1KfUXW+01aCWSMjU56ChNrM2tvHnXicfm7QRNoZyfY8cWh7jLQ==} resolution: {integrity: sha512-CCKEk+H+8c0WGe/8n1E20n85Tq4Pv+HNAbjP1KfUXW+01aCWSMjU56ChNrM2tvHnXicfm7QRNoZyfY8cWh7jLQ==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
@ -2246,6 +2286,13 @@ packages:
os: [linux] os: [linux]
libc: [musl] libc: [musl]
'@rolldown/binding-linux-arm64-musl@1.0.0-rc.4':
resolution: {integrity: sha512-lU+6rgXXViO61B4EudxtVMXSOfiZONR29Sys5VGSetUY7X8mg9FCKIIjcPPj8xNDeYzKl+H8F/qSKOBVFJChCQ==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64]
os: [linux]
libc: [musl]
'@rolldown/binding-linux-x64-gnu@1.0.0-beta.59': '@rolldown/binding-linux-x64-gnu@1.0.0-beta.59':
resolution: {integrity: sha512-VlfwJ/HCskPmQi8R0JuAFndySKVFX7yPhE658o27cjSDWWbXVtGkSbwaxstii7Q+3Rz87ZXN+HLnb1kd4R9Img==} resolution: {integrity: sha512-VlfwJ/HCskPmQi8R0JuAFndySKVFX7yPhE658o27cjSDWWbXVtGkSbwaxstii7Q+3Rz87ZXN+HLnb1kd4R9Img==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
@ -2260,6 +2307,13 @@ packages:
os: [linux] os: [linux]
libc: [glibc] libc: [glibc]
'@rolldown/binding-linux-x64-gnu@1.0.0-rc.4':
resolution: {integrity: sha512-DZaN1f0PGp/bSvKhtw50pPsnln4T13ycDq1FrDWRiHmWt1JeW+UtYg9touPFf8yt993p8tS2QjybpzKNTxYEwg==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64]
os: [linux]
libc: [glibc]
'@rolldown/binding-linux-x64-musl@1.0.0-beta.59': '@rolldown/binding-linux-x64-musl@1.0.0-beta.59':
resolution: {integrity: sha512-kuO92hTRyGy0Ts3Nsqll0rfO8eFsEJe9dGQGktkQnZ2hrJrDVN0y419dMgKy/gB2S2o7F2dpWhpfQOBehZPwVA==} resolution: {integrity: sha512-kuO92hTRyGy0Ts3Nsqll0rfO8eFsEJe9dGQGktkQnZ2hrJrDVN0y419dMgKy/gB2S2o7F2dpWhpfQOBehZPwVA==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
@ -2274,6 +2328,13 @@ packages:
os: [linux] os: [linux]
libc: [musl] libc: [musl]
'@rolldown/binding-linux-x64-musl@1.0.0-rc.4':
resolution: {integrity: sha512-RnGxwZLN7fhMMAItnD6dZ7lvy+TI7ba+2V54UF4dhaWa/p8I/ys1E73KO6HmPmgz92ZkfD8TXS1IMV8+uhbR9g==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64]
os: [linux]
libc: [musl]
'@rolldown/binding-openharmony-arm64@1.0.0-beta.59': '@rolldown/binding-openharmony-arm64@1.0.0-beta.59':
resolution: {integrity: sha512-PXAebvNL4sYfCqi8LdY4qyFRacrRoiPZLo3NoUmiTxm7MPtYYR8CNtBGNokqDmMuZIQIecRaD/jbmFAIDz7DxQ==} resolution: {integrity: sha512-PXAebvNL4sYfCqi8LdY4qyFRacrRoiPZLo3NoUmiTxm7MPtYYR8CNtBGNokqDmMuZIQIecRaD/jbmFAIDz7DxQ==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
@ -2286,6 +2347,12 @@ packages:
cpu: [arm64] cpu: [arm64]
os: [openharmony] os: [openharmony]
'@rolldown/binding-openharmony-arm64@1.0.0-rc.4':
resolution: {integrity: sha512-6lcI79+X8klGiGd8yHuTgQRjuuJYNggmEml+RsyN596P23l/zf9FVmJ7K0KVKkFAeYEdg0iMUKyIxiV5vebDNQ==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64]
os: [openharmony]
'@rolldown/binding-wasm32-wasi@1.0.0-beta.59': '@rolldown/binding-wasm32-wasi@1.0.0-beta.59':
resolution: {integrity: sha512-yJoklQg7XIZq8nAg0bbkEXcDK6sfpjxQGxpg2Nd6ERNtvg+eOaEBRgPww0BVTrYFQzje1pB5qPwC2VnJHT3koQ==} resolution: {integrity: sha512-yJoklQg7XIZq8nAg0bbkEXcDK6sfpjxQGxpg2Nd6ERNtvg+eOaEBRgPww0BVTrYFQzje1pB5qPwC2VnJHT3koQ==}
engines: {node: '>=14.0.0'} engines: {node: '>=14.0.0'}
@ -2296,6 +2363,11 @@ packages:
engines: {node: '>=14.0.0'} engines: {node: '>=14.0.0'}
cpu: [wasm32] cpu: [wasm32]
'@rolldown/binding-wasm32-wasi@1.0.0-rc.4':
resolution: {integrity: sha512-wz7ohsKCAIWy91blZ/1FlpPdqrsm1xpcEOQVveWoL6+aSPKL4VUcoYmmzuLTssyZxRpEwzuIxL/GDsvpjaBtOw==}
engines: {node: '>=14.0.0'}
cpu: [wasm32]
'@rolldown/binding-win32-arm64-msvc@1.0.0-beta.59': '@rolldown/binding-win32-arm64-msvc@1.0.0-beta.59':
resolution: {integrity: sha512-ljZ4+McmCbIuZwEBaoGtiG8Rq2nJjaXEnLEIx+usWetXn1ECjXY0LAhkELxOV6ytv4ensEmoJJ8nXg47hRMjlw==} resolution: {integrity: sha512-ljZ4+McmCbIuZwEBaoGtiG8Rq2nJjaXEnLEIx+usWetXn1ECjXY0LAhkELxOV6ytv4ensEmoJJ8nXg47hRMjlw==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
@ -2308,6 +2380,12 @@ packages:
cpu: [arm64] cpu: [arm64]
os: [win32] os: [win32]
'@rolldown/binding-win32-arm64-msvc@1.0.0-rc.4':
resolution: {integrity: sha512-cfiMrfuWCIgsFmcVG0IPuO6qTRHvF7NuG3wngX1RZzc6dU8FuBFb+J3MIR5WrdTNozlumfgL4cvz+R4ozBCvsQ==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64]
os: [win32]
'@rolldown/binding-win32-x64-msvc@1.0.0-beta.59': '@rolldown/binding-win32-x64-msvc@1.0.0-beta.59':
resolution: {integrity: sha512-bMY4tTIwbdZljW+xe/ln1hvs0SRitahQSXfWtvgAtIzgSX9Ar7KqJzU7lRm33YTRFIHLULRi53yNjw9nJGd6uQ==} resolution: {integrity: sha512-bMY4tTIwbdZljW+xe/ln1hvs0SRitahQSXfWtvgAtIzgSX9Ar7KqJzU7lRm33YTRFIHLULRi53yNjw9nJGd6uQ==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
@ -2320,6 +2398,12 @@ packages:
cpu: [x64] cpu: [x64]
os: [win32] os: [win32]
'@rolldown/binding-win32-x64-msvc@1.0.0-rc.4':
resolution: {integrity: sha512-p6UeR9y7ht82AH57qwGuFYn69S6CZ7LLKdCKy/8T3zS9VTrJei2/CGsTUV45Da4Z9Rbhc7G4gyWQ/Ioamqn09g==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64]
os: [win32]
'@rolldown/pluginutils@1.0.0-beta.29': '@rolldown/pluginutils@1.0.0-beta.29':
resolution: {integrity: sha512-NIJgOsMjbxAXvoGq/X0gD7VPMQ8j9g0BiDaNjVNVjvl+iKXxL3Jre0v31RmBYeLEmkbj2s02v8vFTbUXi5XS2Q==} resolution: {integrity: sha512-NIJgOsMjbxAXvoGq/X0gD7VPMQ8j9g0BiDaNjVNVjvl+iKXxL3Jre0v31RmBYeLEmkbj2s02v8vFTbUXi5XS2Q==}
@ -2329,6 +2413,9 @@ packages:
'@rolldown/pluginutils@1.0.0-beta.60': '@rolldown/pluginutils@1.0.0-beta.60':
resolution: {integrity: sha512-Jz4aqXRPVtqkH1E3jRDzLO5cgN5JwW+WG0wXGE4NiJd25nougv/AHzxmKCzmVQUYnxLmTM0M4wrZp+LlC2FKLg==} resolution: {integrity: sha512-Jz4aqXRPVtqkH1E3jRDzLO5cgN5JwW+WG0wXGE4NiJd25nougv/AHzxmKCzmVQUYnxLmTM0M4wrZp+LlC2FKLg==}
'@rolldown/pluginutils@1.0.0-rc.4':
resolution: {integrity: sha512-1BrrmTu0TWfOP1riA8uakjFc9bpIUGzVKETsOtzY39pPga8zELGDl8eu1Dx7/gjM5CAz14UknsUMpBO8L+YntQ==}
'@rollup/rollup-android-arm-eabi@4.52.4': '@rollup/rollup-android-arm-eabi@4.52.4':
resolution: {integrity: sha512-BTm2qKNnWIQ5auf4deoetINJm2JzvihvGb9R6K/ETwKLql/Bb3Eg2H1FBp1gUb4YGbydMA3jcmQTR73q7J+GAA==} resolution: {integrity: sha512-BTm2qKNnWIQ5auf4deoetINJm2JzvihvGb9R6K/ETwKLql/Bb3Eg2H1FBp1gUb4YGbydMA3jcmQTR73q7J+GAA==}
cpu: [arm] cpu: [arm]
@ -2929,7 +3016,7 @@ packages:
resolution: {integrity: sha512-+MaE752hU0wfPFJEUAIxqw18+20euHHdxVtMvbFcOEpjEyfqXH/5DCoTHiVJ0J29EhTJdoTkjEv5YBKU9dnoTw==} resolution: {integrity: sha512-+MaE752hU0wfPFJEUAIxqw18+20euHHdxVtMvbFcOEpjEyfqXH/5DCoTHiVJ0J29EhTJdoTkjEv5YBKU9dnoTw==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
peerDependencies: peerDependencies:
vite: ^8.0.0-beta.8 vite: ^8.0.0-beta.10
vue: ^3.2.25 vue: ^3.2.25
'@vitest/coverage-v8@4.0.17': '@vitest/coverage-v8@4.0.17':
@ -2961,7 +3048,7 @@ packages:
resolution: {integrity: sha512-+ZtQhLA3lDh1tI2wxe3yMsGzbp7uuJSWBM1iTIKCbppWTSBN09PUC+L+fyNlQApQoR+Ps8twt2pbSSXg2fQVEQ==} resolution: {integrity: sha512-+ZtQhLA3lDh1tI2wxe3yMsGzbp7uuJSWBM1iTIKCbppWTSBN09PUC+L+fyNlQApQoR+Ps8twt2pbSSXg2fQVEQ==}
peerDependencies: peerDependencies:
msw: ^2.4.9 msw: ^2.4.9
vite: ^8.0.0-beta.8 vite: ^8.0.0-beta.10
peerDependenciesMeta: peerDependenciesMeta:
msw: msw:
optional: true optional: true
@ -3219,24 +3306,19 @@ packages:
'@vuepress/utils@2.0.0-rc.26': '@vuepress/utils@2.0.0-rc.26':
resolution: {integrity: sha512-RWzZrGQ0WLSWdELuxg7c6q1D9I22T5PfK/qNFkOsv9eD3gpUsU4jq4zAoumS8o+NRIWHovCJ9WnAhHD0Ns5zAw==} resolution: {integrity: sha512-RWzZrGQ0WLSWdELuxg7c6q1D9I22T5PfK/qNFkOsv9eD3gpUsU4jq4zAoumS8o+NRIWHovCJ9WnAhHD0Ns5zAw==}
'@vueuse/core@14.1.0':
resolution: {integrity: sha512-rgBinKs07hAYyPF834mDTigH7BtPqvZ3Pryuzt1SD/lg5wEcWqvwzXXYGEDb2/cP0Sj5zSvHl3WkmMELr5kfWw==}
peerDependencies:
vue: ^3.5.0
'@vueuse/core@14.2.1': '@vueuse/core@14.2.1':
resolution: {integrity: sha512-3vwDzV+GDUNpdegRY6kzpLm4Igptq+GA0QkJ3W61Iv27YWwW/ufSlOfgQIpN6FZRMG0mkaz4gglJRtq5SeJyIQ==} resolution: {integrity: sha512-3vwDzV+GDUNpdegRY6kzpLm4Igptq+GA0QkJ3W61Iv27YWwW/ufSlOfgQIpN6FZRMG0mkaz4gglJRtq5SeJyIQ==}
peerDependencies: peerDependencies:
vue: ^3.5.0 vue: ^3.5.0
'@vueuse/integrations@14.1.0': '@vueuse/integrations@14.2.1':
resolution: {integrity: sha512-eNQPdisnO9SvdydTIXnTE7c29yOsJBD/xkwEyQLdhDC/LKbqrFpXHb3uS//7NcIrQO3fWVuvMGp8dbK6mNEMCA==} resolution: {integrity: sha512-2LIUpBi/67PoXJGqSDQUF0pgQWpNHh7beiA+KG2AbybcNm+pTGWT6oPGlBgUoDWmYwfeQqM/uzOHqcILpKL7nA==}
peerDependencies: peerDependencies:
async-validator: ^4 async-validator: ^4
axios: ^1 axios: ^1
change-case: ^5 change-case: ^5
drauu: ^0.4 drauu: ^0.4
focus-trap: ^7 focus-trap: ^7 || ^8
fuse.js: ^7 fuse.js: ^7
idb-keyval: ^6 idb-keyval: ^6
jwt-decode: ^4 jwt-decode: ^4
@ -3271,17 +3353,9 @@ packages:
universal-cookie: universal-cookie:
optional: true optional: true
'@vueuse/metadata@14.1.0':
resolution: {integrity: sha512-7hK4g015rWn2PhKcZ99NyT+ZD9sbwm7SGvp7k+k+rKGWnLjS/oQozoIZzWfCewSUeBmnJkIb+CNr7Zc/EyRnnA==}
'@vueuse/metadata@14.2.1': '@vueuse/metadata@14.2.1':
resolution: {integrity: sha512-1ButlVtj5Sb/HDtIy1HFr1VqCP4G6Ypqt5MAo0lCgjokrk2mvQKsK2uuy0vqu/Ks+sHfuHo0B9Y9jn9xKdjZsw==} resolution: {integrity: sha512-1ButlVtj5Sb/HDtIy1HFr1VqCP4G6Ypqt5MAo0lCgjokrk2mvQKsK2uuy0vqu/Ks+sHfuHo0B9Y9jn9xKdjZsw==}
'@vueuse/shared@14.1.0':
resolution: {integrity: sha512-EcKxtYvn6gx1F8z9J5/rsg3+lTQnvOruQd8fUecW99DCK04BkWD7z5KQ/wTAx+DazyoEE9dJt/zV8OIEQbM6kw==}
peerDependencies:
vue: ^3.5.0
'@vueuse/shared@14.2.1': '@vueuse/shared@14.2.1':
resolution: {integrity: sha512-shTJncjV9JTI4oVNyF1FQonetYAiTBd+Qj7cY89SWbXSkx7gyhrgtEdF2ZAVWS1S3SHlaROO6F2IesJxQEkZBw==} resolution: {integrity: sha512-shTJncjV9JTI4oVNyF1FQonetYAiTBd+Qj7cY89SWbXSkx7gyhrgtEdF2ZAVWS1S3SHlaROO6F2IesJxQEkZBw==}
peerDependencies: peerDependencies:
@ -5570,78 +5644,78 @@ packages:
lie@3.1.1: lie@3.1.1:
resolution: {integrity: sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw==} resolution: {integrity: sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw==}
lightningcss-android-arm64@1.30.2: lightningcss-android-arm64@1.31.1:
resolution: {integrity: sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A==} resolution: {integrity: sha512-HXJF3x8w9nQ4jbXRiNppBCqeZPIAfUo8zE/kOEGbW5NZvGc/K7nMxbhIr+YlFlHW5mpbg/YFPdbnCh1wAXCKFg==}
engines: {node: '>= 12.0.0'} engines: {node: '>= 12.0.0'}
cpu: [arm64] cpu: [arm64]
os: [android] os: [android]
lightningcss-darwin-arm64@1.30.2: lightningcss-darwin-arm64@1.31.1:
resolution: {integrity: sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA==} resolution: {integrity: sha512-02uTEqf3vIfNMq3h/z2cJfcOXnQ0GRwQrkmPafhueLb2h7mqEidiCzkE4gBMEH65abHRiQvhdcQ+aP0D0g67sg==}
engines: {node: '>= 12.0.0'} engines: {node: '>= 12.0.0'}
cpu: [arm64] cpu: [arm64]
os: [darwin] os: [darwin]
lightningcss-darwin-x64@1.30.2: lightningcss-darwin-x64@1.31.1:
resolution: {integrity: sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ==} resolution: {integrity: sha512-1ObhyoCY+tGxtsz1lSx5NXCj3nirk0Y0kB/g8B8DT+sSx4G9djitg9ejFnjb3gJNWo7qXH4DIy2SUHvpoFwfTA==}
engines: {node: '>= 12.0.0'} engines: {node: '>= 12.0.0'}
cpu: [x64] cpu: [x64]
os: [darwin] os: [darwin]
lightningcss-freebsd-x64@1.30.2: lightningcss-freebsd-x64@1.31.1:
resolution: {integrity: sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA==} resolution: {integrity: sha512-1RINmQKAItO6ISxYgPwszQE1BrsVU5aB45ho6O42mu96UiZBxEXsuQ7cJW4zs4CEodPUioj/QrXW1r9pLUM74A==}
engines: {node: '>= 12.0.0'} engines: {node: '>= 12.0.0'}
cpu: [x64] cpu: [x64]
os: [freebsd] os: [freebsd]
lightningcss-linux-arm-gnueabihf@1.30.2: lightningcss-linux-arm-gnueabihf@1.31.1:
resolution: {integrity: sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA==} resolution: {integrity: sha512-OOCm2//MZJ87CdDK62rZIu+aw9gBv4azMJuA8/KB74wmfS3lnC4yoPHm0uXZ/dvNNHmnZnB8XLAZzObeG0nS1g==}
engines: {node: '>= 12.0.0'} engines: {node: '>= 12.0.0'}
cpu: [arm] cpu: [arm]
os: [linux] os: [linux]
lightningcss-linux-arm64-gnu@1.30.2: lightningcss-linux-arm64-gnu@1.31.1:
resolution: {integrity: sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A==} resolution: {integrity: sha512-WKyLWztD71rTnou4xAD5kQT+982wvca7E6QoLpoawZ1gP9JM0GJj4Tp5jMUh9B3AitHbRZ2/H3W5xQmdEOUlLg==}
engines: {node: '>= 12.0.0'} engines: {node: '>= 12.0.0'}
cpu: [arm64] cpu: [arm64]
os: [linux] os: [linux]
libc: [glibc] libc: [glibc]
lightningcss-linux-arm64-musl@1.30.2: lightningcss-linux-arm64-musl@1.31.1:
resolution: {integrity: sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==} resolution: {integrity: sha512-mVZ7Pg2zIbe3XlNbZJdjs86YViQFoJSpc41CbVmKBPiGmC4YrfeOyz65ms2qpAobVd7WQsbW4PdsSJEMymyIMg==}
engines: {node: '>= 12.0.0'} engines: {node: '>= 12.0.0'}
cpu: [arm64] cpu: [arm64]
os: [linux] os: [linux]
libc: [musl] libc: [musl]
lightningcss-linux-x64-gnu@1.30.2: lightningcss-linux-x64-gnu@1.31.1:
resolution: {integrity: sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==} resolution: {integrity: sha512-xGlFWRMl+0KvUhgySdIaReQdB4FNudfUTARn7q0hh/V67PVGCs3ADFjw+6++kG1RNd0zdGRlEKa+T13/tQjPMA==}
engines: {node: '>= 12.0.0'} engines: {node: '>= 12.0.0'}
cpu: [x64] cpu: [x64]
os: [linux] os: [linux]
libc: [glibc] libc: [glibc]
lightningcss-linux-x64-musl@1.30.2: lightningcss-linux-x64-musl@1.31.1:
resolution: {integrity: sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==} resolution: {integrity: sha512-eowF8PrKHw9LpoZii5tdZwnBcYDxRw2rRCyvAXLi34iyeYfqCQNA9rmUM0ce62NlPhCvof1+9ivRaTY6pSKDaA==}
engines: {node: '>= 12.0.0'} engines: {node: '>= 12.0.0'}
cpu: [x64] cpu: [x64]
os: [linux] os: [linux]
libc: [musl] libc: [musl]
lightningcss-win32-arm64-msvc@1.30.2: lightningcss-win32-arm64-msvc@1.31.1:
resolution: {integrity: sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==} resolution: {integrity: sha512-aJReEbSEQzx1uBlQizAOBSjcmr9dCdL3XuC/6HLXAxmtErsj2ICo5yYggg1qOODQMtnjNQv2UHb9NpOuFtYe4w==}
engines: {node: '>= 12.0.0'} engines: {node: '>= 12.0.0'}
cpu: [arm64] cpu: [arm64]
os: [win32] os: [win32]
lightningcss-win32-x64-msvc@1.30.2: lightningcss-win32-x64-msvc@1.31.1:
resolution: {integrity: sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw==} resolution: {integrity: sha512-I9aiFrbd7oYHwlnQDqr1Roz+fTz61oDDJX7n9tYF9FJymH1cIN1DtKw3iYt6b8WZgEjoNwVSncwF4wx/ZedMhw==}
engines: {node: '>= 12.0.0'} engines: {node: '>= 12.0.0'}
cpu: [x64] cpu: [x64]
os: [win32] os: [win32]
lightningcss@1.30.2: lightningcss@1.31.1:
resolution: {integrity: sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ==} resolution: {integrity: sha512-l51N2r93WmGUye3WuFoN5k10zyvrVs0qfKBhyC5ogUQ6Ew6JUSswh78mbSO+IU3nTWsyOArqPCcShdQSadghBQ==}
engines: {node: '>= 12.0.0'} engines: {node: '>= 12.0.0'}
lilconfig@3.1.3: lilconfig@3.1.3:
@ -6729,6 +6803,11 @@ packages:
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
hasBin: true hasBin: true
rolldown@1.0.0-rc.4:
resolution: {integrity: sha512-V2tPDUrY3WSevrvU2E41ijZlpF+5PbZu4giH+VpNraaadsJGHa4fR6IFwsocVwEXDoAdIv5qgPPxgrvKAOIPtA==}
engines: {node: ^20.19.0 || >=22.12.0}
hasBin: true
rollup@4.52.4: rollup@4.52.4:
resolution: {integrity: sha512-CLEVl+MnPAiKh5pl4dEWSyMTpuflgNQiLGhMv8ezD5W/qP8AKvmYpCOKRRNOh7oRKnauBZ4SyeYkMS+1VSyKwQ==} resolution: {integrity: sha512-CLEVl+MnPAiKh5pl4dEWSyMTpuflgNQiLGhMv8ezD5W/qP8AKvmYpCOKRRNOh7oRKnauBZ4SyeYkMS+1VSyKwQ==}
engines: {node: '>=18.0.0', npm: '>=8.0.0'} engines: {node: '>=18.0.0', npm: '>=8.0.0'}
@ -7594,12 +7673,13 @@ packages:
vfile@6.0.3: vfile@6.0.3:
resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==} resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==}
vite@8.0.0-beta.8: vite@8.0.0-beta.14:
resolution: {integrity: sha512-PetN5BNs5dj6NSu1pDrbr0AtbH9KjPhQ/dLePvhLYsYgnZdj6+ihGjtA4DYcR9bASOzOmxN1NqEJEJ4JBUIvpA==} resolution: {integrity: sha512-oLW66oi8tZcoxu6+1HFXb+5hLHco3OnEVu2Awmj5NqEo7vxaqybjBM0BXHcq+jAFhzkMGXJl8xcO5qDBczgKLg==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
hasBin: true hasBin: true
peerDependencies: peerDependencies:
'@types/node': ^20.19.0 || >=22.12.0 '@types/node': ^20.19.0 || >=22.12.0
'@vitejs/devtools': ^0.0.0-alpha.31
esbuild: ^0.27.2 esbuild: ^0.27.2
jiti: '>=1.21.0' jiti: '>=1.21.0'
less: ^4.0.0 less: ^4.0.0
@ -7613,6 +7693,8 @@ packages:
peerDependenciesMeta: peerDependenciesMeta:
'@types/node': '@types/node':
optional: true optional: true
'@vitejs/devtools':
optional: true
esbuild: esbuild:
optional: true optional: true
jiti: jiti:
@ -8897,12 +8979,14 @@ snapshots:
'@opentelemetry/api@1.9.0': '@opentelemetry/api@1.9.0':
optional: true optional: true
'@oxc-project/runtime@0.108.0': {} '@oxc-project/runtime@0.113.0': {}
'@oxc-project/types@0.107.0': {} '@oxc-project/types@0.107.0': {}
'@oxc-project/types@0.108.0': {} '@oxc-project/types@0.108.0': {}
'@oxc-project/types@0.113.0': {}
'@parcel/watcher-android-arm64@2.5.1': '@parcel/watcher-android-arm64@2.5.1':
optional: true optional: true
@ -9076,60 +9160,90 @@ snapshots:
'@rolldown/binding-android-arm64@1.0.0-beta.60': '@rolldown/binding-android-arm64@1.0.0-beta.60':
optional: true optional: true
'@rolldown/binding-android-arm64@1.0.0-rc.4':
optional: true
'@rolldown/binding-darwin-arm64@1.0.0-beta.59': '@rolldown/binding-darwin-arm64@1.0.0-beta.59':
optional: true optional: true
'@rolldown/binding-darwin-arm64@1.0.0-beta.60': '@rolldown/binding-darwin-arm64@1.0.0-beta.60':
optional: true optional: true
'@rolldown/binding-darwin-arm64@1.0.0-rc.4':
optional: true
'@rolldown/binding-darwin-x64@1.0.0-beta.59': '@rolldown/binding-darwin-x64@1.0.0-beta.59':
optional: true optional: true
'@rolldown/binding-darwin-x64@1.0.0-beta.60': '@rolldown/binding-darwin-x64@1.0.0-beta.60':
optional: true optional: true
'@rolldown/binding-darwin-x64@1.0.0-rc.4':
optional: true
'@rolldown/binding-freebsd-x64@1.0.0-beta.59': '@rolldown/binding-freebsd-x64@1.0.0-beta.59':
optional: true optional: true
'@rolldown/binding-freebsd-x64@1.0.0-beta.60': '@rolldown/binding-freebsd-x64@1.0.0-beta.60':
optional: true optional: true
'@rolldown/binding-freebsd-x64@1.0.0-rc.4':
optional: true
'@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.59': '@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.59':
optional: true optional: true
'@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.60': '@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.60':
optional: true optional: true
'@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.4':
optional: true
'@rolldown/binding-linux-arm64-gnu@1.0.0-beta.59': '@rolldown/binding-linux-arm64-gnu@1.0.0-beta.59':
optional: true optional: true
'@rolldown/binding-linux-arm64-gnu@1.0.0-beta.60': '@rolldown/binding-linux-arm64-gnu@1.0.0-beta.60':
optional: true optional: true
'@rolldown/binding-linux-arm64-gnu@1.0.0-rc.4':
optional: true
'@rolldown/binding-linux-arm64-musl@1.0.0-beta.59': '@rolldown/binding-linux-arm64-musl@1.0.0-beta.59':
optional: true optional: true
'@rolldown/binding-linux-arm64-musl@1.0.0-beta.60': '@rolldown/binding-linux-arm64-musl@1.0.0-beta.60':
optional: true optional: true
'@rolldown/binding-linux-arm64-musl@1.0.0-rc.4':
optional: true
'@rolldown/binding-linux-x64-gnu@1.0.0-beta.59': '@rolldown/binding-linux-x64-gnu@1.0.0-beta.59':
optional: true optional: true
'@rolldown/binding-linux-x64-gnu@1.0.0-beta.60': '@rolldown/binding-linux-x64-gnu@1.0.0-beta.60':
optional: true optional: true
'@rolldown/binding-linux-x64-gnu@1.0.0-rc.4':
optional: true
'@rolldown/binding-linux-x64-musl@1.0.0-beta.59': '@rolldown/binding-linux-x64-musl@1.0.0-beta.59':
optional: true optional: true
'@rolldown/binding-linux-x64-musl@1.0.0-beta.60': '@rolldown/binding-linux-x64-musl@1.0.0-beta.60':
optional: true optional: true
'@rolldown/binding-linux-x64-musl@1.0.0-rc.4':
optional: true
'@rolldown/binding-openharmony-arm64@1.0.0-beta.59': '@rolldown/binding-openharmony-arm64@1.0.0-beta.59':
optional: true optional: true
'@rolldown/binding-openharmony-arm64@1.0.0-beta.60': '@rolldown/binding-openharmony-arm64@1.0.0-beta.60':
optional: true optional: true
'@rolldown/binding-openharmony-arm64@1.0.0-rc.4':
optional: true
'@rolldown/binding-wasm32-wasi@1.0.0-beta.59': '@rolldown/binding-wasm32-wasi@1.0.0-beta.59':
dependencies: dependencies:
'@napi-rs/wasm-runtime': 1.1.1 '@napi-rs/wasm-runtime': 1.1.1
@ -9140,24 +9254,37 @@ snapshots:
'@napi-rs/wasm-runtime': 1.1.1 '@napi-rs/wasm-runtime': 1.1.1
optional: true optional: true
'@rolldown/binding-wasm32-wasi@1.0.0-rc.4':
dependencies:
'@napi-rs/wasm-runtime': 1.1.1
optional: true
'@rolldown/binding-win32-arm64-msvc@1.0.0-beta.59': '@rolldown/binding-win32-arm64-msvc@1.0.0-beta.59':
optional: true optional: true
'@rolldown/binding-win32-arm64-msvc@1.0.0-beta.60': '@rolldown/binding-win32-arm64-msvc@1.0.0-beta.60':
optional: true optional: true
'@rolldown/binding-win32-arm64-msvc@1.0.0-rc.4':
optional: true
'@rolldown/binding-win32-x64-msvc@1.0.0-beta.59': '@rolldown/binding-win32-x64-msvc@1.0.0-beta.59':
optional: true optional: true
'@rolldown/binding-win32-x64-msvc@1.0.0-beta.60': '@rolldown/binding-win32-x64-msvc@1.0.0-beta.60':
optional: true optional: true
'@rolldown/binding-win32-x64-msvc@1.0.0-rc.4':
optional: true
'@rolldown/pluginutils@1.0.0-beta.29': {} '@rolldown/pluginutils@1.0.0-beta.29': {}
'@rolldown/pluginutils@1.0.0-beta.59': {} '@rolldown/pluginutils@1.0.0-beta.59': {}
'@rolldown/pluginutils@1.0.0-beta.60': {} '@rolldown/pluginutils@1.0.0-beta.60': {}
'@rolldown/pluginutils@1.0.0-rc.4': {}
'@rollup/rollup-android-arm-eabi@4.52.4': '@rollup/rollup-android-arm-eabi@4.52.4':
optional: true optional: true
@ -9774,10 +9901,10 @@ snapshots:
'@ungap/structured-clone@1.3.0': {} '@ungap/structured-clone@1.3.0': {}
'@vitejs/plugin-vue@6.0.1(vite@8.0.0-beta.8(@types/node@25.0.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(sass-embedded@1.97.2)(sass@1.97.2)(stylus@0.64.0)(yaml@2.8.2))(vue@3.5.27(typescript@5.9.3))': '@vitejs/plugin-vue@6.0.1(vite@8.0.0-beta.14(@types/node@25.0.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(sass-embedded@1.97.2)(sass@1.97.2)(stylus@0.64.0)(yaml@2.8.2))(vue@3.5.27(typescript@5.9.3))':
dependencies: dependencies:
'@rolldown/pluginutils': 1.0.0-beta.29 '@rolldown/pluginutils': 1.0.0-beta.29
vite: 8.0.0-beta.8(@types/node@25.0.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(sass-embedded@1.97.2)(sass@1.97.2)(stylus@0.64.0)(yaml@2.8.2) vite: 8.0.0-beta.14(@types/node@25.0.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(sass-embedded@1.97.2)(sass@1.97.2)(stylus@0.64.0)(yaml@2.8.2)
vue: 3.5.27(typescript@5.9.3) vue: 3.5.27(typescript@5.9.3)
'@vitest/coverage-v8@4.0.17(vitest@4.0.17(@opentelemetry/api@1.9.0)(@types/node@25.0.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(sass-embedded@1.97.2)(sass@1.97.2)(stylus@0.64.0)(yaml@2.8.2))': '@vitest/coverage-v8@4.0.17(vitest@4.0.17(@opentelemetry/api@1.9.0)(@types/node@25.0.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(sass-embedded@1.97.2)(sass@1.97.2)(stylus@0.64.0)(yaml@2.8.2))':
@ -9814,13 +9941,13 @@ snapshots:
chai: 6.2.1 chai: 6.2.1
tinyrainbow: 3.0.3 tinyrainbow: 3.0.3
'@vitest/mocker@4.0.17(vite@8.0.0-beta.8(@types/node@25.0.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(sass-embedded@1.97.2)(sass@1.97.2)(stylus@0.64.0)(yaml@2.8.2))': '@vitest/mocker@4.0.17(vite@8.0.0-beta.14(@types/node@25.0.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(sass-embedded@1.97.2)(sass@1.97.2)(stylus@0.64.0)(yaml@2.8.2))':
dependencies: dependencies:
'@vitest/spy': 4.0.17 '@vitest/spy': 4.0.17
estree-walker: 3.0.3 estree-walker: 3.0.3
magic-string: 0.30.21 magic-string: 0.30.21
optionalDependencies: optionalDependencies:
vite: 8.0.0-beta.8(@types/node@25.0.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(sass-embedded@1.97.2)(sass@1.97.2)(stylus@0.64.0)(yaml@2.8.2) vite: 8.0.0-beta.14(@types/node@25.0.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(sass-embedded@1.97.2)(sass@1.97.2)(stylus@0.64.0)(yaml@2.8.2)
'@vitest/pretty-format@4.0.17': '@vitest/pretty-format@4.0.17':
dependencies: dependencies:
@ -9940,7 +10067,7 @@ snapshots:
'@vuepress/bundler-vite@2.0.0-rc.26(@types/node@25.0.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(sass-embedded@1.97.2)(sass@1.97.2)(stylus@0.64.0)(typescript@5.9.3)(yaml@2.8.2)': '@vuepress/bundler-vite@2.0.0-rc.26(@types/node@25.0.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(sass-embedded@1.97.2)(sass@1.97.2)(stylus@0.64.0)(typescript@5.9.3)(yaml@2.8.2)':
dependencies: dependencies:
'@vitejs/plugin-vue': 6.0.1(vite@8.0.0-beta.8(@types/node@25.0.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(sass-embedded@1.97.2)(sass@1.97.2)(stylus@0.64.0)(yaml@2.8.2))(vue@3.5.27(typescript@5.9.3)) '@vitejs/plugin-vue': 6.0.1(vite@8.0.0-beta.14(@types/node@25.0.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(sass-embedded@1.97.2)(sass@1.97.2)(stylus@0.64.0)(yaml@2.8.2))(vue@3.5.27(typescript@5.9.3))
'@vuepress/bundlerutils': 2.0.0-rc.26(typescript@5.9.3) '@vuepress/bundlerutils': 2.0.0-rc.26(typescript@5.9.3)
'@vuepress/client': 2.0.0-rc.26(typescript@5.9.3) '@vuepress/client': 2.0.0-rc.26(typescript@5.9.3)
'@vuepress/core': 2.0.0-rc.26(typescript@5.9.3) '@vuepress/core': 2.0.0-rc.26(typescript@5.9.3)
@ -9951,11 +10078,12 @@ snapshots:
postcss: 8.5.6 postcss: 8.5.6
postcss-load-config: 6.0.1(jiti@2.6.1)(postcss@8.5.6)(yaml@2.8.2) postcss-load-config: 6.0.1(jiti@2.6.1)(postcss@8.5.6)(yaml@2.8.2)
rollup: 4.52.4 rollup: 4.52.4
vite: 8.0.0-beta.8(@types/node@25.0.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(sass-embedded@1.97.2)(sass@1.97.2)(stylus@0.64.0)(yaml@2.8.2) vite: 8.0.0-beta.14(@types/node@25.0.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(sass-embedded@1.97.2)(sass@1.97.2)(stylus@0.64.0)(yaml@2.8.2)
vue: 3.5.27(typescript@5.9.3) vue: 3.5.27(typescript@5.9.3)
vue-router: 4.6.4(vue@3.5.27(typescript@5.9.3)) vue-router: 4.6.4(vue@3.5.27(typescript@5.9.3))
transitivePeerDependencies: transitivePeerDependencies:
- '@types/node' - '@types/node'
- '@vitejs/devtools'
- esbuild - esbuild
- jiti - jiti
- less - less
@ -10027,12 +10155,12 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- typescript - typescript
'@vuepress/highlighter-helper@2.0.0-rc.122(@vuepress/helper@2.0.0-rc.122(typescript@5.9.3)(vuepress@2.0.0-rc.26(@vuepress/bundler-vite@2.0.0-rc.26(@types/node@25.0.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(sass-embedded@1.97.2)(sass@1.97.2)(stylus@0.64.0)(typescript@5.9.3)(yaml@2.8.2))(typescript@5.9.3)(vue@3.5.27(typescript@5.9.3))))(@vueuse/core@14.1.0(vue@3.5.27(typescript@5.9.3)))(vuepress@2.0.0-rc.26(@vuepress/bundler-vite@2.0.0-rc.26(@types/node@25.0.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(sass-embedded@1.97.2)(sass@1.97.2)(stylus@0.64.0)(typescript@5.9.3)(yaml@2.8.2))(typescript@5.9.3)(vue@3.5.27(typescript@5.9.3)))': '@vuepress/highlighter-helper@2.0.0-rc.122(@vuepress/helper@2.0.0-rc.122(typescript@5.9.3)(vuepress@2.0.0-rc.26(@vuepress/bundler-vite@2.0.0-rc.26(@types/node@25.0.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(sass-embedded@1.97.2)(sass@1.97.2)(stylus@0.64.0)(typescript@5.9.3)(yaml@2.8.2))(typescript@5.9.3)(vue@3.5.27(typescript@5.9.3))))(@vueuse/core@14.2.1(vue@3.5.27(typescript@5.9.3)))(vuepress@2.0.0-rc.26(@vuepress/bundler-vite@2.0.0-rc.26(@types/node@25.0.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(sass-embedded@1.97.2)(sass@1.97.2)(stylus@0.64.0)(typescript@5.9.3)(yaml@2.8.2))(typescript@5.9.3)(vue@3.5.27(typescript@5.9.3)))':
dependencies: dependencies:
'@vuepress/helper': 2.0.0-rc.122(typescript@5.9.3)(vuepress@2.0.0-rc.26(@vuepress/bundler-vite@2.0.0-rc.26(@types/node@25.0.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(sass-embedded@1.97.2)(sass@1.97.2)(stylus@0.64.0)(typescript@5.9.3)(yaml@2.8.2))(typescript@5.9.3)(vue@3.5.27(typescript@5.9.3))) '@vuepress/helper': 2.0.0-rc.122(typescript@5.9.3)(vuepress@2.0.0-rc.26(@vuepress/bundler-vite@2.0.0-rc.26(@types/node@25.0.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(sass-embedded@1.97.2)(sass@1.97.2)(stylus@0.64.0)(typescript@5.9.3)(yaml@2.8.2))(typescript@5.9.3)(vue@3.5.27(typescript@5.9.3)))
vuepress: 2.0.0-rc.26(@vuepress/bundler-vite@2.0.0-rc.26(@types/node@25.0.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(sass-embedded@1.97.2)(sass@1.97.2)(stylus@0.64.0)(typescript@5.9.3)(yaml@2.8.2))(typescript@5.9.3)(vue@3.5.27(typescript@5.9.3)) vuepress: 2.0.0-rc.26(@vuepress/bundler-vite@2.0.0-rc.26(@types/node@25.0.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(sass-embedded@1.97.2)(sass@1.97.2)(stylus@0.64.0)(typescript@5.9.3)(yaml@2.8.2))(typescript@5.9.3)(vue@3.5.27(typescript@5.9.3))
optionalDependencies: optionalDependencies:
'@vueuse/core': 14.1.0(vue@3.5.27(typescript@5.9.3)) '@vueuse/core': 14.2.1(vue@3.5.27(typescript@5.9.3))
'@vuepress/markdown@2.0.0-rc.26': '@vuepress/markdown@2.0.0-rc.26':
dependencies: dependencies:
@ -10243,11 +10371,11 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- typescript - typescript
'@vuepress/plugin-shiki@2.0.0-rc.122(@vuepress/shiki-twoslash@2.0.0-rc.122(typescript@5.9.3)(vue@3.5.27(typescript@5.9.3))(vuepress@2.0.0-rc.26(@vuepress/bundler-vite@2.0.0-rc.26(@types/node@25.0.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(sass-embedded@1.97.2)(sass@1.97.2)(stylus@0.64.0)(typescript@5.9.3)(yaml@2.8.2))(typescript@5.9.3)(vue@3.5.27(typescript@5.9.3))))(@vueuse/core@14.1.0(vue@3.5.27(typescript@5.9.3)))(typescript@5.9.3)(vuepress@2.0.0-rc.26(@vuepress/bundler-vite@2.0.0-rc.26(@types/node@25.0.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(sass-embedded@1.97.2)(sass@1.97.2)(stylus@0.64.0)(typescript@5.9.3)(yaml@2.8.2))(typescript@5.9.3)(vue@3.5.27(typescript@5.9.3)))': '@vuepress/plugin-shiki@2.0.0-rc.122(@vuepress/shiki-twoslash@2.0.0-rc.122(typescript@5.9.3)(vue@3.5.27(typescript@5.9.3))(vuepress@2.0.0-rc.26(@vuepress/bundler-vite@2.0.0-rc.26(@types/node@25.0.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(sass-embedded@1.97.2)(sass@1.97.2)(stylus@0.64.0)(typescript@5.9.3)(yaml@2.8.2))(typescript@5.9.3)(vue@3.5.27(typescript@5.9.3))))(@vueuse/core@14.2.1(vue@3.5.27(typescript@5.9.3)))(typescript@5.9.3)(vuepress@2.0.0-rc.26(@vuepress/bundler-vite@2.0.0-rc.26(@types/node@25.0.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(sass-embedded@1.97.2)(sass@1.97.2)(stylus@0.64.0)(typescript@5.9.3)(yaml@2.8.2))(typescript@5.9.3)(vue@3.5.27(typescript@5.9.3)))':
dependencies: dependencies:
'@shikijs/transformers': 3.22.0 '@shikijs/transformers': 3.22.0
'@vuepress/helper': 2.0.0-rc.122(typescript@5.9.3)(vuepress@2.0.0-rc.26(@vuepress/bundler-vite@2.0.0-rc.26(@types/node@25.0.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(sass-embedded@1.97.2)(sass@1.97.2)(stylus@0.64.0)(typescript@5.9.3)(yaml@2.8.2))(typescript@5.9.3)(vue@3.5.27(typescript@5.9.3))) '@vuepress/helper': 2.0.0-rc.122(typescript@5.9.3)(vuepress@2.0.0-rc.26(@vuepress/bundler-vite@2.0.0-rc.26(@types/node@25.0.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(sass-embedded@1.97.2)(sass@1.97.2)(stylus@0.64.0)(typescript@5.9.3)(yaml@2.8.2))(typescript@5.9.3)(vue@3.5.27(typescript@5.9.3)))
'@vuepress/highlighter-helper': 2.0.0-rc.122(@vuepress/helper@2.0.0-rc.122(typescript@5.9.3)(vuepress@2.0.0-rc.26(@vuepress/bundler-vite@2.0.0-rc.26(@types/node@25.0.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(sass-embedded@1.97.2)(sass@1.97.2)(stylus@0.64.0)(typescript@5.9.3)(yaml@2.8.2))(typescript@5.9.3)(vue@3.5.27(typescript@5.9.3))))(@vueuse/core@14.1.0(vue@3.5.27(typescript@5.9.3)))(vuepress@2.0.0-rc.26(@vuepress/bundler-vite@2.0.0-rc.26(@types/node@25.0.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(sass-embedded@1.97.2)(sass@1.97.2)(stylus@0.64.0)(typescript@5.9.3)(yaml@2.8.2))(typescript@5.9.3)(vue@3.5.27(typescript@5.9.3))) '@vuepress/highlighter-helper': 2.0.0-rc.122(@vuepress/helper@2.0.0-rc.122(typescript@5.9.3)(vuepress@2.0.0-rc.26(@vuepress/bundler-vite@2.0.0-rc.26(@types/node@25.0.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(sass-embedded@1.97.2)(sass@1.97.2)(stylus@0.64.0)(typescript@5.9.3)(yaml@2.8.2))(typescript@5.9.3)(vue@3.5.27(typescript@5.9.3))))(@vueuse/core@14.2.1(vue@3.5.27(typescript@5.9.3)))(vuepress@2.0.0-rc.26(@vuepress/bundler-vite@2.0.0-rc.26(@types/node@25.0.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(sass-embedded@1.97.2)(sass@1.97.2)(stylus@0.64.0)(typescript@5.9.3)(yaml@2.8.2))(typescript@5.9.3)(vue@3.5.27(typescript@5.9.3)))
nanoid: 5.1.6 nanoid: 5.1.6
shiki: 3.22.0 shiki: 3.22.0
synckit: 0.11.12 synckit: 0.11.12
@ -10315,13 +10443,6 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@vueuse/core@14.1.0(vue@3.5.27(typescript@5.9.3))':
dependencies:
'@types/web-bluetooth': 0.0.21
'@vueuse/metadata': 14.1.0
'@vueuse/shared': 14.1.0(vue@3.5.27(typescript@5.9.3))
vue: 3.5.27(typescript@5.9.3)
'@vueuse/core@14.2.1(vue@3.5.27(typescript@5.9.3))': '@vueuse/core@14.2.1(vue@3.5.27(typescript@5.9.3))':
dependencies: dependencies:
'@types/web-bluetooth': 0.0.21 '@types/web-bluetooth': 0.0.21
@ -10329,10 +10450,10 @@ snapshots:
'@vueuse/shared': 14.2.1(vue@3.5.27(typescript@5.9.3)) '@vueuse/shared': 14.2.1(vue@3.5.27(typescript@5.9.3))
vue: 3.5.27(typescript@5.9.3) vue: 3.5.27(typescript@5.9.3)
'@vueuse/integrations@14.1.0(axios@1.13.2)(change-case@5.4.4)(focus-trap@7.8.0)(qrcode@1.5.4)(vue@3.5.27(typescript@5.9.3))': '@vueuse/integrations@14.2.1(axios@1.13.2)(change-case@5.4.4)(focus-trap@7.8.0)(qrcode@1.5.4)(vue@3.5.27(typescript@5.9.3))':
dependencies: dependencies:
'@vueuse/core': 14.1.0(vue@3.5.27(typescript@5.9.3)) '@vueuse/core': 14.2.1(vue@3.5.27(typescript@5.9.3))
'@vueuse/shared': 14.1.0(vue@3.5.27(typescript@5.9.3)) '@vueuse/shared': 14.2.1(vue@3.5.27(typescript@5.9.3))
vue: 3.5.27(typescript@5.9.3) vue: 3.5.27(typescript@5.9.3)
optionalDependencies: optionalDependencies:
axios: 1.13.2 axios: 1.13.2
@ -10340,14 +10461,8 @@ snapshots:
focus-trap: 7.8.0 focus-trap: 7.8.0
qrcode: 1.5.4 qrcode: 1.5.4
'@vueuse/metadata@14.1.0': {}
'@vueuse/metadata@14.2.1': {} '@vueuse/metadata@14.2.1': {}
'@vueuse/shared@14.1.0(vue@3.5.27(typescript@5.9.3))':
dependencies:
vue: 3.5.27(typescript@5.9.3)
'@vueuse/shared@14.2.1(vue@3.5.27(typescript@5.9.3))': '@vueuse/shared@14.2.1(vue@3.5.27(typescript@5.9.3))':
dependencies: dependencies:
vue: 3.5.27(typescript@5.9.3) vue: 3.5.27(typescript@5.9.3)
@ -12931,54 +13046,54 @@ snapshots:
dependencies: dependencies:
immediate: 3.0.6 immediate: 3.0.6
lightningcss-android-arm64@1.30.2: lightningcss-android-arm64@1.31.1:
optional: true optional: true
lightningcss-darwin-arm64@1.30.2: lightningcss-darwin-arm64@1.31.1:
optional: true optional: true
lightningcss-darwin-x64@1.30.2: lightningcss-darwin-x64@1.31.1:
optional: true optional: true
lightningcss-freebsd-x64@1.30.2: lightningcss-freebsd-x64@1.31.1:
optional: true optional: true
lightningcss-linux-arm-gnueabihf@1.30.2: lightningcss-linux-arm-gnueabihf@1.31.1:
optional: true optional: true
lightningcss-linux-arm64-gnu@1.30.2: lightningcss-linux-arm64-gnu@1.31.1:
optional: true optional: true
lightningcss-linux-arm64-musl@1.30.2: lightningcss-linux-arm64-musl@1.31.1:
optional: true optional: true
lightningcss-linux-x64-gnu@1.30.2: lightningcss-linux-x64-gnu@1.31.1:
optional: true optional: true
lightningcss-linux-x64-musl@1.30.2: lightningcss-linux-x64-musl@1.31.1:
optional: true optional: true
lightningcss-win32-arm64-msvc@1.30.2: lightningcss-win32-arm64-msvc@1.31.1:
optional: true optional: true
lightningcss-win32-x64-msvc@1.30.2: lightningcss-win32-x64-msvc@1.31.1:
optional: true optional: true
lightningcss@1.30.2: lightningcss@1.31.1:
dependencies: dependencies:
detect-libc: 2.1.2 detect-libc: 2.1.2
optionalDependencies: optionalDependencies:
lightningcss-android-arm64: 1.30.2 lightningcss-android-arm64: 1.31.1
lightningcss-darwin-arm64: 1.30.2 lightningcss-darwin-arm64: 1.31.1
lightningcss-darwin-x64: 1.30.2 lightningcss-darwin-x64: 1.31.1
lightningcss-freebsd-x64: 1.30.2 lightningcss-freebsd-x64: 1.31.1
lightningcss-linux-arm-gnueabihf: 1.30.2 lightningcss-linux-arm-gnueabihf: 1.31.1
lightningcss-linux-arm64-gnu: 1.30.2 lightningcss-linux-arm64-gnu: 1.31.1
lightningcss-linux-arm64-musl: 1.30.2 lightningcss-linux-arm64-musl: 1.31.1
lightningcss-linux-x64-gnu: 1.30.2 lightningcss-linux-x64-gnu: 1.31.1
lightningcss-linux-x64-musl: 1.30.2 lightningcss-linux-x64-musl: 1.31.1
lightningcss-win32-arm64-msvc: 1.30.2 lightningcss-win32-arm64-msvc: 1.31.1
lightningcss-win32-x64-msvc: 1.30.2 lightningcss-win32-x64-msvc: 1.31.1
lilconfig@3.1.3: {} lilconfig@3.1.3: {}
@ -14310,6 +14425,25 @@ snapshots:
'@rolldown/binding-win32-arm64-msvc': 1.0.0-beta.60 '@rolldown/binding-win32-arm64-msvc': 1.0.0-beta.60
'@rolldown/binding-win32-x64-msvc': 1.0.0-beta.60 '@rolldown/binding-win32-x64-msvc': 1.0.0-beta.60
rolldown@1.0.0-rc.4:
dependencies:
'@oxc-project/types': 0.113.0
'@rolldown/pluginutils': 1.0.0-rc.4
optionalDependencies:
'@rolldown/binding-android-arm64': 1.0.0-rc.4
'@rolldown/binding-darwin-arm64': 1.0.0-rc.4
'@rolldown/binding-darwin-x64': 1.0.0-rc.4
'@rolldown/binding-freebsd-x64': 1.0.0-rc.4
'@rolldown/binding-linux-arm-gnueabihf': 1.0.0-rc.4
'@rolldown/binding-linux-arm64-gnu': 1.0.0-rc.4
'@rolldown/binding-linux-arm64-musl': 1.0.0-rc.4
'@rolldown/binding-linux-x64-gnu': 1.0.0-rc.4
'@rolldown/binding-linux-x64-musl': 1.0.0-rc.4
'@rolldown/binding-openharmony-arm64': 1.0.0-rc.4
'@rolldown/binding-wasm32-wasi': 1.0.0-rc.4
'@rolldown/binding-win32-arm64-msvc': 1.0.0-rc.4
'@rolldown/binding-win32-x64-msvc': 1.0.0-rc.4
rollup@4.52.4: rollup@4.52.4:
dependencies: dependencies:
'@types/estree': 1.0.8 '@types/estree': 1.0.8
@ -15248,14 +15382,14 @@ snapshots:
'@types/unist': 3.0.3 '@types/unist': 3.0.3
vfile-message: 4.0.3 vfile-message: 4.0.3
vite@8.0.0-beta.8(@types/node@25.0.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(sass-embedded@1.97.2)(sass@1.97.2)(stylus@0.64.0)(yaml@2.8.2): vite@8.0.0-beta.14(@types/node@25.0.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(sass-embedded@1.97.2)(sass@1.97.2)(stylus@0.64.0)(yaml@2.8.2):
dependencies: dependencies:
'@oxc-project/runtime': 0.108.0 '@oxc-project/runtime': 0.113.0
fdir: 6.5.0(picomatch@4.0.3) fdir: 6.5.0(picomatch@4.0.3)
lightningcss: 1.30.2 lightningcss: 1.31.1
picomatch: 4.0.3 picomatch: 4.0.3
postcss: 8.5.6 postcss: 8.5.6
rolldown: 1.0.0-beta.60 rolldown: 1.0.0-rc.4
tinyglobby: 0.2.15 tinyglobby: 0.2.15
optionalDependencies: optionalDependencies:
'@types/node': 25.0.9 '@types/node': 25.0.9
@ -15271,7 +15405,7 @@ snapshots:
vitest@4.0.17(@opentelemetry/api@1.9.0)(@types/node@25.0.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(sass-embedded@1.97.2)(sass@1.97.2)(stylus@0.64.0)(yaml@2.8.2): vitest@4.0.17(@opentelemetry/api@1.9.0)(@types/node@25.0.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(sass-embedded@1.97.2)(sass@1.97.2)(stylus@0.64.0)(yaml@2.8.2):
dependencies: dependencies:
'@vitest/expect': 4.0.17 '@vitest/expect': 4.0.17
'@vitest/mocker': 4.0.17(vite@8.0.0-beta.8(@types/node@25.0.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(sass-embedded@1.97.2)(sass@1.97.2)(stylus@0.64.0)(yaml@2.8.2)) '@vitest/mocker': 4.0.17(vite@8.0.0-beta.14(@types/node@25.0.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(sass-embedded@1.97.2)(sass@1.97.2)(stylus@0.64.0)(yaml@2.8.2))
'@vitest/pretty-format': 4.0.17 '@vitest/pretty-format': 4.0.17
'@vitest/runner': 4.0.17 '@vitest/runner': 4.0.17
'@vitest/snapshot': 4.0.17 '@vitest/snapshot': 4.0.17
@ -15288,12 +15422,13 @@ snapshots:
tinyexec: 1.0.2 tinyexec: 1.0.2
tinyglobby: 0.2.15 tinyglobby: 0.2.15
tinyrainbow: 3.0.3 tinyrainbow: 3.0.3
vite: 8.0.0-beta.8(@types/node@25.0.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(sass-embedded@1.97.2)(sass@1.97.2)(stylus@0.64.0)(yaml@2.8.2) vite: 8.0.0-beta.14(@types/node@25.0.9)(esbuild@0.27.2)(jiti@2.6.1)(less@4.5.1)(sass-embedded@1.97.2)(sass@1.97.2)(stylus@0.64.0)(yaml@2.8.2)
why-is-node-running: 2.3.0 why-is-node-running: 2.3.0
optionalDependencies: optionalDependencies:
'@opentelemetry/api': 1.9.0 '@opentelemetry/api': 1.9.0
'@types/node': 25.0.9 '@types/node': 25.0.9
transitivePeerDependencies: transitivePeerDependencies:
- '@vitejs/devtools'
- esbuild - esbuild
- jiti - jiti
- less - less

View File

@ -61,7 +61,7 @@ catalogs:
tsconfig-vuepress: ^7.0.0 tsconfig-vuepress: ^7.0.0
tsdown: ^0.19.0 tsdown: ^0.19.0
typescript: ^5.9.3 typescript: ^5.9.3
vite: ^8.0.0-beta.8 vite: ^8.0.0-beta.10
vitest: ^4.0.17 vitest: ^4.0.17
vue-router: ^4.6.4 vue-router: ^4.6.4
wait-on: ^9.0.3 wait-on: ^9.0.3
@ -97,8 +97,8 @@ catalogs:
'@mdit/plugin-tab': ^0.23.0 '@mdit/plugin-tab': ^0.23.0
'@mdit/plugin-tasklist': ^0.22.2 '@mdit/plugin-tasklist': ^0.22.2
'@pengzhanbo/utils': ^3.1.0 '@pengzhanbo/utils': ^3.1.0
'@vueuse/core': ^14.1.0 '@vueuse/core': ^14.2.0
'@vueuse/integrations': ^14.1.0 '@vueuse/integrations': ^14.2.0
cac: ^6.7.14 cac: ^6.7.14
chart.js: ^4.5.1 chart.js: ^4.5.1
chokidar: 5.0.0 chokidar: 5.0.0

View File

@ -61,6 +61,7 @@ let defaultTheme: string | undefined
watch(() => props.forceDark, () => { watch(() => props.forceDark, () => {
if (!inBrowser || __VUEPRESS_SSR__) if (!inBrowser || __VUEPRESS_SSR__)
return return
if (props.forceDark) { if (props.forceDark) {
defaultTheme ??= document.documentElement.dataset.theme defaultTheme ??= document.documentElement.dataset.theme
document.documentElement.dataset.theme = 'dark' document.documentElement.dataset.theme = 'dark'
@ -69,7 +70,7 @@ watch(() => props.forceDark, () => {
noTransition() noTransition()
} }
document.documentElement.classList.add(`effect-${effect.value}`) document.documentElement.classList.add(`effect-${effect.value}`)
}, { immediate: true }) }, { immediate: true, flush: 'post' })
onMounted(() => { onMounted(() => {
if (props.forceDark) { if (props.forceDark) {
@ -273,7 +274,9 @@ html.no-transition *::after {
animation-iteration-count: 1 !important; animation-iteration-count: 1 !important;
} }
html[class*="effect-"].force-dark .vp-navbar-appearance { html[class*="effect-"].force-dark .vp-navbar-appearance,
html[class*="effect-"].force-dark .vp-navbar-extra .group.appearance,
html[class*="effect-"].force-dark .vp-nav-screen .vp-nav-screen-appearance {
display: none; display: none;
} }

View File

@ -50,7 +50,7 @@ const hasExtraContent = computed(
</template> </template>
</div> </div>
<div v-if="theme.appearance && theme.appearance !== 'force-dark'" class="group"> <div v-if="theme.appearance && theme.appearance !== 'force-dark'" class="group appearance">
<div class="item appearance"> <div class="item appearance">
<p class="label"> <p class="label">
{{ theme.appearanceText || 'Appearance' }} {{ theme.appearanceText || 'Appearance' }}
@ -61,7 +61,7 @@ const hasExtraContent = computed(
</div> </div>
</div> </div>
<div v-if="social" class="group"> <div v-if="social" class="group social">
<div class="item social-links"> <div class="item social-links">
<VPSocialLinks class="social-links-list" :links="social" /> <VPSocialLinks class="social-links-list" :links="social" />
</div> </div>

View File

@ -4,11 +4,10 @@ import { decodeData } from '@vuepress/helper/client'
import { ref } from 'vue' import { ref } from 'vue'
export type EncryptConfig = readonly [ export type EncryptConfig = readonly [
boolean, // global keys: string, // keys
string, // separator rules: string, // rules
string, // admin global: number, // global
string[], // keys admin: string, // admin
Record<string, string>, // rules
] ]
export interface EncryptDataRule { export interface EncryptDataRule {
@ -19,7 +18,6 @@ export interface EncryptDataRule {
export interface EncryptData { export interface EncryptData {
global: boolean global: boolean
separator: string
admins: string[] admins: string[]
matches: string[] matches: string[]
ruleList: EncryptDataRule[] ruleList: EncryptDataRule[]
@ -34,22 +32,27 @@ export function useEncryptData(): EncryptRef {
} }
function resolveEncryptData( function resolveEncryptData(
[global, separator, admin, matches, rules]: EncryptConfig, [rawKeys, rawRules, global, admin]: EncryptConfig,
): EncryptData { ): EncryptData {
const keys = matches.map(match => decodeData(match)) const keys = unwrapData<string[]>(rawKeys).map(key => decodeData(key))
const rules = unwrapData<Record<string, string>>(rawRules)
const separator = ':'
return { return {
global, global: !!global,
separator,
matches: keys, matches: keys,
admins: admin.split(separator), admins: admin.split(separator),
ruleList: Object.keys(rules).map(key => ({ ruleList: Object.keys(rules).map(key => ({
key, key,
match: keys[key] as string, match: keys[key],
rules: rules[key].split(separator), rules: rules[key].split(separator),
})), })),
} }
} }
function unwrapData<T>(raw: string): T {
return JSON.parse(decodeData(raw)) as T
}
if (__VUEPRESS_DEV__ && (import.meta.webpackHot || import.meta.hot)) { if (__VUEPRESS_DEV__ && (import.meta.webpackHot || import.meta.hot)) {
__VUE_HMR_RUNTIME__.updateEncrypt = (data: EncryptConfig) => { __VUE_HMR_RUNTIME__.updateEncrypt = (data: EncryptConfig) => {
encrypt.value = resolveEncryptData(data) encrypt.value = resolveEncryptData(data)

View File

@ -30,7 +30,8 @@ const storage = useSessionStorage('2a0a3d6afb2fdf1f', () => {
}) })
const compareCache = new Map<string, boolean>() const compareCache = new Map<string, boolean>()
async function compareDecrypt(content: string, hash: string, separator = ':'): Promise<boolean> { const separator = ':'
async function compareDecrypt(content: string, hash: string): Promise<boolean> {
const key = [content, hash].join(separator) const key = [content, hash].join(separator)
if (compareCache.has(key)) if (compareCache.has(key))
return compareCache.get(key)! return compareCache.get(key)!
@ -164,7 +165,7 @@ export function useEncryptCompare(): {
return false return false
for (const admin of encrypt.value.admins) { for (const admin of encrypt.value.admins) {
if (await compareDecrypt(password, admin, encrypt.value.separator)) { if (await compareDecrypt(password, admin)) {
storage.value.g = await md5(admin) storage.value.g = await md5(admin)
return true return true
} }
@ -185,7 +186,7 @@ export function useEncryptCompare(): {
for (const { match, key, rules } of hashList.value) { for (const { match, key, rules } of hashList.value) {
if (toMatch(match, pagePath, filePathRelative)) { if (toMatch(match, pagePath, filePathRelative)) {
for (const rule of rules) { for (const rule of rules) {
if (await compareDecrypt(password, rule, encrypt.value.separator)) { if (await compareDecrypt(password, rule)) {
decrypted = true decrypted = true
storage.value.p[key] = await md5(rule) storage.value.p[key] = await md5(rule)
break break

View File

@ -61,11 +61,10 @@ declare module '@internal/sidebar' {
declare module '@internal/encrypt' { declare module '@internal/encrypt' {
const encrypt: readonly [ const encrypt: readonly [
boolean, // global keys: string,
string, // separator rules: string,
string, // admin global: number,
string[], // keys admin: string,
Record<string, string>, // rules
] ]
export { export {

View File

@ -66,6 +66,8 @@ export const MARKDOWN_POWER_FIELDS: (keyof MarkdownPowerPluginOptions)[] = [
'chat', 'chat',
'youtube', 'youtube',
'qrcode', 'qrcode',
'encrypt',
'locales',
] ]
export const MARKDOWN_SUPPORT_FIELDS: (keyof MarkdownOptions)[] = [ export const MARKDOWN_SUPPORT_FIELDS: (keyof MarkdownOptions)[] = [

View File

@ -15,7 +15,6 @@ import { zhTwLocale, zhTwPresetLocale } from './zh-tw.js'
import { zhLocale, zhPresetLocale } from './zh.js' import { zhLocale, zhPresetLocale } from './zh.js'
export const LOCALE_OPTIONS: DefaultLocaleInfo<ThemeLocaleText> = [ export const LOCALE_OPTIONS: DefaultLocaleInfo<ThemeLocaleText> = [
[['ko', 'ko-KR'], koLocale],
[['en', 'en-US'], enLocale], [['en', 'en-US'], enLocale],
[['zh', 'zh-CN', 'zh-Hans', 'zh-Hant'], zhLocale], [['zh', 'zh-CN', 'zh-Hans', 'zh-Hant'], zhLocale],
[['zh-TW'], zhTwLocale], [['zh-TW'], zhTwLocale],
@ -23,10 +22,10 @@ export const LOCALE_OPTIONS: DefaultLocaleInfo<ThemeLocaleText> = [
[['fr', 'fr-FR'], frLocale], [['fr', 'fr-FR'], frLocale],
[['ru', 'ru-RU'], ruLocale], [['ru', 'ru-RU'], ruLocale],
[['ja', 'ja-JP'], jaLocale], [['ja', 'ja-JP'], jaLocale],
[['ko', 'ko-KR'], koLocale],
] ]
export const PRESET_LOCALES: DefaultLocaleInfo<PresetLocale> = [ export const PRESET_LOCALES: DefaultLocaleInfo<PresetLocale> = [
[['ko', 'ko-KR'], koPresetLocale],
[['en', 'en-US'], enPresetLocale], [['en', 'en-US'], enPresetLocale],
[['zh', 'zh-CN', 'zh-Hans', 'zh-Hant'], zhPresetLocale], [['zh', 'zh-CN', 'zh-Hans', 'zh-Hant'], zhPresetLocale],
[['zh-TW'], zhTwPresetLocale], [['zh-TW'], zhTwPresetLocale],
@ -34,4 +33,5 @@ export const PRESET_LOCALES: DefaultLocaleInfo<PresetLocale> = [
[['fr', 'fr-FR'], frPresetLocale], [['fr', 'fr-FR'], frPresetLocale],
[['ru', 'ru-RU'], ruPresetLocale], [['ru', 'ru-RU'], ruPresetLocale],
[['ja', 'ja-JP'], jaPresetLocale], [['ja', 'ja-JP'], jaPresetLocale],
[['ko', 'ko-KR'], koPresetLocale],
] ]

View File

@ -5,13 +5,17 @@ import { generateTOCLink as rawGenerateTOCLink, llmsPlugin as rawLlmsPlugin } fr
import { ensureEndingSlash, ensureLeadingSlash, isPlainObject } from 'vuepress/shared' import { ensureEndingSlash, ensureLeadingSlash, isPlainObject } from 'vuepress/shared'
import { getThemeConfig } from '../loadConfig/index.js' import { getThemeConfig } from '../loadConfig/index.js'
import { isEncryptPage } from '../prepare/prepareEncrypt.js' import { isEncryptPage } from '../prepare/prepareEncrypt.js'
import { withBase } from '../utils/index.js' import { hash, withBase } from '../utils/index.js'
const CODE_BLOCK_RE = /(?:^|\n)(?<marker>\s*`{3,})([\s\w])[\s\S]*?\n\k<marker>(?:\n|$)/g
const ENCRYPT_CONTAINER_RE = /(?:^|\n)(?<marker>\s*:{3,})\s*encrypt\b[\s\S]*?\n\k<marker>(?:\n|$)/g
const RESTORE_RE = /<!-- llms-code-block:(\w+) -->/g
export function llmsPlugin(app: App, userOptions: true | LlmsPluginOptions): PluginConfig { export function llmsPlugin(app: App, userOptions: true | LlmsPluginOptions): PluginConfig {
if (!app.env.isBuild) if (!app.env.isBuild)
return [] return []
const { llmsTxtTemplateGetter, ...userLLMsTxt } = isPlainObject(userOptions) ? userOptions : {} const { llmsTxtTemplateGetter, transformMarkdown, ...userLLMsTxt } = isPlainObject(userOptions) ? userOptions : {}
function tocGetter(llmPages: LLMPage[], llmState: LLMState): string { function tocGetter(llmPages: LLMPage[], llmState: LLMState): string {
const options = getThemeConfig() const options = getThemeConfig()
@ -126,6 +130,21 @@ export function llmsPlugin(app: App, userOptions: true | LlmsPluginOptions): Plu
}, },
locale: '/', locale: '/',
...userLLMsTxt, ...userLLMsTxt,
transformMarkdown(markdown, page) {
// { hash: content }
let rematches: Record<string, string> = {}
markdown = markdown.replaceAll(CODE_BLOCK_RE, (content) => {
const contentHash = hash(content)
rematches[contentHash] = content
return `<!-- llms-code-block:${contentHash} -->`
})
markdown = markdown.replaceAll(ENCRYPT_CONTAINER_RE, '')
markdown = markdown.replaceAll(RESTORE_RE, (_, hash) => {
return rematches[hash] || ''
})
rematches = {}
return transformMarkdown?.(markdown, page) ?? markdown
},
llmsTxtTemplateGetter: { llmsTxtTemplateGetter: {
toc: tocGetter, toc: tocGetter,
...llmsTxtTemplateGetter, ...llmsTxtTemplateGetter,

View File

@ -9,11 +9,10 @@ import { getThemeConfig } from '../loadConfig/index.js'
import { createFsCache, genEncrypt, hash, perf, resolveContent, writeTemp } from '../utils/index.js' import { createFsCache, genEncrypt, hash, perf, resolveContent, writeTemp } from '../utils/index.js'
export type EncryptConfig = readonly [ export type EncryptConfig = readonly [
boolean, // global keys: string, // keys
string, // separator rules: string, // rules
string, // admin global: number, // global
string[], // keys admin: string, // admin
Record<string, string>, // rules
] ]
const isStringLike = (value: unknown): boolean => isString(value) || isNumber(value) const isStringLike = (value: unknown): boolean => isString(value) || isNumber(value)
@ -73,7 +72,12 @@ async function resolveEncrypt(encrypt?: EncryptOptions): Promise<EncryptConfig>
} }
} }
return [encrypt?.global ?? false, separator, admin, keys, rules] return [
encodeData(JSON.stringify(keys)), // keys
encodeData(JSON.stringify(rules)), // rules
encrypt?.global ? 1 : 0, // global
admin, // admin
]
} }
export function isEncryptPage(page: Page<ThemePageData>, encrypt?: EncryptOptions): boolean { export function isEncryptPage(page: Page<ThemePageData>, encrypt?: EncryptOptions): boolean {

View File

@ -50,8 +50,8 @@ export default defineConfig((cli) => {
...DEFAULT_OPTIONS, ...DEFAULT_OPTIONS,
entry: ['./src/node/index.ts'], entry: ['./src/node/index.ts'],
outDir: './lib/node', outDir: './lib/node',
external: sharedExternal, external: [...sharedExternal, '@pinyin-pro/data/complete'],
target: 'node20.6.0', target: 'node20.19.0',
watch: false, watch: false,
}) })
} }

View File

@ -4,7 +4,6 @@
"jsx": "preserve", "jsx": "preserve",
"baseUrl": ".", "baseUrl": ".",
"paths": { "paths": {
"@internal/md-power/replEditorData": ["./plugins/plugin-md-power/src/client/shim.d.ts"],
"@internal/*": ["./docs/.vuepress/.temp/internal/*"], "@internal/*": ["./docs/.vuepress/.temp/internal/*"],
"@theme/*": ["./theme/src/client/components/*"] "@theme/*": ["./theme/src/client/components/*"]
}, },