diff --git a/docs/.vuepress/theme.ts b/docs/.vuepress/theme.ts index 008299b3..5753c251 100644 --- a/docs/.vuepress/theme.ts +++ b/docs/.vuepress/theme.ts @@ -57,6 +57,7 @@ export const theme: Theme = plumeTheme({ codeSandbox: true, jsfiddle: true, demo: true, + encrypt: true, npmTo: ['pnpm', 'yarn', 'npm'], repl: { go: true, diff --git a/docs/en/guide/features/encryption.md b/docs/en/guide/features/encryption.md index e352ab9d..8679699a 100644 --- a/docs/en/guide/features/encryption.md +++ b/docs/en/guide/features/encryption.md @@ -7,19 +7,18 @@ permalink: /en/guide/features/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 -Due to the inherent limitations of `vuepress` as a static site generator, -the **encryption** only makes content *appear* invisible and excludes the content from being pre-rendered -into `html` during compilation. However, the content can still be accessed from the site's source files. - -Therefore, the **encryption** feature should not be considered **secure and reliable**. +Due to the limitations of `vuepress` as a static site, **encryption** only makes the content *appear* invisible. +During compilation, the content is not pre-rendered into the `html`, +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. 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 @@ -40,8 +39,8 @@ export default defineUserConfig({ ## Full-Site Encryption -In some cases, you may need to encrypt the entire site. Configure full-site encryption using the `encrypt. -global` option, then set one or more passwords using the `encrypt.admin` option. +In some cases, you may need to encrypt the entire site. +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" export default defineUserConfig({ @@ -56,22 +55,23 @@ export default defineUserConfig({ ## 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" export default defineUserConfig({ theme: plumeTheme({ encrypt: { 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', - // 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', - // 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', - // Can be specific page request path - encrypts this page + // Can be a specific page's request path to encrypt that page '/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', } } @@ -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 - 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. -- 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 -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 --- @@ -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 --- @@ -114,9 +115,9 @@ passwordHint: The password is 123456 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 @@ -124,7 +125,7 @@ The following configurations support use in [multilingual configuration](../../c - **Default**: `'Only password can access this site'` - **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 @@ -132,19 +133,19 @@ The following configurations support use in [multilingual configuration](../../c - **Default**: `'Only password can access this page'` - **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 - **Type**: `string` - **Default**: `'Confirm'` -- **Description**: Text for the confirmation button +- **Description**: The text for the confirmation button. ### encryptPlaceholder - **Type**: `string` - **Default**: `'Enter password'` -- **Description**: Placeholder text for the password input field +- **Description**: The placeholder text for the password input field. ### Example diff --git a/docs/en/guide/features/llmstxt.md b/docs/en/guide/features/llmstxt.md index ad4f1840..243c28f0 100644 --- a/docs/en/guide/features/llmstxt.md +++ b/docs/en/guide/features/llmstxt.md @@ -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**. ::: + +## Markup Extensions + +### `` + +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 `` tag. + +```md + + +## Section for LLMs + +This content appears only in the generated LLM file and will not include the `` tag itself. + + +``` + +You can also use the `` tag inline, but note that only one `` tag can be included per line; +otherwise, it will cause a parsing error. + +```md +Check the plugin API guide for documentation on creating plugins. + +For LLMs only +``` + +### `` + +You can add content in a file that is visible to humans but not to LLMs, which is the opposite of ``: + +```md + + +## Section for humans + +This content will not appear in the files generated for LLMs. + + +``` + +You can also use the `` tag inline, but note that only one `` tag can be included per line; +otherwise, it will cause a parsing error. + +```md +Check the plugin API guide for documentation on creating plugins. + +For humans only +``` diff --git a/docs/guide/features/encryption.md b/docs/guide/features/encryption.md index 028e4f32..a043ea40 100644 --- a/docs/guide/features/encryption.md +++ b/docs/guide/features/encryption.md @@ -7,7 +7,7 @@ permalink: /guide/features/encryption/ ## 加密 -在本主题中,支持 **全站加密** 和 **部分加密** 等多种灵活的加密方式。 +在本主题中,支持 **全站加密** 、 **部分页面加密** 和 **部分内容加密** 等多种灵活的加密方式。 ::: warning 提示 由于 `vuepress` 是静态站点,其自身限制的原因,**加密** 仅仅只是 看起来 看不到内容, @@ -53,7 +53,7 @@ export default defineUserConfig({ }) ``` -## 部分加密 +## 部分页面加密 大多数情况下,你可能只需需要 加密 某一篇文章、某一个目录 等。 因此,你可以通过 `encrypt.rules` 选项配置部分加密。 @@ -110,10 +110,112 @@ passwordHint: 密码是 123456 --- ``` -## 示例 +### 示例 点击访问 [加密文章,密码: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) 中使用。 diff --git a/docs/guide/features/llmstxt.md b/docs/guide/features/llmstxt.md index 02fb090e..33577b1c 100644 --- a/docs/guide/features/llmstxt.md +++ b/docs/guide/features/llmstxt.md @@ -103,3 +103,52 @@ export default defineClientConfig({ 因此,此组件提供的功能 **仅在构建后的生产包中才可用** 。 ::: + +## 扩展标记 (Markup) + +### `` + +你可以在文件中添加对 LLM 可见但对人类不可见的内容,这有助于设置特殊指令, +例如 “参考 basic-queries 获取演示”、“切勿执行……”、“在……情况下始终使用……”等。 + +为此,需要使用 `` 标签来包裹内容。 + +```md + + +## Section for LLMs + +此内容仅出现在生成的LLM文件中,不会包含 `` 标签本身。 + + +``` + +也可以在单行中使用 `` 标签,但请注意单行时仅能包含一个 `` 标签,否则会导致解析错误。 + +```md +查看插件API指南,了解创建插件的相关文档。 + +仅限 LLM 阅读 +``` + +### `` + +你可以在文件中添加对人类可见但对LLM不可见的内容,这与 `` 的作用相反: + +```md + + +## Section for humans + +此内容将不会出现在为 LLMs 生成的文件中 + + +``` + +也可以在单行中使用 `` 标签,但请注意单行时仅能包含一个 `` 标签,否则会导致解析错误。 + +```md +查看插件API指南,了解创建插件的相关文档。 + +仅限人类阅读 +``` diff --git a/plugins/plugin-md-power/src/client/components/VPEncryptSnippet.vue b/plugins/plugin-md-power/src/client/components/VPEncryptSnippet.vue new file mode 100644 index 00000000..6702e30e --- /dev/null +++ b/plugins/plugin-md-power/src/client/components/VPEncryptSnippet.vue @@ -0,0 +1,248 @@ + + + + + diff --git a/plugins/plugin-md-power/src/client/composables/decrypt.ts b/plugins/plugin-md-power/src/client/composables/decrypt.ts new file mode 100644 index 00000000..a1891e3e --- /dev/null +++ b/plugins/plugin-md-power/src/client/composables/decrypt.ts @@ -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'], + ) +} diff --git a/plugins/plugin-md-power/src/client/options.ts b/plugins/plugin-md-power/src/client/options.ts index cf59fcdf..41fb8a0e 100644 --- a/plugins/plugin-md-power/src/client/options.ts +++ b/plugins/plugin-md-power/src/client/options.ts @@ -1,5 +1,13 @@ +import type { LocaleConfig } from 'vuepress' +import type { EncryptSnippetLocale } from '../shared/encrypt.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 + export const pluginOptions: MarkdownPowerPluginOptions = __MD_POWER_INJECT_OPTIONS__ export const installed: { @@ -33,3 +41,5 @@ export const INJECT_TIMELINE_KEY: symbol = Symbol( export const INJECT_COLLAPSE_KEY: symbol = Symbol( __VUEPRESS_DEV__ ? 'collapse' : '', ) + +export const ENCRYPT_LOCALES = __MD_POWER_ENCRYPT_LOCALES__ diff --git a/plugins/plugin-md-power/src/client/shim.d.ts b/plugins/plugin-md-power/src/client/shim.d.ts index ce27319b..fab61a54 100644 --- a/plugins/plugin-md-power/src/client/shim.d.ts +++ b/plugins/plugin-md-power/src/client/shim.d.ts @@ -1,5 +1,3 @@ -import type { ReplEditorData } from '../shared/repl.js' - declare module '*.vue' { import type { ComponentOptions } from 'vue' @@ -8,16 +6,13 @@ declare module '*.vue' { } declare module '@internal/md-power/replEditorData' { + import type { ReplEditorData } from '../shared/repl.js' const res: ReplEditorData export default res } -declare global { - - const __MD_POWER_INJECT_OPTIONS__: MarkdownPowerPluginOptions - const __MD_POWER_DASHJS_INSTALLED__: boolean - const __MD_POWER_HLSJS_INSTALLED__: boolean - const __MD_POWER_MPEGTSJS_INSTALLED__: boolean - +declare module '@internal/encrypt-snippets' { + const res: Record Promise<{ default: string }>> + export default res } diff --git a/plugins/plugin-md-power/src/node/container/encrypt.ts b/plugins/plugin-md-power/src/node/container/encrypt.ts new file mode 100644 index 00000000..51fdd07b --- /dev/null +++ b/plugins/plugin-md-power/src/node/container/encrypt.ts @@ -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 = 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 `` + }) +} diff --git a/plugins/plugin-md-power/src/node/container/index.ts b/plugins/plugin-md-power/src/node/container/index.ts index 86f90f1d..46f45b88 100644 --- a/plugins/plugin-md-power/src/node/container/index.ts +++ b/plugins/plugin-md-power/src/node/container/index.ts @@ -9,6 +9,7 @@ import { codeTabs } from './codeTabs.js' import { codeTreePlugin } from './codeTree.js' import { collapsePlugin } from './collapse.js' import { demoWrapperPlugin } from './demoWrapper.js' +import { encryptPlugin } from './encrypt.js' import { fieldPlugin } from './field.js' import { fileTreePlugin } from './fileTree.js' import { langReplPlugin } from './langRepl.js' @@ -39,6 +40,11 @@ export async function containerPlugin( // ::: card / card-grid cardPlugin(md) + if (options.encrypt) { + // ::: encrypt password="xxx" + encryptPlugin(app, md, typeof options.encrypt === 'boolean' ? {} : options.encrypt) + } + if (options.npmTo) { // ::: npm-to npmToPlugins(md, typeof options.npmTo === 'boolean' ? {} : options.npmTo) diff --git a/plugins/plugin-md-power/src/node/locales/de.ts b/plugins/plugin-md-power/src/node/locales/de.ts new file mode 100644 index 00000000..1971b5fd --- /dev/null +++ b/plugins/plugin-md-power/src/node/locales/de.ts @@ -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.', + }, +} diff --git a/plugins/plugin-md-power/src/node/locales/en.ts b/plugins/plugin-md-power/src/node/locales/en.ts new file mode 100644 index 00000000..df6631e4 --- /dev/null +++ b/plugins/plugin-md-power/src/node/locales/en.ts @@ -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.', + }, +} diff --git a/plugins/plugin-md-power/src/node/locales/fr.ts b/plugins/plugin-md-power/src/node/locales/fr.ts new file mode 100644 index 00000000..3c8051fe --- /dev/null +++ b/plugins/plugin-md-power/src/node/locales/fr.ts @@ -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é.', + }, +} diff --git a/plugins/plugin-md-power/src/node/locales/index.ts b/plugins/plugin-md-power/src/node/locales/index.ts new file mode 100644 index 00000000..2050a037 --- /dev/null +++ b/plugins/plugin-md-power/src/node/locales/index.ts @@ -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 = [ + [['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], +] diff --git a/plugins/plugin-md-power/src/node/locales/ja.ts b/plugins/plugin-md-power/src/node/locales/ja.ts new file mode 100644 index 00000000..b981137e --- /dev/null +++ b/plugins/plugin-md-power/src/node/locales/ja.ts @@ -0,0 +1,12 @@ +import type { MDPowerLocaleData } from '../../shared/locale' + +export const jaLocale: MDPowerLocaleData = { + encrypt: { + hint: 'コンテンツは暗号化されています。閲覧するにはロックを解除してください。', + placeholder: 'パスワードを入力', + incPwd: 'パスワードが間違っています', + noContent: 'ロックは解除されましたが、コンテンツの読み込みに失敗しました。後ほど再度お試しください。', + warningTitle: '🚨 セキュリティ警告:', + warningText: '接続がHTTPSで暗号化されていないため、コンテンツの漏洩リスクがあり、暗号化されたコンテンツへのアクセスができません。', + }, +} diff --git a/plugins/plugin-md-power/src/node/locales/ko.ts b/plugins/plugin-md-power/src/node/locales/ko.ts new file mode 100644 index 00000000..e3631e16 --- /dev/null +++ b/plugins/plugin-md-power/src/node/locales/ko.ts @@ -0,0 +1,12 @@ +import type { MDPowerLocaleData } from '../../shared/locale' + +export const koLocale: MDPowerLocaleData = { + encrypt: { + hint: '내용이 암호화되어 있습니다. 잠금 해제 후 확인하세요.', + placeholder: '비밀번호 입력', + incPwd: '잘못된 비밀번호', + noContent: '잠금이 해제되었지만 내용을 불러오지 못했습니다. 나중에 다시 시도해 주세요.', + warningTitle: '🚨 보안 경고:', + warningText: '연결이 HTTPS로 암호화되지 않아 내용 유출 위험이 있으며, 암호화된 콘텐츠에 접근할 수 없습니다.', + }, +} diff --git a/plugins/plugin-md-power/src/node/locales/ru.ts b/plugins/plugin-md-power/src/node/locales/ru.ts new file mode 100644 index 00000000..cdaefe47 --- /dev/null +++ b/plugins/plugin-md-power/src/node/locales/ru.ts @@ -0,0 +1,12 @@ +import type { MDPowerLocaleData } from '../../shared/locale' + +export const ruLocale: MDPowerLocaleData = { + encrypt: { + hint: 'Контент зашифрован, разблокируйте для просмотра.', + placeholder: 'Введите пароль', + incPwd: 'Неверный пароль', + noContent: 'Разблокировано, но не удалось загрузить содержимое. Повторите попытку позже.', + warningTitle: '🚨 Предупреждение безопасности:', + warningText: 'Ваше соединение не защищено HTTPS, что создает риск утечки данных и блокирует доступ к зашифрованному контенту.', + }, +} diff --git a/plugins/plugin-md-power/src/node/locales/zh-tw.ts b/plugins/plugin-md-power/src/node/locales/zh-tw.ts new file mode 100644 index 00000000..2c60ab2a --- /dev/null +++ b/plugins/plugin-md-power/src/node/locales/zh-tw.ts @@ -0,0 +1,12 @@ +import type { MDPowerLocaleData } from '../../shared/locale' + +export const zhTWLocale: MDPowerLocaleData = { + encrypt: { + hint: '內容已加密,請解鎖後查看。', + placeholder: '輸入密碼', + incPwd: '密碼錯誤', + noContent: '已解鎖,但內容載入失敗,請稍後再試。', + warningTitle: '🚨 安全警告:', + warningText: '您的連線未使用 HTTPS 加密,可能導致內容洩露風險,無法存取加密內容。', + }, +} diff --git a/plugins/plugin-md-power/src/node/locales/zh.ts b/plugins/plugin-md-power/src/node/locales/zh.ts new file mode 100644 index 00000000..8a946554 --- /dev/null +++ b/plugins/plugin-md-power/src/node/locales/zh.ts @@ -0,0 +1,12 @@ +import type { MDPowerLocaleData } from '../../shared/locale' + +export const zhLocale: MDPowerLocaleData = { + encrypt: { + hint: '内容已加密,请解锁后查看。', + placeholder: '输入密码', + incPwd: '密码错误', + noContent: '已解锁,但内容加载失败,请稍后再试。', + warningTitle: '🚨 安全警告:', + warningText: '您的连接未使用HTTPS加密,存在内容泄露风险,无法访问加密内容。', + }, +} diff --git a/plugins/plugin-md-power/src/node/plugin.ts b/plugins/plugin-md-power/src/node/plugin.ts index ef871cc7..423b9a01 100644 --- a/plugins/plugin-md-power/src/node/plugin.ts +++ b/plugins/plugin-md-power/src/node/plugin.ts @@ -22,7 +22,14 @@ export function markdownPowerPlugin( 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) { if (options.repl) { diff --git a/plugins/plugin-md-power/src/node/prepareConfigFile.ts b/plugins/plugin-md-power/src/node/prepareConfigFile.ts index 2da8c52a..5ac63504 100644 --- a/plugins/plugin-md-power/src/node/prepareConfigFile.ts +++ b/plugins/plugin-md-power/src/node/prepareConfigFile.ts @@ -21,6 +21,11 @@ export async function prepareConfigFile(app: App, options: MarkdownPowerPluginOp imports.add(`import CodeTabs from '${CLIENT_FOLDER}components/CodeTabs.vue'`) 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) { imports.add(`import PDFViewer from '${CLIENT_FOLDER}components/PDFViewer.vue'`) enhances.add(`app.component('PDFViewer', PDFViewer)`) diff --git a/plugins/plugin-md-power/src/node/provideData.ts b/plugins/plugin-md-power/src/node/provideData.ts index 8b21ec70..09b45c4d 100644 --- a/plugins/plugin-md-power/src/node/provideData.ts +++ b/plugins/plugin-md-power/src/node/provideData.ts @@ -1,19 +1,44 @@ +import type { App, LocaleConfig } from 'vuepress' 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 { LOCALE_OPTIONS } from './locales/index.js' -export function provideData(options: MarkdownPowerPluginOptions): Record { - const mardownOptions = { +export function provideData(app: App, options: MarkdownPowerPluginOptions): Record { + const markdownOptions = { plot: options.plot, pdf: options.pdf, } + + const locales = getFullLocaleConfig({ + app, + name: 'vuepress-plugin-md-power', + default: LOCALE_OPTIONS, + config: options.locales, + }) const icon = options.icon ?? { provider: 'iconify' } return { - __MD_POWER_INJECT_OPTIONS__: mardownOptions, + __MD_POWER_INJECT_OPTIONS__: markdownOptions, __MD_POWER_DASHJS_INSTALLED__: isPackageExists('dashjs'), __MD_POWER_HLSJS_INSTALLED__: isPackageExists('hls.js'), __MD_POWER_MPEGTSJS_INSTALLED__: isPackageExists('mpegts.js'), __MD_POWER_ICON_PROVIDER__: icon.provider || 'iconify', __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, key: K): Record { + const res: Record = {} + + for (const [locale, value] of Object.entries(locales)) { + res[locale] = value[key] ?? {} as T[K] + } + + return res +} diff --git a/plugins/plugin-md-power/src/node/utils/encryptContent.ts b/plugins/plugin-md-power/src/node/utils/encryptContent.ts new file mode 100644 index 00000000..08acf0d8 --- /dev/null +++ b/plugins/plugin-md-power/src/node/utils/encryptContent.ts @@ -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)) +} diff --git a/plugins/plugin-md-power/src/shared/encrypt.ts b/plugins/plugin-md-power/src/shared/encrypt.ts new file mode 100644 index 00000000..c7c7a9ef --- /dev/null +++ b/plugins/plugin-md-power/src/shared/encrypt.ts @@ -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 +} diff --git a/plugins/plugin-md-power/src/shared/locale.ts b/plugins/plugin-md-power/src/shared/locale.ts new file mode 100644 index 00000000..c783a95a --- /dev/null +++ b/plugins/plugin-md-power/src/shared/locale.ts @@ -0,0 +1,6 @@ +import type { LocaleData } from 'vuepress' +import type { EncryptSnippetLocale } from './encrypt' + +export interface MDPowerLocaleData extends LocaleData { + encrypt?: EncryptSnippetLocale +} diff --git a/plugins/plugin-md-power/src/shared/plugin.ts b/plugins/plugin-md-power/src/shared/plugin.ts index c6e26ec7..0879e48f 100644 --- a/plugins/plugin-md-power/src/shared/plugin.ts +++ b/plugins/plugin-md-power/src/shared/plugin.ts @@ -1,9 +1,12 @@ +import type { LocaleConfig } from 'vuepress' import type { CanIUseOptions } from './caniuse.js' import type { CodeTabsOptions } from './codeTabs.js' import type { CodeTreeOptions } from './codeTree.js' +import type { EncryptSnippetOptions } from './encrypt.js' import type { MarkdownEnvPreset } from './env.js' import type { FileTreeOptions } from './fileTree.js' import type { IconOptions } from './icon.js' +import type { MDPowerLocaleData } from './locale.js' import type { MarkOptions } from './mark.js' import type { NpmToOptions } from './npmTo.js' import type { PDFOptions } from './pdf.js' @@ -55,6 +58,13 @@ export interface MarkdownPowerPluginOptions { * @default 'eager' */ mark?: MarkOptions + + /** + * 是否启用 内容片段加密容器 + * + * @default false + */ + encrypt?: boolean | EncryptSnippetOptions /** * 配置代码块分组 */ @@ -310,4 +320,6 @@ export interface MarkdownPowerPluginOptions { * @default false */ imageSize?: boolean | 'local' | 'all' + + locales?: LocaleConfig } diff --git a/plugins/plugin-md-power/tsdown.config.mjs b/plugins/plugin-md-power/tsdown.config.mjs index 7c44a5fe..0348a30e 100644 --- a/plugins/plugin-md-power/tsdown.config.mjs +++ b/plugins/plugin-md-power/tsdown.config.mjs @@ -4,7 +4,7 @@ import { argv } from '../../scripts/tsdown-args.mjs' /** @import {Options} from 'tsdown' */ 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: '', files: ['index.ts', 'options.ts'] }, ] diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a1b85499..7e58c4ba 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -213,11 +213,11 @@ catalogs: specifier: ^3.1.0 version: 3.1.0 '@vueuse/core': - specifier: ^14.1.0 - version: 14.1.0 + specifier: ^14.2.0 + version: 14.2.1 '@vueuse/integrations': - specifier: ^14.1.0 - version: 14.1.0 + specifier: ^14.2.0 + version: 14.2.1 cac: specifier: ^6.7.14 version: 6.7.14 @@ -400,7 +400,7 @@ overrides: chokidar: 5.0.0 esbuild: ^0.27.2 sass-embedded: ^1.97.2 - vite: ^8.0.0-beta.8 + vite: ^8.0.0-beta.10 vue-router: ^4.6.4 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))) '@vueuse/core': 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: specifier: 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))) '@vueuse/core': 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': 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: specifier: 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))) '@vuepress/plugin-shiki': 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': 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))) @@ -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))) '@vueuse/core': 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: specifier: 5.0.0 version: 5.0.0 @@ -1956,8 +1956,8 @@ packages: resolution: {integrity: sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==} engines: {node: '>=8.0.0'} - '@oxc-project/runtime@0.108.0': - resolution: {integrity: sha512-J1cESY4anMO4i9KtCPmCfQAzAR00Uw4SWsDPFP10CIwDMugkh34UrTKByuYKuPaHy0XAk8LlJiZJq2OLMfbuIQ==} + '@oxc-project/runtime@0.113.0': + resolution: {integrity: sha512-apRWH/gXeAsl/sQiblIZnLu7f8P/C9S2fJIicuHV9KOK9J7Hv1JPyTwB8WAcOrDBfjs+cbzjMOGe9UR2ue4ZQg==} engines: {node: ^20.19.0 || >=22.12.0} '@oxc-project/types@0.107.0': @@ -1966,6 +1966,9 @@ packages: '@oxc-project/types@0.108.0': 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': resolution: {integrity: sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==} engines: {node: '>= 10.0.0'} @@ -2170,6 +2173,12 @@ packages: cpu: [arm64] 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': resolution: {integrity: sha512-hqGXRc162qCCIOAcHN2Cw4eXiVTwYsMFLOhAy1IG2CxY+dwc/l4Ga+dLPkLor3Ikqy5WDn+7kxHbbh6EmshEpQ==} engines: {node: ^20.19.0 || >=22.12.0} @@ -2182,6 +2191,12 @@ packages: cpu: [arm64] 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': resolution: {integrity: sha512-ezvvGuhteE15JmMhJW0wS7BaXmhwLy1YHeEwievYaPC1PgGD86wgBKfOpHr9tSKllAXbCe0BeeMvasscWLhKdA==} engines: {node: ^20.19.0 || >=22.12.0} @@ -2194,6 +2209,12 @@ packages: cpu: [x64] 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': resolution: {integrity: sha512-4fhKVJiEYVd5n6no/mrL3LZ9kByfCGwmONOrdtvx8DJGDQhehH/q3RfhG3V/4jGKhpXgbDjpIjkkFdybCTcgew==} engines: {node: ^20.19.0 || >=22.12.0} @@ -2206,6 +2227,12 @@ packages: cpu: [x64] 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': resolution: {integrity: sha512-T3Y52sW6JAhvIqArBw+wtjNU1Ieaz4g0NBxyjSJoW971nZJBZygNlSYx78G4cwkCmo1dYTciTPDOnQygLV23pA==} engines: {node: ^20.19.0 || >=22.12.0} @@ -2218,6 +2245,12 @@ packages: cpu: [arm] 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': resolution: {integrity: sha512-NIW40jQDSQap2KDdmm9z3B/4OzWJ6trf8dwx3FD74kcQb3v34ThsBFTtzE5KjDuxnxgUlV+DkAu+XgSMKrgufw==} engines: {node: ^20.19.0 || >=22.12.0} @@ -2232,6 +2265,13 @@ packages: os: [linux] 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': resolution: {integrity: sha512-CCKEk+H+8c0WGe/8n1E20n85Tq4Pv+HNAbjP1KfUXW+01aCWSMjU56ChNrM2tvHnXicfm7QRNoZyfY8cWh7jLQ==} engines: {node: ^20.19.0 || >=22.12.0} @@ -2246,6 +2286,13 @@ packages: os: [linux] 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': resolution: {integrity: sha512-VlfwJ/HCskPmQi8R0JuAFndySKVFX7yPhE658o27cjSDWWbXVtGkSbwaxstii7Q+3Rz87ZXN+HLnb1kd4R9Img==} engines: {node: ^20.19.0 || >=22.12.0} @@ -2260,6 +2307,13 @@ packages: os: [linux] 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': resolution: {integrity: sha512-kuO92hTRyGy0Ts3Nsqll0rfO8eFsEJe9dGQGktkQnZ2hrJrDVN0y419dMgKy/gB2S2o7F2dpWhpfQOBehZPwVA==} engines: {node: ^20.19.0 || >=22.12.0} @@ -2274,6 +2328,13 @@ packages: os: [linux] 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': resolution: {integrity: sha512-PXAebvNL4sYfCqi8LdY4qyFRacrRoiPZLo3NoUmiTxm7MPtYYR8CNtBGNokqDmMuZIQIecRaD/jbmFAIDz7DxQ==} engines: {node: ^20.19.0 || >=22.12.0} @@ -2286,6 +2347,12 @@ packages: cpu: [arm64] 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': resolution: {integrity: sha512-yJoklQg7XIZq8nAg0bbkEXcDK6sfpjxQGxpg2Nd6ERNtvg+eOaEBRgPww0BVTrYFQzje1pB5qPwC2VnJHT3koQ==} engines: {node: '>=14.0.0'} @@ -2296,6 +2363,11 @@ packages: engines: {node: '>=14.0.0'} 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': resolution: {integrity: sha512-ljZ4+McmCbIuZwEBaoGtiG8Rq2nJjaXEnLEIx+usWetXn1ECjXY0LAhkELxOV6ytv4ensEmoJJ8nXg47hRMjlw==} engines: {node: ^20.19.0 || >=22.12.0} @@ -2308,6 +2380,12 @@ packages: cpu: [arm64] 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': resolution: {integrity: sha512-bMY4tTIwbdZljW+xe/ln1hvs0SRitahQSXfWtvgAtIzgSX9Ar7KqJzU7lRm33YTRFIHLULRi53yNjw9nJGd6uQ==} engines: {node: ^20.19.0 || >=22.12.0} @@ -2320,6 +2398,12 @@ packages: cpu: [x64] 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': resolution: {integrity: sha512-NIJgOsMjbxAXvoGq/X0gD7VPMQ8j9g0BiDaNjVNVjvl+iKXxL3Jre0v31RmBYeLEmkbj2s02v8vFTbUXi5XS2Q==} @@ -2329,6 +2413,9 @@ packages: '@rolldown/pluginutils@1.0.0-beta.60': 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': resolution: {integrity: sha512-BTm2qKNnWIQ5auf4deoetINJm2JzvihvGb9R6K/ETwKLql/Bb3Eg2H1FBp1gUb4YGbydMA3jcmQTR73q7J+GAA==} cpu: [arm] @@ -2929,7 +3016,7 @@ packages: resolution: {integrity: sha512-+MaE752hU0wfPFJEUAIxqw18+20euHHdxVtMvbFcOEpjEyfqXH/5DCoTHiVJ0J29EhTJdoTkjEv5YBKU9dnoTw==} engines: {node: ^20.19.0 || >=22.12.0} peerDependencies: - vite: ^8.0.0-beta.8 + vite: ^8.0.0-beta.10 vue: ^3.2.25 '@vitest/coverage-v8@4.0.17': @@ -2961,7 +3048,7 @@ packages: resolution: {integrity: sha512-+ZtQhLA3lDh1tI2wxe3yMsGzbp7uuJSWBM1iTIKCbppWTSBN09PUC+L+fyNlQApQoR+Ps8twt2pbSSXg2fQVEQ==} peerDependencies: msw: ^2.4.9 - vite: ^8.0.0-beta.8 + vite: ^8.0.0-beta.10 peerDependenciesMeta: msw: optional: true @@ -3219,24 +3306,19 @@ packages: '@vuepress/utils@2.0.0-rc.26': 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': resolution: {integrity: sha512-3vwDzV+GDUNpdegRY6kzpLm4Igptq+GA0QkJ3W61Iv27YWwW/ufSlOfgQIpN6FZRMG0mkaz4gglJRtq5SeJyIQ==} peerDependencies: vue: ^3.5.0 - '@vueuse/integrations@14.1.0': - resolution: {integrity: sha512-eNQPdisnO9SvdydTIXnTE7c29yOsJBD/xkwEyQLdhDC/LKbqrFpXHb3uS//7NcIrQO3fWVuvMGp8dbK6mNEMCA==} + '@vueuse/integrations@14.2.1': + resolution: {integrity: sha512-2LIUpBi/67PoXJGqSDQUF0pgQWpNHh7beiA+KG2AbybcNm+pTGWT6oPGlBgUoDWmYwfeQqM/uzOHqcILpKL7nA==} peerDependencies: async-validator: ^4 axios: ^1 change-case: ^5 drauu: ^0.4 - focus-trap: ^7 + focus-trap: ^7 || ^8 fuse.js: ^7 idb-keyval: ^6 jwt-decode: ^4 @@ -3271,17 +3353,9 @@ packages: universal-cookie: optional: true - '@vueuse/metadata@14.1.0': - resolution: {integrity: sha512-7hK4g015rWn2PhKcZ99NyT+ZD9sbwm7SGvp7k+k+rKGWnLjS/oQozoIZzWfCewSUeBmnJkIb+CNr7Zc/EyRnnA==} - '@vueuse/metadata@14.2.1': 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': resolution: {integrity: sha512-shTJncjV9JTI4oVNyF1FQonetYAiTBd+Qj7cY89SWbXSkx7gyhrgtEdF2ZAVWS1S3SHlaROO6F2IesJxQEkZBw==} peerDependencies: @@ -5570,78 +5644,78 @@ packages: lie@3.1.1: resolution: {integrity: sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw==} - lightningcss-android-arm64@1.30.2: - resolution: {integrity: sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A==} + lightningcss-android-arm64@1.31.1: + resolution: {integrity: sha512-HXJF3x8w9nQ4jbXRiNppBCqeZPIAfUo8zE/kOEGbW5NZvGc/K7nMxbhIr+YlFlHW5mpbg/YFPdbnCh1wAXCKFg==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [android] - lightningcss-darwin-arm64@1.30.2: - resolution: {integrity: sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA==} + lightningcss-darwin-arm64@1.31.1: + resolution: {integrity: sha512-02uTEqf3vIfNMq3h/z2cJfcOXnQ0GRwQrkmPafhueLb2h7mqEidiCzkE4gBMEH65abHRiQvhdcQ+aP0D0g67sg==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [darwin] - lightningcss-darwin-x64@1.30.2: - resolution: {integrity: sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ==} + lightningcss-darwin-x64@1.31.1: + resolution: {integrity: sha512-1ObhyoCY+tGxtsz1lSx5NXCj3nirk0Y0kB/g8B8DT+sSx4G9djitg9ejFnjb3gJNWo7qXH4DIy2SUHvpoFwfTA==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [darwin] - lightningcss-freebsd-x64@1.30.2: - resolution: {integrity: sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA==} + lightningcss-freebsd-x64@1.31.1: + resolution: {integrity: sha512-1RINmQKAItO6ISxYgPwszQE1BrsVU5aB45ho6O42mu96UiZBxEXsuQ7cJW4zs4CEodPUioj/QrXW1r9pLUM74A==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [freebsd] - lightningcss-linux-arm-gnueabihf@1.30.2: - resolution: {integrity: sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA==} + lightningcss-linux-arm-gnueabihf@1.31.1: + resolution: {integrity: sha512-OOCm2//MZJ87CdDK62rZIu+aw9gBv4azMJuA8/KB74wmfS3lnC4yoPHm0uXZ/dvNNHmnZnB8XLAZzObeG0nS1g==} engines: {node: '>= 12.0.0'} cpu: [arm] os: [linux] - lightningcss-linux-arm64-gnu@1.30.2: - resolution: {integrity: sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A==} + lightningcss-linux-arm64-gnu@1.31.1: + resolution: {integrity: sha512-WKyLWztD71rTnou4xAD5kQT+982wvca7E6QoLpoawZ1gP9JM0GJj4Tp5jMUh9B3AitHbRZ2/H3W5xQmdEOUlLg==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] libc: [glibc] - lightningcss-linux-arm64-musl@1.30.2: - resolution: {integrity: sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==} + lightningcss-linux-arm64-musl@1.31.1: + resolution: {integrity: sha512-mVZ7Pg2zIbe3XlNbZJdjs86YViQFoJSpc41CbVmKBPiGmC4YrfeOyz65ms2qpAobVd7WQsbW4PdsSJEMymyIMg==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] libc: [musl] - lightningcss-linux-x64-gnu@1.30.2: - resolution: {integrity: sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==} + lightningcss-linux-x64-gnu@1.31.1: + resolution: {integrity: sha512-xGlFWRMl+0KvUhgySdIaReQdB4FNudfUTARn7q0hh/V67PVGCs3ADFjw+6++kG1RNd0zdGRlEKa+T13/tQjPMA==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] libc: [glibc] - lightningcss-linux-x64-musl@1.30.2: - resolution: {integrity: sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==} + lightningcss-linux-x64-musl@1.31.1: + resolution: {integrity: sha512-eowF8PrKHw9LpoZii5tdZwnBcYDxRw2rRCyvAXLi34iyeYfqCQNA9rmUM0ce62NlPhCvof1+9ivRaTY6pSKDaA==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] libc: [musl] - lightningcss-win32-arm64-msvc@1.30.2: - resolution: {integrity: sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==} + lightningcss-win32-arm64-msvc@1.31.1: + resolution: {integrity: sha512-aJReEbSEQzx1uBlQizAOBSjcmr9dCdL3XuC/6HLXAxmtErsj2ICo5yYggg1qOODQMtnjNQv2UHb9NpOuFtYe4w==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [win32] - lightningcss-win32-x64-msvc@1.30.2: - resolution: {integrity: sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw==} + lightningcss-win32-x64-msvc@1.31.1: + resolution: {integrity: sha512-I9aiFrbd7oYHwlnQDqr1Roz+fTz61oDDJX7n9tYF9FJymH1cIN1DtKw3iYt6b8WZgEjoNwVSncwF4wx/ZedMhw==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [win32] - lightningcss@1.30.2: - resolution: {integrity: sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ==} + lightningcss@1.31.1: + resolution: {integrity: sha512-l51N2r93WmGUye3WuFoN5k10zyvrVs0qfKBhyC5ogUQ6Ew6JUSswh78mbSO+IU3nTWsyOArqPCcShdQSadghBQ==} engines: {node: '>= 12.0.0'} lilconfig@3.1.3: @@ -6729,6 +6803,11 @@ packages: engines: {node: ^20.19.0 || >=22.12.0} 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: resolution: {integrity: sha512-CLEVl+MnPAiKh5pl4dEWSyMTpuflgNQiLGhMv8ezD5W/qP8AKvmYpCOKRRNOh7oRKnauBZ4SyeYkMS+1VSyKwQ==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} @@ -7594,12 +7673,13 @@ packages: vfile@6.0.3: resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==} - vite@8.0.0-beta.8: - resolution: {integrity: sha512-PetN5BNs5dj6NSu1pDrbr0AtbH9KjPhQ/dLePvhLYsYgnZdj6+ihGjtA4DYcR9bASOzOmxN1NqEJEJ4JBUIvpA==} + vite@8.0.0-beta.14: + resolution: {integrity: sha512-oLW66oi8tZcoxu6+1HFXb+5hLHco3OnEVu2Awmj5NqEo7vxaqybjBM0BXHcq+jAFhzkMGXJl8xcO5qDBczgKLg==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true peerDependencies: '@types/node': ^20.19.0 || >=22.12.0 + '@vitejs/devtools': ^0.0.0-alpha.31 esbuild: ^0.27.2 jiti: '>=1.21.0' less: ^4.0.0 @@ -7613,6 +7693,8 @@ packages: peerDependenciesMeta: '@types/node': optional: true + '@vitejs/devtools': + optional: true esbuild: optional: true jiti: @@ -8897,12 +8979,14 @@ snapshots: '@opentelemetry/api@1.9.0': optional: true - '@oxc-project/runtime@0.108.0': {} + '@oxc-project/runtime@0.113.0': {} '@oxc-project/types@0.107.0': {} '@oxc-project/types@0.108.0': {} + '@oxc-project/types@0.113.0': {} + '@parcel/watcher-android-arm64@2.5.1': optional: true @@ -9076,60 +9160,90 @@ snapshots: '@rolldown/binding-android-arm64@1.0.0-beta.60': optional: true + '@rolldown/binding-android-arm64@1.0.0-rc.4': + optional: true + '@rolldown/binding-darwin-arm64@1.0.0-beta.59': optional: true '@rolldown/binding-darwin-arm64@1.0.0-beta.60': optional: true + '@rolldown/binding-darwin-arm64@1.0.0-rc.4': + optional: true + '@rolldown/binding-darwin-x64@1.0.0-beta.59': optional: true '@rolldown/binding-darwin-x64@1.0.0-beta.60': optional: true + '@rolldown/binding-darwin-x64@1.0.0-rc.4': + optional: true + '@rolldown/binding-freebsd-x64@1.0.0-beta.59': optional: true '@rolldown/binding-freebsd-x64@1.0.0-beta.60': optional: true + '@rolldown/binding-freebsd-x64@1.0.0-rc.4': + optional: true + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.59': optional: true '@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.60': optional: true + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.4': + optional: true + '@rolldown/binding-linux-arm64-gnu@1.0.0-beta.59': optional: true '@rolldown/binding-linux-arm64-gnu@1.0.0-beta.60': optional: true + '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.4': + optional: true + '@rolldown/binding-linux-arm64-musl@1.0.0-beta.59': optional: true '@rolldown/binding-linux-arm64-musl@1.0.0-beta.60': optional: true + '@rolldown/binding-linux-arm64-musl@1.0.0-rc.4': + optional: true + '@rolldown/binding-linux-x64-gnu@1.0.0-beta.59': optional: true '@rolldown/binding-linux-x64-gnu@1.0.0-beta.60': optional: true + '@rolldown/binding-linux-x64-gnu@1.0.0-rc.4': + optional: true + '@rolldown/binding-linux-x64-musl@1.0.0-beta.59': optional: true '@rolldown/binding-linux-x64-musl@1.0.0-beta.60': optional: true + '@rolldown/binding-linux-x64-musl@1.0.0-rc.4': + optional: true + '@rolldown/binding-openharmony-arm64@1.0.0-beta.59': optional: true '@rolldown/binding-openharmony-arm64@1.0.0-beta.60': optional: true + '@rolldown/binding-openharmony-arm64@1.0.0-rc.4': + optional: true + '@rolldown/binding-wasm32-wasi@1.0.0-beta.59': dependencies: '@napi-rs/wasm-runtime': 1.1.1 @@ -9140,24 +9254,37 @@ snapshots: '@napi-rs/wasm-runtime': 1.1.1 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': optional: true '@rolldown/binding-win32-arm64-msvc@1.0.0-beta.60': optional: true + '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.4': + optional: true + '@rolldown/binding-win32-x64-msvc@1.0.0-beta.59': optional: true '@rolldown/binding-win32-x64-msvc@1.0.0-beta.60': 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.59': {} '@rolldown/pluginutils@1.0.0-beta.60': {} + '@rolldown/pluginutils@1.0.0-rc.4': {} + '@rollup/rollup-android-arm-eabi@4.52.4': optional: true @@ -9774,10 +9901,10 @@ snapshots: '@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: '@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) '@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 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: '@vitest/spy': 4.0.17 estree-walker: 3.0.3 magic-string: 0.30.21 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': 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)': 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/client': 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-load-config: 6.0.1(jiti@2.6.1)(postcss@8.5.6)(yaml@2.8.2) 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-router: 4.6.4(vue@3.5.27(typescript@5.9.3)) transitivePeerDependencies: - '@types/node' + - '@vitejs/devtools' - esbuild - jiti - less @@ -10027,12 +10155,12 @@ snapshots: transitivePeerDependencies: - 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: '@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)) 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': dependencies: @@ -10243,11 +10371,11 @@ snapshots: transitivePeerDependencies: - 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: '@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/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 shiki: 3.22.0 synckit: 0.11.12 @@ -10315,13 +10443,6 @@ snapshots: transitivePeerDependencies: - 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))': dependencies: '@types/web-bluetooth': 0.0.21 @@ -10329,10 +10450,10 @@ snapshots: '@vueuse/shared': 14.2.1(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: - '@vueuse/core': 14.1.0(vue@3.5.27(typescript@5.9.3)) - '@vueuse/shared': 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.2.1(vue@3.5.27(typescript@5.9.3)) vue: 3.5.27(typescript@5.9.3) optionalDependencies: axios: 1.13.2 @@ -10340,14 +10461,8 @@ snapshots: focus-trap: 7.8.0 qrcode: 1.5.4 - '@vueuse/metadata@14.1.0': {} - '@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))': dependencies: vue: 3.5.27(typescript@5.9.3) @@ -12931,54 +13046,54 @@ snapshots: dependencies: immediate: 3.0.6 - lightningcss-android-arm64@1.30.2: + lightningcss-android-arm64@1.31.1: optional: true - lightningcss-darwin-arm64@1.30.2: + lightningcss-darwin-arm64@1.31.1: optional: true - lightningcss-darwin-x64@1.30.2: + lightningcss-darwin-x64@1.31.1: optional: true - lightningcss-freebsd-x64@1.30.2: + lightningcss-freebsd-x64@1.31.1: optional: true - lightningcss-linux-arm-gnueabihf@1.30.2: + lightningcss-linux-arm-gnueabihf@1.31.1: optional: true - lightningcss-linux-arm64-gnu@1.30.2: + lightningcss-linux-arm64-gnu@1.31.1: optional: true - lightningcss-linux-arm64-musl@1.30.2: + lightningcss-linux-arm64-musl@1.31.1: optional: true - lightningcss-linux-x64-gnu@1.30.2: + lightningcss-linux-x64-gnu@1.31.1: optional: true - lightningcss-linux-x64-musl@1.30.2: + lightningcss-linux-x64-musl@1.31.1: optional: true - lightningcss-win32-arm64-msvc@1.30.2: + lightningcss-win32-arm64-msvc@1.31.1: optional: true - lightningcss-win32-x64-msvc@1.30.2: + lightningcss-win32-x64-msvc@1.31.1: optional: true - lightningcss@1.30.2: + lightningcss@1.31.1: dependencies: detect-libc: 2.1.2 optionalDependencies: - lightningcss-android-arm64: 1.30.2 - lightningcss-darwin-arm64: 1.30.2 - lightningcss-darwin-x64: 1.30.2 - lightningcss-freebsd-x64: 1.30.2 - lightningcss-linux-arm-gnueabihf: 1.30.2 - lightningcss-linux-arm64-gnu: 1.30.2 - lightningcss-linux-arm64-musl: 1.30.2 - lightningcss-linux-x64-gnu: 1.30.2 - lightningcss-linux-x64-musl: 1.30.2 - lightningcss-win32-arm64-msvc: 1.30.2 - lightningcss-win32-x64-msvc: 1.30.2 + lightningcss-android-arm64: 1.31.1 + lightningcss-darwin-arm64: 1.31.1 + lightningcss-darwin-x64: 1.31.1 + lightningcss-freebsd-x64: 1.31.1 + lightningcss-linux-arm-gnueabihf: 1.31.1 + lightningcss-linux-arm64-gnu: 1.31.1 + lightningcss-linux-arm64-musl: 1.31.1 + lightningcss-linux-x64-gnu: 1.31.1 + lightningcss-linux-x64-musl: 1.31.1 + lightningcss-win32-arm64-msvc: 1.31.1 + lightningcss-win32-x64-msvc: 1.31.1 lilconfig@3.1.3: {} @@ -14310,6 +14425,25 @@ snapshots: '@rolldown/binding-win32-arm64-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: dependencies: '@types/estree': 1.0.8 @@ -15248,14 +15382,14 @@ snapshots: '@types/unist': 3.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: - '@oxc-project/runtime': 0.108.0 + '@oxc-project/runtime': 0.113.0 fdir: 6.5.0(picomatch@4.0.3) - lightningcss: 1.30.2 + lightningcss: 1.31.1 picomatch: 4.0.3 postcss: 8.5.6 - rolldown: 1.0.0-beta.60 + rolldown: 1.0.0-rc.4 tinyglobby: 0.2.15 optionalDependencies: '@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): dependencies: '@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/runner': 4.0.17 '@vitest/snapshot': 4.0.17 @@ -15288,12 +15422,13 @@ snapshots: tinyexec: 1.0.2 tinyglobby: 0.2.15 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 optionalDependencies: '@opentelemetry/api': 1.9.0 '@types/node': 25.0.9 transitivePeerDependencies: + - '@vitejs/devtools' - esbuild - jiti - less diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index babf440e..5ff8640d 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -61,7 +61,7 @@ catalogs: tsconfig-vuepress: ^7.0.0 tsdown: ^0.19.0 typescript: ^5.9.3 - vite: ^8.0.0-beta.8 + vite: ^8.0.0-beta.10 vitest: ^4.0.17 vue-router: ^4.6.4 wait-on: ^9.0.3 @@ -97,8 +97,8 @@ catalogs: '@mdit/plugin-tab': ^0.23.0 '@mdit/plugin-tasklist': ^0.22.2 '@pengzhanbo/utils': ^3.1.0 - '@vueuse/core': ^14.1.0 - '@vueuse/integrations': ^14.1.0 + '@vueuse/core': ^14.2.0 + '@vueuse/integrations': ^14.2.0 cac: ^6.7.14 chart.js: ^4.5.1 chokidar: 5.0.0 diff --git a/theme/src/client/components/Home/VPHomeHero.vue b/theme/src/client/components/Home/VPHomeHero.vue index ed6f9352..0e6db818 100644 --- a/theme/src/client/components/Home/VPHomeHero.vue +++ b/theme/src/client/components/Home/VPHomeHero.vue @@ -61,6 +61,7 @@ let defaultTheme: string | undefined watch(() => props.forceDark, () => { if (!inBrowser || __VUEPRESS_SSR__) return + if (props.forceDark) { defaultTheme ??= document.documentElement.dataset.theme document.documentElement.dataset.theme = 'dark' @@ -69,7 +70,7 @@ watch(() => props.forceDark, () => { noTransition() } document.documentElement.classList.add(`effect-${effect.value}`) -}, { immediate: true }) +}, { immediate: true, flush: 'post' }) onMounted(() => { if (props.forceDark) { @@ -273,7 +274,9 @@ html.no-transition *::after { 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; } diff --git a/theme/src/client/components/Nav/VPNavBarExtra.vue b/theme/src/client/components/Nav/VPNavBarExtra.vue index 6bdfa02e..3b46599a 100644 --- a/theme/src/client/components/Nav/VPNavBarExtra.vue +++ b/theme/src/client/components/Nav/VPNavBarExtra.vue @@ -50,7 +50,7 @@ const hasExtraContent = computed( -
+

{{ theme.appearanceText || 'Appearance' }} @@ -61,7 +61,7 @@ const hasExtraContent = computed(

-
+