diff --git a/.github/labeler.yml b/.github/labeler.yml index 00bcab5958..f564e060d2 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -5,6 +5,7 @@ i18n: - src/content/docs/fr/**/* - src/content/docs/it/**/* - src/content/docs/zh-cn/**/* + - src/content/docs/zh-tw/**/* - src/content/docs/ja/**/* "i18n: es": @@ -19,6 +20,9 @@ i18n: "i18n: zh-cn": - src/content/docs/zh-cn/**/* +"i18n: zh-tw": + - src/content/docs/zh-tw/**/* + "i18n: ja": - src/content/docs/ja/**/* diff --git a/astro.config.mjs b/astro.config.mjs index 261cb2ae04..6ac8b30b4c 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -145,6 +145,7 @@ export default defineConfig({ label: 'Guides', translations: { 'zh-CN': '指引', + 'zh-TW': '指南', }, collapsed: true, items: [ @@ -152,6 +153,7 @@ export default defineConfig({ label: 'Quick Start', translations: { 'zh-CN': '快速开始', + 'zh-TW': '快速開始', }, collapsed: true, items: [ @@ -159,6 +161,7 @@ export default defineConfig({ label: 'What is Tauri?', translations: { 'zh-CN': '什么是 Tauri?', + 'zh-TW': '什麼是 Tauri?', }, link: '/start/', }, @@ -166,6 +169,7 @@ export default defineConfig({ label: 'Prerequisites', translations: { 'zh-CN': '前置条件', + 'zh-TW': '前置條件', }, link: '/start/prerequisites/', }, @@ -173,6 +177,7 @@ export default defineConfig({ label: 'Create a Project', translations: { 'zh-CN': '创建项目', + 'zh-TW': '建立專案', }, link: '/start/create-project/', }, @@ -180,6 +185,7 @@ export default defineConfig({ label: 'Frontend Configuration', translations: { 'zh-CN': '前端配置', + 'zh-TW': '前端組態設置', }, collapsed: true, autogenerate: { directory: 'start/frontend' }, @@ -188,6 +194,7 @@ export default defineConfig({ label: 'Upgrade & Migrate', translations: { 'zh-CN': '升级和迁移', + 'zh-TW': '升級和遷移', }, collapsed: true, autogenerate: { directory: 'start/migrate' }, @@ -198,6 +205,7 @@ export default defineConfig({ label: 'Core Concepts', translations: { 'zh-CN': '核心概念', + 'zh-TW': '核心概念', }, collapsed: true, autogenerate: { directory: 'concept' }, @@ -206,6 +214,7 @@ export default defineConfig({ label: 'Security', translations: { 'zh-CN': '安全', + 'zh-TW': '安全', }, collapsed: true, autogenerate: { directory: 'security' }, @@ -214,6 +223,7 @@ export default defineConfig({ label: 'Develop', translations: { 'zh-CN': '开发', + 'zh-TW': '開發', }, collapsed: true, autogenerate: { directory: 'develop' }, @@ -222,6 +232,7 @@ export default defineConfig({ label: 'Distribute', translations: { 'zh-CN': '分发', + 'zh-TW': '分發', }, collapsed: true, autogenerate: { directory: 'distribute' }, @@ -230,6 +241,7 @@ export default defineConfig({ label: 'Learn', translations: { 'zh-CN': '学习', + 'zh-TW': '學習', }, collapsed: true, autogenerate: { directory: 'learn' }, @@ -238,6 +250,7 @@ export default defineConfig({ label: 'Plugins', translations: { 'zh-CN': '插件', + 'zh-TW': '外掛', }, collapsed: true, autogenerate: { directory: 'plugin' }, @@ -246,6 +259,7 @@ export default defineConfig({ label: 'About', translations: { 'zh-CN': '关于', + 'zh-TW': '關於', }, collapsed: true, autogenerate: { directory: 'about' }, @@ -256,6 +270,7 @@ export default defineConfig({ label: 'References', translations: { 'zh-CN': '参考', + 'zh-TW': '參考', }, collapsed: true, items: [ @@ -263,6 +278,7 @@ export default defineConfig({ label: 'Security', translations: { 'zh-CN': '安全', + 'zh-TW': '安全', }, collapsed: true, autogenerate: { directory: 'reference/acl' }, @@ -271,6 +287,7 @@ export default defineConfig({ label: 'Command Line Interface', translations: { 'zh-CN': '命令行接口(CLI)', + 'zh-TW': '命令列介面(CLI)', }, link: '/reference/cli/', }, @@ -278,6 +295,7 @@ export default defineConfig({ label: 'Configuration', translations: { 'zh-CN': '配置', + 'zh-TW': '組態設置', }, link: '/reference/config/', }, @@ -285,6 +303,7 @@ export default defineConfig({ label: 'Environment Variables', translations: { 'zh-CN': '环境变量', + 'zh-TW': '環境變數', }, link: '/reference/environment-variables/', }, @@ -292,6 +311,7 @@ export default defineConfig({ label: 'Webview Versions', translations: { 'zh-CN': 'Webview 版本', + 'zh-TW': 'Webview 版本', }, link: '/reference/webview-versions/', }, @@ -299,6 +319,7 @@ export default defineConfig({ label: 'Releases', translations: { 'zh-CN': '发行版', + 'zh-TW': '發行版', }, collapsed: true, autogenerate: { directory: 'release' }, @@ -318,6 +339,7 @@ export default defineConfig({ label: 'Blog', translations: { 'zh-CN': '博客', + 'zh-TW': '部落格', }, collapsed: true, items: [ diff --git a/locales.json b/locales.json index b9898091be..321acba66e 100644 --- a/locales.json +++ b/locales.json @@ -15,6 +15,10 @@ "label": "简体中文", "lang": "zh-cn" }, + "zh-tw": { + "label": "繁體中文", + "lang": "zh-tw" + }, "ja": { "label": "日本語", "lang": "ja" diff --git a/lunaria/style.css b/lunaria/style.css index 16922bf534..92e6bc48bc 100644 --- a/lunaria/style.css +++ b/lunaria/style.css @@ -1,8 +1,9 @@ :root { color-scheme: dark; - --font-fallback: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, - Apple Color Emoji, Segoe UI Emoji; + --font-fallback: + -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, + Segoe UI Emoji; --font-body: system-ui, var(--font-fallback); --theme-accent: hsl(186, 100%, 87%); --theme-bg: hsl(186, 13%, 10%); diff --git a/makefile b/makefile new file mode 100644 index 0000000000..3a40655da2 --- /dev/null +++ b/makefile @@ -0,0 +1,45 @@ +# Makefile for Node.js project using pnpm + +NODE_ENV ?= development +PNPM = pnpm + +.PHONY: all dev build test format clean update serve help + +all: install + +install: + $(PNPM) install + +dev: + $(PNPM) run dev + +build: + $(PNPM) run build + +test: + $(PNPM) run test + +format: + $(PNPM) run format + +clean: + $(PNPM) store prune + rm -rf node_modules + rm -rf dist + +update: + $(PNPM) update + +serve: + $(PNPM) run start + +help: + @echo "Available Make targets:" + @echo " install - Install project dependencies" + @echo " dev - Start development server" + @echo " build - Build production version" + @echo " test - Run tests" + @echo " format - Run code formatting" + @echo " clean - Clean build artifacts" + @echo " update - Update dependencies" + @echo " serve - Start server" diff --git a/package.json b/package.json index 2aceea6fd8..6ea05efaa7 100644 --- a/package.json +++ b/package.json @@ -22,8 +22,8 @@ "preview": "astro preview" }, "dependencies": { - "@astrojs/markdown-remark": "^5.2.0", - "@astrojs/rss": "^4.0.7", + "@astrojs/markdown-remark": "^5.3.0", + "@astrojs/rss": "^4.0.11", "@astrojs/starlight": "0.29.2", "@lorenzo_lewis/starlight-utils": "^0.2.0", "@lunariajs/core": "^0.1.1", @@ -34,14 +34,14 @@ "astro-feelback": "^0.3.4", "astrojs-service-worker": "^2.0.0", "jsdom": "^26.0.0", - "prettier": "^3.2.5", - "prettier-plugin-astro": "^0.14.0", + "prettier": "^3.5.3", + "prettier-plugin-astro": "^0.14.1", "rehype-autolink-headings": "^7.1.0", - "sass": "^1.77.2", - "sharp": "^0.33.2", - "shiki": "^1.1.7", + "sass": "^1.86.0", + "sharp": "^0.33.5", + "shiki": "^1.29.2", "starlight-blog": "^0.15.0", - "starlight-links-validator": "^0.13.0" + "starlight-links-validator": "^0.13.4" }, "packageManager": "pnpm@10.6.2", "engines": { diff --git a/packages/tauri b/packages/tauri index 053b57c1df..5ae507af1b 160000 --- a/packages/tauri +++ b/packages/tauri @@ -1 +1 @@ -Subproject commit 053b57c1df1512c03b4c3bc89e91c4175606bf85 +Subproject commit 5ae507af1b5db6f1fa2a96c00da5a4658adfb765 diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e32af4db08..6cc8dfbc4a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -14,65 +14,65 @@ importers: .: dependencies: '@astrojs/markdown-remark': - specifier: ^5.2.0 + specifier: ^5.3.0 version: 5.3.0 '@astrojs/rss': - specifier: ^4.0.7 + specifier: ^4.0.11 version: 4.0.11 '@astrojs/starlight': specifier: 0.29.2 - version: 0.29.2(patch_hash=cce5b634885e07791c60f64102f8e7a74def815cdbc19d8aa069b9f4602f2890)(astro@4.16.18(@types/node@22.13.10)(rollup@2.79.1)(sass@1.83.4)(terser@5.31.0)(typescript@5.7.3)) + version: 0.29.2(patch_hash=cce5b634885e07791c60f64102f8e7a74def815cdbc19d8aa069b9f4602f2890)(astro@4.16.18(@types/node@22.13.13)(rollup@2.79.2)(sass@1.86.0)(terser@5.39.0)(typescript@5.7.3)) '@lorenzo_lewis/starlight-utils': specifier: ^0.2.0 - version: 0.2.0(@astrojs/starlight@0.29.2(patch_hash=cce5b634885e07791c60f64102f8e7a74def815cdbc19d8aa069b9f4602f2890)(astro@4.16.18(@types/node@22.13.10)(rollup@2.79.1)(sass@1.83.4)(terser@5.31.0)(typescript@5.7.3)))(astro@4.16.18(@types/node@22.13.10)(rollup@2.79.1)(sass@1.83.4)(terser@5.31.0)(typescript@5.7.3)) + version: 0.2.0(@astrojs/starlight@0.29.2(patch_hash=cce5b634885e07791c60f64102f8e7a74def815cdbc19d8aa069b9f4602f2890)(astro@4.16.18(@types/node@22.13.13)(rollup@2.79.2)(sass@1.86.0)(terser@5.39.0)(typescript@5.7.3)))(astro@4.16.18(@types/node@22.13.13)(rollup@2.79.2)(sass@1.86.0)(terser@5.39.0)(typescript@5.7.3)) '@lunariajs/core': specifier: ^0.1.1 version: 0.1.1 '@lunariajs/starlight': specifier: ^0.1.1 - version: 0.1.1(@astrojs/starlight@0.29.2(patch_hash=cce5b634885e07791c60f64102f8e7a74def815cdbc19d8aa069b9f4602f2890)(astro@4.16.18(@types/node@22.13.10)(rollup@2.79.1)(sass@1.83.4)(terser@5.31.0)(typescript@5.7.3)))(astro@4.16.18(@types/node@22.13.10)(rollup@2.79.1)(sass@1.83.4)(terser@5.31.0)(typescript@5.7.3)) + version: 0.1.1(@astrojs/starlight@0.29.2(patch_hash=cce5b634885e07791c60f64102f8e7a74def815cdbc19d8aa069b9f4602f2890)(astro@4.16.18(@types/node@22.13.13)(rollup@2.79.2)(sass@1.86.0)(terser@5.39.0)(typescript@5.7.3)))(astro@4.16.18(@types/node@22.13.13)(rollup@2.79.2)(sass@1.86.0)(terser@5.39.0)(typescript@5.7.3)) '@types/json-schema': specifier: ^7.0.15 version: 7.0.15 astro: specifier: ^4.16.18 - version: 4.16.18(@types/node@22.13.10)(rollup@2.79.1)(sass@1.83.4)(terser@5.31.0)(typescript@5.7.3) + version: 4.16.18(@types/node@22.13.13)(rollup@2.79.2)(sass@1.86.0)(terser@5.39.0)(typescript@5.7.3) astro-d2: specifier: ^0.6.0 - version: 0.6.0(astro@4.16.18(@types/node@22.13.10)(rollup@2.79.1)(sass@1.83.4)(terser@5.31.0)(typescript@5.7.3)) + version: 0.6.0(astro@4.16.18(@types/node@22.13.13)(rollup@2.79.2)(sass@1.86.0)(terser@5.39.0)(typescript@5.7.3)) astro-feelback: specifier: ^0.3.4 version: 0.3.4 astrojs-service-worker: specifier: ^2.0.0 - version: 2.0.0(@types/babel__core@7.20.5)(astro@4.16.18(@types/node@22.13.10)(rollup@2.79.1)(sass@1.83.4)(terser@5.31.0)(typescript@5.7.3)) + version: 2.0.0(@types/babel__core@7.20.5)(astro@4.16.18(@types/node@22.13.13)(rollup@2.79.2)(sass@1.86.0)(terser@5.39.0)(typescript@5.7.3)) jsdom: specifier: ^26.0.0 version: 26.0.0 prettier: - specifier: ^3.2.5 - version: 3.4.2 + specifier: ^3.5.3 + version: 3.5.3 prettier-plugin-astro: - specifier: ^0.14.0 + specifier: ^0.14.1 version: 0.14.1 rehype-autolink-headings: specifier: ^7.1.0 version: 7.1.0 sass: - specifier: ^1.77.2 - version: 1.83.4 + specifier: ^1.86.0 + version: 1.86.0 sharp: - specifier: ^0.33.2 + specifier: ^0.33.5 version: 0.33.5 shiki: - specifier: ^1.1.7 - version: 1.26.1 + specifier: ^1.29.2 + version: 1.29.2 starlight-blog: specifier: ^0.15.0 - version: 0.15.0(@astrojs/starlight@0.29.2(patch_hash=cce5b634885e07791c60f64102f8e7a74def815cdbc19d8aa069b9f4602f2890)(astro@4.16.18(@types/node@22.13.10)(rollup@2.79.1)(sass@1.83.4)(terser@5.31.0)(typescript@5.7.3)))(astro@4.16.18(@types/node@22.13.10)(rollup@2.79.1)(sass@1.83.4)(terser@5.31.0)(typescript@5.7.3)) + version: 0.15.0(@astrojs/starlight@0.29.2(patch_hash=cce5b634885e07791c60f64102f8e7a74def815cdbc19d8aa069b9f4602f2890)(astro@4.16.18(@types/node@22.13.13)(rollup@2.79.2)(sass@1.86.0)(terser@5.39.0)(typescript@5.7.3)))(astro@4.16.18(@types/node@22.13.13)(rollup@2.79.2)(sass@1.86.0)(terser@5.39.0)(typescript@5.7.3)) starlight-links-validator: - specifier: ^0.13.0 - version: 0.13.4(@astrojs/starlight@0.29.2(patch_hash=cce5b634885e07791c60f64102f8e7a74def815cdbc19d8aa069b9f4602f2890)(astro@4.16.18(@types/node@22.13.10)(rollup@2.79.1)(sass@1.83.4)(terser@5.31.0)(typescript@5.7.3)))(astro@4.16.18(@types/node@22.13.10)(rollup@2.79.1)(sass@1.83.4)(terser@5.31.0)(typescript@5.7.3)) + specifier: ^0.13.4 + version: 0.13.4(@astrojs/starlight@0.29.2(patch_hash=cce5b634885e07791c60f64102f8e7a74def815cdbc19d8aa069b9f4602f2890)(astro@4.16.18(@types/node@22.13.13)(rollup@2.79.2)(sass@1.86.0)(terser@5.39.0)(typescript@5.7.3)))(astro@4.16.18(@types/node@22.13.13)(rollup@2.79.2)(sass@1.86.0)(terser@5.39.0)(typescript@5.7.3)) packages/cli-generator: dependencies: @@ -167,11 +167,11 @@ packages: peerDependencies: ajv: '>=8' - '@asamuzakjp/css-color@2.8.2': - resolution: {integrity: sha512-RtWv9jFN2/bLExuZgFFZ0I3pWWeezAHGgrmjqGGWclATl1aDe3yhCUaI0Ilkp6OCk9zX7+FjvDasEX8Q9Rxc5w==} + '@asamuzakjp/css-color@3.1.1': + resolution: {integrity: sha512-hpRD68SV2OMcZCsrbdkccTw5FXjNDLo5OuqSHyHZfwweGsDWZwDJ2+gONyNAbazZclobMirACLw0lk8WVxIqxA==} - '@astrojs/compiler@2.10.3': - resolution: {integrity: sha512-bL/O7YBxsFt55YHU021oL+xz+B/9HvGNId3F9xURN16aeqDK9juHGktdkCSXz+U4nqFACq6ZFvWomOzhV+zfPw==} + '@astrojs/compiler@2.11.0': + resolution: {integrity: sha512-zZOO7i+JhojO8qmlyR/URui6LyfHJY6m+L9nwyX5GiKD78YoRaZ5tzz6X0fkl+5bD3uwlDHayf6Oe8Fu36RKNg==} '@astrojs/internal-helpers@0.4.1': resolution: {integrity: sha512-bMf9jFihO8YP940uD70SI/RDzIhUHJAolWVcO1v5PUivxGKvfLZTLTVVxEYzGYyPsA3ivdLNqMnL5VgmQySa+g==} @@ -195,8 +195,8 @@ packages: '@astrojs/rss@4.0.5': resolution: {integrity: sha512-IyJVL6z09AQtxbgLaAwebT3T5YKe4oTHDesqydJv1KLHw+zEzzMCFuuNsEyxjiqu7df9+DDCpDXLj/WRiEUXvw==} - '@astrojs/sitemap@3.1.6': - resolution: {integrity: sha512-1Qp2NvAzVImqA6y+LubKi1DVhve/hXXgFvB0szxiipzh7BvtuKe4oJJ9dXSqaubaTkt4nMa6dv6RCCAYeB6xaQ==} + '@astrojs/sitemap@3.3.0': + resolution: {integrity: sha512-nYE4lKQtk+Kbrw/w0G0TTgT724co0jUsU4tPlHY9au5HmTBKbwiCLwO/15b1/y13aZ4Kr9ZbMeMHlXuwn0ty4Q==} '@astrojs/starlight@0.29.2': resolution: {integrity: sha512-xv9AhWkP3fxCB6EF6MlT4yEbxzye3aMSbuVbFEGbQh8G/w1MPhdNCnQakIHpmIwwyxwG9cW3mQdAZum4oOO39w==} @@ -211,61 +211,45 @@ packages: resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==} engines: {node: '>=6.9.0'} - '@babel/compat-data@7.26.3': - resolution: {integrity: sha512-nHIxvKPniQXpmQLb0vhY3VaFb3S0YrTAwpOWJZh1wn3oJPjJk9Asva204PsBdmAE8vpzfHudT8DB0scYvy9q0g==} + '@babel/compat-data@7.26.8': + resolution: {integrity: sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==} engines: {node: '>=6.9.0'} - '@babel/core@7.26.0': - resolution: {integrity: sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==} + '@babel/core@7.26.10': + resolution: {integrity: sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==} engines: {node: '>=6.9.0'} - '@babel/generator@7.26.3': - resolution: {integrity: sha512-6FF/urZvD0sTeO7k6/B15pMLC4CHUv1426lzr3N01aHJTl046uCAh9LXW/fzeXXjPNCJ6iABW5XaWOsIZB93aQ==} + '@babel/generator@7.27.0': + resolution: {integrity: sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw==} engines: {node: '>=6.9.0'} '@babel/helper-annotate-as-pure@7.25.9': resolution: {integrity: sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==} engines: {node: '>=6.9.0'} - '@babel/helper-builder-binary-assignment-operator-visitor@7.22.15': - resolution: {integrity: sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw==} + '@babel/helper-compilation-targets@7.27.0': + resolution: {integrity: sha512-LVk7fbXml0H2xH34dFzKQ7TDZ2G4/rVTOrq9V+icbbadjbVxxeFeDsNHv2SrZeWoA+6ZiTyWYWtScEIW07EAcA==} engines: {node: '>=6.9.0'} - '@babel/helper-compilation-targets@7.25.9': - resolution: {integrity: sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ==} - engines: {node: '>=6.9.0'} - - '@babel/helper-create-class-features-plugin@7.24.5': - resolution: {integrity: sha512-uRc4Cv8UQWnE4NXlYTIIdM7wfFkOqlFztcC/gVXDKohKoVB3OyonfelUBaJzSwpBntZ2KYGF/9S7asCHsXwW6g==} + '@babel/helper-create-class-features-plugin@7.27.0': + resolution: {integrity: sha512-vSGCvMecvFCd/BdpGlhpXYNhhC4ccxyvQWpbGL4CWbvfEoLFWUZuSuf7s9Aw70flgQF+6vptvgK2IfOnKlRmBg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/helper-create-regexp-features-plugin@7.22.15': - resolution: {integrity: sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w==} + '@babel/helper-create-regexp-features-plugin@7.27.0': + resolution: {integrity: sha512-fO8l08T76v48BhpNRW/nQ0MxfnSdoSKUJBMjubOAYffsVuGG5qOfMq7N6Es7UJvi7Y8goXXo07EfcHZXDPuELQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/helper-define-polyfill-provider@0.6.2': - resolution: {integrity: sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==} + '@babel/helper-define-polyfill-provider@0.6.4': + resolution: {integrity: sha512-jljfR1rGnXXNWnmQg2K3+bvhkxB51Rl32QRaOTuwwjviGrHzIbSc8+x9CpraDtbT7mfyjXObULP4w/adunNwAw==} peerDependencies: '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 - '@babel/helper-environment-visitor@7.24.7': - resolution: {integrity: sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==} - engines: {node: '>=6.9.0'} - - '@babel/helper-function-name@7.24.7': - resolution: {integrity: sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA==} - engines: {node: '>=6.9.0'} - - '@babel/helper-hoist-variables@7.24.7': - resolution: {integrity: sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ==} - engines: {node: '>=6.9.0'} - - '@babel/helper-member-expression-to-functions@7.24.5': - resolution: {integrity: sha512-4owRteeihKWKamtqg4JmWSsEZU445xpFRXPEwp44HbgbxdWlUV1b4Agg4lkA806Lil5XM/e+FJyS0vj5T6vmcA==} + '@babel/helper-member-expression-to-functions@7.25.9': + resolution: {integrity: sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ==} engines: {node: '>=6.9.0'} '@babel/helper-module-imports@7.25.9': @@ -278,36 +262,28 @@ packages: peerDependencies: '@babel/core': ^7.0.0 - '@babel/helper-optimise-call-expression@7.22.5': - resolution: {integrity: sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==} + '@babel/helper-optimise-call-expression@7.25.9': + resolution: {integrity: sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ==} engines: {node: '>=6.9.0'} - '@babel/helper-plugin-utils@7.25.9': - resolution: {integrity: sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw==} + '@babel/helper-plugin-utils@7.26.5': + resolution: {integrity: sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==} engines: {node: '>=6.9.0'} - '@babel/helper-remap-async-to-generator@7.22.20': - resolution: {integrity: sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw==} + '@babel/helper-remap-async-to-generator@7.25.9': + resolution: {integrity: sha512-IZtukuUeBbhgOcaW2s06OXTzVNJR0ybm4W5xC1opWFFJMZbwRj5LCk+ByYH7WdZPZTt8KnFwA8pvjN2yqcPlgw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/helper-replace-supers@7.24.1': - resolution: {integrity: sha512-QCR1UqC9BzG5vZl8BMicmZ28RuUBnHhAMddD8yHFHDRH9lLTZ9uUPehX8ctVPT8l0TKblJidqcgUUKGVrePleQ==} + '@babel/helper-replace-supers@7.26.5': + resolution: {integrity: sha512-bJ6iIVdYX1YooY2X7w1q6VITt+LnUILtNk7zT78ykuwStx8BauCzxvFqFaHjOpW1bVnSUM1PN1f0p5P21wHxvg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/helper-simple-access@7.25.9': - resolution: {integrity: sha512-c6WHXuiaRsJTyHYLJV75t9IqsmTbItYfdj99PnzYGQZkYKvan5/2jKJ7gu31J3/BJ/A18grImSPModuyG/Eo0Q==} - engines: {node: '>=6.9.0'} - - '@babel/helper-skip-transparent-expression-wrappers@7.22.5': - resolution: {integrity: sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==} - engines: {node: '>=6.9.0'} - - '@babel/helper-split-export-declaration@7.24.7': - resolution: {integrity: sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==} + '@babel/helper-skip-transparent-expression-wrappers@7.25.9': + resolution: {integrity: sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA==} engines: {node: '>=6.9.0'} '@babel/helper-string-parser@7.25.9': @@ -322,39 +298,45 @@ packages: resolution: {integrity: sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==} engines: {node: '>=6.9.0'} - '@babel/helper-wrap-function@7.24.5': - resolution: {integrity: sha512-/xxzuNvgRl4/HLNKvnFwdhdgN3cpLxgLROeLDl83Yx0AJ1SGvq1ak0OszTOjDfiB8Vx03eJbeDWh9r+jCCWttw==} + '@babel/helper-wrap-function@7.25.9': + resolution: {integrity: sha512-ETzz9UTjQSTmw39GboatdymDq4XIQbR8ySgVrylRhPOFpsd+JrKHIuF0de7GCWmem+T4uC5z7EZguod7Wj4A4g==} engines: {node: '>=6.9.0'} - '@babel/helpers@7.26.0': - resolution: {integrity: sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==} + '@babel/helpers@7.27.0': + resolution: {integrity: sha512-U5eyP/CTFPuNE3qk+WZMxFkp/4zUzdceQlfzf7DdGdhp+Fezd7HD+i8Y24ZuTMKX3wQBld449jijbGq6OdGNQg==} engines: {node: '>=6.9.0'} - '@babel/parser@7.26.3': - resolution: {integrity: sha512-WJ/CvmY8Mea8iDXo6a7RK2wbmJITT5fN3BEkRuFlxVyNx8jOKIIhmC4fSkTcPcf8JyavbBwIe6OpiCOBXt/IcA==} + '@babel/parser@7.27.0': + resolution: {integrity: sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==} engines: {node: '>=6.0.0'} hasBin: true - '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.24.5': - resolution: {integrity: sha512-LdXRi1wEMTrHVR4Zc9F8OewC3vdm5h4QB6L71zy6StmYeqGi1b3ttIO8UC+BfZKcH9jdr4aI249rBkm+3+YvHw==} + '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.25.9': + resolution: {integrity: sha512-ZkRyVkThtxQ/J6nv3JFYv1RYY+JT5BvU0y3k5bWrmuG4woXypRa4PXmm9RhOwodRkYFWqC0C0cqcJ4OqR7kW+g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.25.9': + resolution: {integrity: sha512-MrGRLZxLD/Zjj0gdU15dfs+HH/OXvnw/U4jJD8vpcP2CJQapPEv1IWwjc/qMg7ItBlPwSv1hRBbb7LeuANdcnw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.24.1': - resolution: {integrity: sha512-y4HqEnkelJIOQGd+3g1bTeKsA5c6qM7eOn7VggGVbBc0y8MLSKHacwcIE2PplNlQSj0PqS9rrXL/nkPVK+kUNg==} + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.25.9': + resolution: {integrity: sha512-2qUwwfAFpJLZqxd02YW9btUCZHl+RFvdDkNfZwaIJrvB8Tesjsk8pEQkTvGwZXLqXUx/2oyY3ySRhm6HOXuCug==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.24.1': - resolution: {integrity: sha512-Hj791Ii4ci8HqnaKHAlLNs+zaLXb0EzSDhiAWp5VNlyvCNymYfacs64pxTxbH1znW/NcArSmwpmG9IKE/TUVVQ==} + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.25.9': + resolution: {integrity: sha512-6xWgLZTJXwilVjlnV7ospI3xi+sl8lN8rXXbBD6vYn3UYDlGsag8wrZkKcSI8G6KgqKP7vNFaDgeDnfAABq61g==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.13.0 - '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.24.1': - resolution: {integrity: sha512-m9m/fXsXLiHfwdgydIFnpk+7jlVbnvlK5B2EKiPdLUb6WX654ZaaEWJUjk8TftRbZpK0XibovlLWX4KIZhV6jw==} + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.25.9': + resolution: {integrity: sha512-aLnMXYPnzwwqhYSCyXfKkIkYgJ8zv9RK+roo9DkTXz38ynIhd9XCbN08s3MGvqL2MYGVUGdRQLL/JqBIeJhJBg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 @@ -365,326 +347,254 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-syntax-async-generators@7.8.4': - resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-class-properties@7.12.13': - resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-class-static-block@7.14.5': - resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-dynamic-import@7.8.3': - resolution: {integrity: sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-export-namespace-from@7.8.3': - resolution: {integrity: sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-import-assertions@7.24.1': - resolution: {integrity: sha512-IuwnI5XnuF189t91XbxmXeCDz3qs6iDRO7GJ++wcfgeXNs/8FmIlKcpDSXNVyuLQxlwvskmI3Ct73wUODkJBlQ==} + '@babel/plugin-syntax-import-assertions@7.26.0': + resolution: {integrity: sha512-QCWT5Hh830hK5EQa7XzuqIkQU9tT/whqbDz7kuaZMHFl1inRRg7JnuAEOQ0Ur0QUl0NufCk1msK2BeY79Aj/eg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-syntax-import-attributes@7.24.1': - resolution: {integrity: sha512-zhQTMH0X2nVLnb04tz+s7AMuasX8U0FnpE+nHTOhSOINjWMnopoZTxtIKsd45n4GQ/HIZLyfIpoul8e2m0DnRA==} + '@babel/plugin-syntax-import-attributes@7.26.0': + resolution: {integrity: sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-syntax-import-meta@7.10.4': - resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-json-strings@7.8.3': - resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} - peerDependencies: - '@babel/core': ^7.0.0-0 - '@babel/plugin-syntax-jsx@7.25.9': resolution: {integrity: sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-syntax-logical-assignment-operators@7.10.4': - resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3': - resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-numeric-separator@7.10.4': - resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-object-rest-spread@7.8.3': - resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-optional-catch-binding@7.8.3': - resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-optional-chaining@7.8.3': - resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-private-property-in-object@7.14.5': - resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-top-level-await@7.14.5': - resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - '@babel/plugin-syntax-unicode-sets-regex@7.18.6': resolution: {integrity: sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/plugin-transform-arrow-functions@7.24.1': - resolution: {integrity: sha512-ngT/3NkRhsaep9ck9uj2Xhv9+xB1zShY3tM3g6om4xxCELwCDN4g4Aq5dRn48+0hasAql7s2hdBOysCfNpr4fw==} + '@babel/plugin-transform-arrow-functions@7.25.9': + resolution: {integrity: sha512-6jmooXYIwn9ca5/RylZADJ+EnSxVUS5sjeJ9UPk6RWRzXCmOJCy6dqItPJFpw2cuCangPK4OYr5uhGKcmrm5Qg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-async-generator-functions@7.24.3': - resolution: {integrity: sha512-Qe26CMYVjpQxJ8zxM1340JFNjZaF+ISWpr1Kt/jGo+ZTUzKkfw/pphEWbRCb+lmSM6k/TOgfYLvmbHkUQ0asIg==} + '@babel/plugin-transform-async-generator-functions@7.26.8': + resolution: {integrity: sha512-He9Ej2X7tNf2zdKMAGOsmg2MrFc+hfoAhd3po4cWfo/NWjzEAKa0oQruj1ROVUdl0e6fb6/kE/G3SSxE0lRJOg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-async-to-generator@7.24.1': - resolution: {integrity: sha512-AawPptitRXp1y0n4ilKcGbRYWfbbzFWz2NqNu7dacYDtFtz0CMjG64b3LQsb3KIgnf4/obcUL78hfaOS7iCUfw==} + '@babel/plugin-transform-async-to-generator@7.25.9': + resolution: {integrity: sha512-NT7Ejn7Z/LjUH0Gv5KsBCxh7BH3fbLTV0ptHvpeMvrt3cPThHfJfst9Wrb7S8EvJ7vRTFI7z+VAvFVEQn/m5zQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-block-scoped-functions@7.24.1': - resolution: {integrity: sha512-TWWC18OShZutrv9C6mye1xwtam+uNi2bnTOCBUd5sZxyHOiWbU6ztSROofIMrK84uweEZC219POICK/sTYwfgg==} + '@babel/plugin-transform-block-scoped-functions@7.26.5': + resolution: {integrity: sha512-chuTSY+hq09+/f5lMj8ZSYgCFpppV2CbYrhNFJ1BFoXpiWPnnAb7R0MqrafCpN8E1+YRrtM1MXZHJdIx8B6rMQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-block-scoping@7.24.5': - resolution: {integrity: sha512-sMfBc3OxghjC95BkYrYocHL3NaOplrcaunblzwXhGmlPwpmfsxr4vK+mBBt49r+S240vahmv+kUxkeKgs+haCw==} + '@babel/plugin-transform-block-scoping@7.27.0': + resolution: {integrity: sha512-u1jGphZ8uDI2Pj/HJj6YQ6XQLZCNjOlprjxB5SVz6rq2T6SwAR+CdrWK0CP7F+9rDVMXdB0+r6Am5G5aobOjAQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-class-properties@7.24.1': - resolution: {integrity: sha512-OMLCXi0NqvJfORTaPQBwqLXHhb93wkBKZ4aNwMl6WtehO7ar+cmp+89iPEQPqxAnxsOKTaMcs3POz3rKayJ72g==} + '@babel/plugin-transform-class-properties@7.25.9': + resolution: {integrity: sha512-bbMAII8GRSkcd0h0b4X+36GksxuheLFjP65ul9w6C3KgAamI3JqErNgSrosX6ZPj+Mpim5VvEbawXxJCyEUV3Q==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-class-static-block@7.24.4': - resolution: {integrity: sha512-B8q7Pz870Hz/q9UgP8InNpY01CSLDSCyqX7zcRuv3FcPl87A2G17lASroHWaCtbdIcbYzOZ7kWmXFKbijMSmFg==} + '@babel/plugin-transform-class-static-block@7.26.0': + resolution: {integrity: sha512-6J2APTs7BDDm+UMqP1useWqhcRAXo0WIoVj26N7kPFB6S73Lgvyka4KTZYIxtgYXiN5HTyRObA72N2iu628iTQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.12.0 - '@babel/plugin-transform-classes@7.24.5': - resolution: {integrity: sha512-gWkLP25DFj2dwe9Ck8uwMOpko4YsqyfZJrOmqqcegeDYEbp7rmn4U6UQZNj08UF6MaX39XenSpKRCvpDRBtZ7Q==} + '@babel/plugin-transform-classes@7.25.9': + resolution: {integrity: sha512-mD8APIXmseE7oZvZgGABDyM34GUmK45Um2TXiBUt7PnuAxrgoSVf123qUzPxEr/+/BHrRn5NMZCdE2m/1F8DGg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-computed-properties@7.24.1': - resolution: {integrity: sha512-5pJGVIUfJpOS+pAqBQd+QMaTD2vCL/HcePooON6pDpHgRp4gNRmzyHTPIkXntwKsq3ayUFVfJaIKPw2pOkOcTw==} + '@babel/plugin-transform-computed-properties@7.25.9': + resolution: {integrity: sha512-HnBegGqXZR12xbcTHlJ9HGxw1OniltT26J5YpfruGqtUHlz/xKf/G2ak9e+t0rVqrjXa9WOhvYPz1ERfMj23AA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-destructuring@7.24.5': - resolution: {integrity: sha512-SZuuLyfxvsm+Ah57I/i1HVjveBENYK9ue8MJ7qkc7ndoNjqquJiElzA7f5yaAXjyW2hKojosOTAQQRX50bPSVg==} + '@babel/plugin-transform-destructuring@7.25.9': + resolution: {integrity: sha512-WkCGb/3ZxXepmMiX101nnGiU+1CAdut8oHyEOHxkKuS1qKpU2SMXE2uSvfz8PBuLd49V6LEsbtyPhWC7fnkgvQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-dotall-regex@7.24.1': - resolution: {integrity: sha512-p7uUxgSoZwZ2lPNMzUkqCts3xlp8n+o05ikjy7gbtFJSt9gdU88jAmtfmOxHM14noQXBxfgzf2yRWECiNVhTCw==} + '@babel/plugin-transform-dotall-regex@7.25.9': + resolution: {integrity: sha512-t7ZQ7g5trIgSRYhI9pIJtRl64KHotutUJsh4Eze5l7olJv+mRSg4/MmbZ0tv1eeqRbdvo/+trvJD/Oc5DmW2cA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-duplicate-keys@7.24.1': - resolution: {integrity: sha512-msyzuUnvsjsaSaocV6L7ErfNsa5nDWL1XKNnDePLgmz+WdU4w/J8+AxBMrWfi9m4IxfL5sZQKUPQKDQeeAT6lA==} + '@babel/plugin-transform-duplicate-keys@7.25.9': + resolution: {integrity: sha512-LZxhJ6dvBb/f3x8xwWIuyiAHy56nrRG3PeYTpBkkzkYRRQ6tJLu68lEF5VIqMUZiAV7a8+Tb78nEoMCMcqjXBw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-dynamic-import@7.24.1': - resolution: {integrity: sha512-av2gdSTyXcJVdI+8aFZsCAtR29xJt0S5tas+Ef8NvBNmD1a+N/3ecMLeMBgfcK+xzsjdLDT6oHt+DFPyeqUbDA==} + '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.25.9': + resolution: {integrity: sha512-0UfuJS0EsXbRvKnwcLjFtJy/Sxc5J5jhLHnFhy7u4zih97Hz6tJkLU+O+FMMrNZrosUPxDi6sYxJ/EA8jDiAog==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-transform-dynamic-import@7.25.9': + resolution: {integrity: sha512-GCggjexbmSLaFhqsojeugBpeaRIgWNTcgKVq/0qIteFEqY2A+b9QidYadrWlnbWQUrW5fn+mCvf3tr7OeBFTyg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-exponentiation-operator@7.24.1': - resolution: {integrity: sha512-U1yX13dVBSwS23DEAqU+Z/PkwE9/m7QQy8Y9/+Tdb8UWYaGNDYwTLi19wqIAiROr8sXVum9A/rtiH5H0boUcTw==} + '@babel/plugin-transform-exponentiation-operator@7.26.3': + resolution: {integrity: sha512-7CAHcQ58z2chuXPWblnn1K6rLDnDWieghSOEmqQsrBenH0P9InCUtOJYD89pvngljmZlJcz3fcmgYsXFNGa1ZQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-export-namespace-from@7.24.1': - resolution: {integrity: sha512-Ft38m/KFOyzKw2UaJFkWG9QnHPG/Q/2SkOrRk4pNBPg5IPZ+dOxcmkK5IyuBcxiNPyyYowPGUReyBvrvZs7IlQ==} + '@babel/plugin-transform-export-namespace-from@7.25.9': + resolution: {integrity: sha512-2NsEz+CxzJIVOPx2o9UsW1rXLqtChtLoVnwYHHiB04wS5sgn7mrV45fWMBX0Kk+ub9uXytVYfNP2HjbVbCB3Ww==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-for-of@7.24.1': - resolution: {integrity: sha512-OxBdcnF04bpdQdR3i4giHZNZQn7cm8RQKcSwA17wAAqEELo1ZOwp5FFgeptWUQXFyT9kwHo10aqqauYkRZPCAg==} + '@babel/plugin-transform-for-of@7.26.9': + resolution: {integrity: sha512-Hry8AusVm8LW5BVFgiyUReuoGzPUpdHQQqJY5bZnbbf+ngOHWuCuYFKw/BqaaWlvEUrF91HMhDtEaI1hZzNbLg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-function-name@7.24.1': - resolution: {integrity: sha512-BXmDZpPlh7jwicKArQASrj8n22/w6iymRnvHYYd2zO30DbE277JO20/7yXJT3QxDPtiQiOxQBbZH4TpivNXIxA==} + '@babel/plugin-transform-function-name@7.25.9': + resolution: {integrity: sha512-8lP+Yxjv14Vc5MuWBpJsoUCd3hD6V9DgBon2FVYL4jJgbnVQ9fTgYmonchzZJOVNgzEgbxp4OwAf6xz6M/14XA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-json-strings@7.24.1': - resolution: {integrity: sha512-U7RMFmRvoasscrIFy5xA4gIp8iWnWubnKkKuUGJjsuOH7GfbMkB+XZzeslx2kLdEGdOJDamEmCqOks6e8nv8DQ==} + '@babel/plugin-transform-json-strings@7.25.9': + resolution: {integrity: sha512-xoTMk0WXceiiIvsaquQQUaLLXSW1KJ159KP87VilruQm0LNNGxWzahxSS6T6i4Zg3ezp4vA4zuwiNUR53qmQAw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-literals@7.24.1': - resolution: {integrity: sha512-zn9pwz8U7nCqOYIiBaOxoQOtYmMODXTJnkxG4AtX8fPmnCRYWBOHD0qcpwS9e2VDSp1zNJYpdnFMIKb8jmwu6g==} + '@babel/plugin-transform-literals@7.25.9': + resolution: {integrity: sha512-9N7+2lFziW8W9pBl2TzaNht3+pgMIRP74zizeCSrtnSKVdUl8mAjjOP2OOVQAfZ881P2cNjDj1uAMEdeD50nuQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-logical-assignment-operators@7.24.1': - resolution: {integrity: sha512-OhN6J4Bpz+hIBqItTeWJujDOfNP+unqv/NJgyhlpSqgBTPm37KkMmZV6SYcOj+pnDbdcl1qRGV/ZiIjX9Iy34w==} + '@babel/plugin-transform-logical-assignment-operators@7.25.9': + resolution: {integrity: sha512-wI4wRAzGko551Y8eVf6iOY9EouIDTtPb0ByZx+ktDGHwv6bHFimrgJM/2T021txPZ2s4c7bqvHbd+vXG6K948Q==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-member-expression-literals@7.24.1': - resolution: {integrity: sha512-4ojai0KysTWXzHseJKa1XPNXKRbuUrhkOPY4rEGeR+7ChlJVKxFa3H3Bz+7tWaGKgJAXUWKOGmltN+u9B3+CVg==} + '@babel/plugin-transform-member-expression-literals@7.25.9': + resolution: {integrity: sha512-PYazBVfofCQkkMzh2P6IdIUaCEWni3iYEerAsRWuVd8+jlM1S9S9cz1dF9hIzyoZ8IA3+OwVYIp9v9e+GbgZhA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-modules-amd@7.24.1': - resolution: {integrity: sha512-lAxNHi4HVtjnHd5Rxg3D5t99Xm6H7b04hUS7EHIXcUl2EV4yl1gWdqZrNzXnSrHveL9qMdbODlLF55mvgjAfaQ==} + '@babel/plugin-transform-modules-amd@7.25.9': + resolution: {integrity: sha512-g5T11tnI36jVClQlMlt4qKDLlWnG5pP9CSM4GhdRciTNMRgkfpo5cR6b4rGIOYPgRRuFAvwjPQ/Yk+ql4dyhbw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-modules-commonjs@7.24.1': - resolution: {integrity: sha512-szog8fFTUxBfw0b98gEWPaEqF42ZUD/T3bkynW/wtgx2p/XCP55WEsb+VosKceRSd6njipdZvNogqdtI4Q0chw==} + '@babel/plugin-transform-modules-commonjs@7.26.3': + resolution: {integrity: sha512-MgR55l4q9KddUDITEzEFYn5ZsGDXMSsU9E+kh7fjRXTIC3RHqfCo8RPRbyReYJh44HQ/yomFkqbOFohXvDCiIQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-modules-systemjs@7.24.1': - resolution: {integrity: sha512-mqQ3Zh9vFO1Tpmlt8QPnbwGHzNz3lpNEMxQb1kAemn/erstyqw1r9KeOlOfo3y6xAnFEcOv2tSyrXfmMk+/YZA==} + '@babel/plugin-transform-modules-systemjs@7.25.9': + resolution: {integrity: sha512-hyss7iIlH/zLHaehT+xwiymtPOpsiwIIRlCAOwBB04ta5Tt+lNItADdlXw3jAWZ96VJ2jlhl/c+PNIQPKNfvcA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-modules-umd@7.24.1': - resolution: {integrity: sha512-tuA3lpPj+5ITfcCluy6nWonSL7RvaG0AOTeAuvXqEKS34lnLzXpDb0dcP6K8jD0zWZFNDVly90AGFJPnm4fOYg==} + '@babel/plugin-transform-modules-umd@7.25.9': + resolution: {integrity: sha512-bS9MVObUgE7ww36HEfwe6g9WakQ0KF07mQF74uuXdkoziUPfKyu/nIm663kz//e5O1nPInPFx36z7WJmJ4yNEw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-named-capturing-groups-regex@7.22.5': - resolution: {integrity: sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ==} + '@babel/plugin-transform-named-capturing-groups-regex@7.25.9': + resolution: {integrity: sha512-oqB6WHdKTGl3q/ItQhpLSnWWOpjUJLsOCLVyeFgeTktkBSCiurvPOsyt93gibI9CmuKvTUEtWmG5VhZD+5T/KA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/plugin-transform-new-target@7.24.1': - resolution: {integrity: sha512-/rurytBM34hYy0HKZQyA0nHbQgQNFm4Q/BOc9Hflxi2X3twRof7NaE5W46j4kQitm7SvACVRXsa6N/tSZxvPug==} + '@babel/plugin-transform-new-target@7.25.9': + resolution: {integrity: sha512-U/3p8X1yCSoKyUj2eOBIx3FOn6pElFOKvAAGf8HTtItuPyB+ZeOqfn+mvTtg9ZlOAjsPdK3ayQEjqHjU/yLeVQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-nullish-coalescing-operator@7.24.1': - resolution: {integrity: sha512-iQ+caew8wRrhCikO5DrUYx0mrmdhkaELgFa+7baMcVuhxIkN7oxt06CZ51D65ugIb1UWRQ8oQe+HXAVM6qHFjw==} + '@babel/plugin-transform-nullish-coalescing-operator@7.26.6': + resolution: {integrity: sha512-CKW8Vu+uUZneQCPtXmSBUC6NCAUdya26hWCElAWh5mVSlSRsmiCPUUDKb3Z0szng1hiAJa098Hkhg9o4SE35Qw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-numeric-separator@7.24.1': - resolution: {integrity: sha512-7GAsGlK4cNL2OExJH1DzmDeKnRv/LXq0eLUSvudrehVA5Rgg4bIrqEUW29FbKMBRT0ztSqisv7kjP+XIC4ZMNw==} + '@babel/plugin-transform-numeric-separator@7.25.9': + resolution: {integrity: sha512-TlprrJ1GBZ3r6s96Yq8gEQv82s8/5HnCVHtEJScUj90thHQbwe+E5MLhi2bbNHBEJuzrvltXSru+BUxHDoog7Q==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-object-rest-spread@7.24.5': - resolution: {integrity: sha512-7EauQHszLGM3ay7a161tTQH7fj+3vVM/gThlz5HpFtnygTxjrlvoeq7MPVA1Vy9Q555OB8SnAOsMkLShNkkrHA==} + '@babel/plugin-transform-object-rest-spread@7.25.9': + resolution: {integrity: sha512-fSaXafEE9CVHPweLYw4J0emp1t8zYTXyzN3UuG+lylqkvYd7RMrsOQ8TYx5RF231be0vqtFC6jnx3UmpJmKBYg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-object-super@7.24.1': - resolution: {integrity: sha512-oKJqR3TeI5hSLRxudMjFQ9re9fBVUU0GICqM3J1mi8MqlhVr6hC/ZN4ttAyMuQR6EZZIY6h/exe5swqGNNIkWQ==} + '@babel/plugin-transform-object-super@7.25.9': + resolution: {integrity: sha512-Kj/Gh+Rw2RNLbCK1VAWj2U48yxxqL2x0k10nPtSdRa0O2xnHXalD0s+o1A6a0W43gJ00ANo38jxkQreckOzv5A==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-optional-catch-binding@7.24.1': - resolution: {integrity: sha512-oBTH7oURV4Y+3EUrf6cWn1OHio3qG/PVwO5J03iSJmBg6m2EhKjkAu/xuaXaYwWW9miYtvbWv4LNf0AmR43LUA==} + '@babel/plugin-transform-optional-catch-binding@7.25.9': + resolution: {integrity: sha512-qM/6m6hQZzDcZF3onzIhZeDHDO43bkNNlOX0i8n3lR6zLbu0GN2d8qfM/IERJZYauhAHSLHy39NF0Ctdvcid7g==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-optional-chaining@7.24.5': - resolution: {integrity: sha512-xWCkmwKT+ihmA6l7SSTpk8e4qQl/274iNbSKRRS8mpqFR32ksy36+a+LWY8OXCCEefF8WFlnOHVsaDI2231wBg==} + '@babel/plugin-transform-optional-chaining@7.25.9': + resolution: {integrity: sha512-6AvV0FsLULbpnXeBjrY4dmWF8F7gf8QnvTEoO/wX/5xm/xE1Xo8oPuD3MPS+KS9f9XBEAWN7X1aWr4z9HdOr7A==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-parameters@7.24.5': - resolution: {integrity: sha512-9Co00MqZ2aoky+4j2jhofErthm6QVLKbpQrvz20c3CH9KQCLHyNB+t2ya4/UrRpQGR+Wrwjg9foopoeSdnHOkA==} + '@babel/plugin-transform-parameters@7.25.9': + resolution: {integrity: sha512-wzz6MKwpnshBAiRmn4jR8LYz/g8Ksg0o80XmwZDlordjwEk9SxBzTWC7F5ef1jhbrbOW2DJ5J6ayRukrJmnr0g==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-private-methods@7.24.1': - resolution: {integrity: sha512-tGvisebwBO5em4PaYNqt4fkw56K2VALsAbAakY0FjTYqJp7gfdrgr7YX76Or8/cpik0W6+tj3rZ0uHU9Oil4tw==} + '@babel/plugin-transform-private-methods@7.25.9': + resolution: {integrity: sha512-D/JUozNpQLAPUVusvqMxyvjzllRaF8/nSrP1s2YGQT/W4LHK4xxsMcHjhOGTS01mp9Hda8nswb+FblLdJornQw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-private-property-in-object@7.24.5': - resolution: {integrity: sha512-JM4MHZqnWR04jPMujQDTBVRnqxpLLpx2tkn7iPn+Hmsc0Gnb79yvRWOkvqFOx3Z7P7VxiRIR22c4eGSNj87OBQ==} + '@babel/plugin-transform-private-property-in-object@7.25.9': + resolution: {integrity: sha512-Evf3kcMqzXA3xfYJmZ9Pg1OvKdtqsDMSWBDzZOPLvHiTt36E75jLDQo5w1gtRU95Q4E5PDttrTf25Fw8d/uWLw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-property-literals@7.24.1': - resolution: {integrity: sha512-LetvD7CrHmEx0G442gOomRr66d7q8HzzGGr4PMHGr+5YIm6++Yke+jxj246rpvsbyhJwCLxcTn6zW1P1BSenqA==} + '@babel/plugin-transform-property-literals@7.25.9': + resolution: {integrity: sha512-IvIUeV5KrS/VPavfSM/Iu+RE6llrHrYIKY1yfCzyO/lMXHQ+p7uGhonmGVisv6tSBSVgWzMBohTcvkC9vQcQFA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -695,74 +605,80 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-regenerator@7.24.1': - resolution: {integrity: sha512-sJwZBCzIBE4t+5Q4IGLaaun5ExVMRY0lYwos/jNecjMrVCygCdph3IKv0tkP5Fc87e/1+bebAmEAGBfnRD+cnw==} + '@babel/plugin-transform-regenerator@7.27.0': + resolution: {integrity: sha512-LX/vCajUJQDqE7Aum/ELUMZAY19+cDpghxrnyt5I1tV6X5PyC86AOoWXWFYFeIvauyeSA6/ktn4tQVn/3ZifsA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-reserved-words@7.24.1': - resolution: {integrity: sha512-JAclqStUfIwKN15HrsQADFgeZt+wexNQ0uLhuqvqAUFoqPMjEcFCYZBhq0LUdz6dZK/mD+rErhW71fbx8RYElg==} + '@babel/plugin-transform-regexp-modifiers@7.26.0': + resolution: {integrity: sha512-vN6saax7lrA2yA/Pak3sCxuD6F5InBjn9IcrIKQPjpsLvuHYLVroTxjdlVRHjjBWxKOqIwpTXDkOssYT4BFdRw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-transform-reserved-words@7.25.9': + resolution: {integrity: sha512-7DL7DKYjn5Su++4RXu8puKZm2XBPHyjWLUidaPEkCUBbE7IPcsrkRHggAOOKydH1dASWdcUBxrkOGNxUv5P3Jg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-shorthand-properties@7.24.1': - resolution: {integrity: sha512-LyjVB1nsJ6gTTUKRjRWx9C1s9hE7dLfP/knKdrfeH9UPtAGjYGgxIbFfx7xyLIEWs7Xe1Gnf8EWiUqfjLhInZA==} + '@babel/plugin-transform-shorthand-properties@7.25.9': + resolution: {integrity: sha512-MUv6t0FhO5qHnS/W8XCbHmiRWOphNufpE1IVxhK5kuN3Td9FT1x4rx4K42s3RYdMXCXpfWkGSbCSd0Z64xA7Ng==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-spread@7.24.1': - resolution: {integrity: sha512-KjmcIM+fxgY+KxPVbjelJC6hrH1CgtPmTvdXAfn3/a9CnWGSTY7nH4zm5+cjmWJybdcPSsD0++QssDsjcpe47g==} + '@babel/plugin-transform-spread@7.25.9': + resolution: {integrity: sha512-oNknIB0TbURU5pqJFVbOOFspVlrpVwo2H1+HUIsVDvp5VauGGDP1ZEvO8Nn5xyMEs3dakajOxlmkNW7kNgSm6A==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-sticky-regex@7.24.1': - resolution: {integrity: sha512-9v0f1bRXgPVcPrngOQvLXeGNNVLc8UjMVfebo9ka0WF3/7+aVUHmaJVT3sa0XCzEFioPfPHZiOcYG9qOsH63cw==} + '@babel/plugin-transform-sticky-regex@7.25.9': + resolution: {integrity: sha512-WqBUSgeVwucYDP9U/xNRQam7xV8W5Zf+6Eo7T2SRVUFlhRiMNFdFz58u0KZmCVVqs2i7SHgpRnAhzRNmKfi2uA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-template-literals@7.24.1': - resolution: {integrity: sha512-WRkhROsNzriarqECASCNu/nojeXCDTE/F2HmRgOzi7NGvyfYGq1NEjKBK3ckLfRgGc6/lPAqP0vDOSw3YtG34g==} + '@babel/plugin-transform-template-literals@7.26.8': + resolution: {integrity: sha512-OmGDL5/J0CJPJZTHZbi2XpO0tyT2Ia7fzpW5GURwdtp2X3fMmN8au/ej6peC/T33/+CRiIpA8Krse8hFGVmT5Q==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-typeof-symbol@7.24.5': - resolution: {integrity: sha512-UTGnhYVZtTAjdwOTzT+sCyXmTn8AhaxOS/MjG9REclZ6ULHWF9KoCZur0HSGU7hk8PdBFKKbYe6+gqdXWz84Jg==} + '@babel/plugin-transform-typeof-symbol@7.27.0': + resolution: {integrity: sha512-+LLkxA9rKJpNoGsbLnAgOCdESl73vwYn+V6b+5wHbrE7OGKVDPHIQvbFSzqE6rwqaCw2RE+zdJrlLkcf8YOA0w==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-unicode-escapes@7.24.1': - resolution: {integrity: sha512-RlkVIcWT4TLI96zM660S877E7beKlQw7Ig+wqkKBiWfj0zH5Q4h50q6er4wzZKRNSYpfo6ILJ+hrJAGSX2qcNw==} + '@babel/plugin-transform-unicode-escapes@7.25.9': + resolution: {integrity: sha512-s5EDrE6bW97LtxOcGj1Khcx5AaXwiMmi4toFWRDP9/y0Woo6pXC+iyPu/KuhKtfSrNFd7jJB+/fkOtZy6aIC6Q==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-unicode-property-regex@7.24.1': - resolution: {integrity: sha512-Ss4VvlfYV5huWApFsF8/Sq0oXnGO+jB+rijFEFugTd3cwSObUSnUi88djgR5528Csl0uKlrI331kRqe56Ov2Ng==} + '@babel/plugin-transform-unicode-property-regex@7.25.9': + resolution: {integrity: sha512-Jt2d8Ga+QwRluxRQ307Vlxa6dMrYEMZCgGxoPR8V52rxPyldHu3hdlHspxaqYmE7oID5+kB+UKUB/eWS+DkkWg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-unicode-regex@7.24.1': - resolution: {integrity: sha512-2A/94wgZgxfTsiLaQ2E36XAOdcZmGAaEEgVmxQWwZXWkGhvoHbaqXcKnU8zny4ycpu3vNqg0L/PcCiYtHtA13g==} + '@babel/plugin-transform-unicode-regex@7.25.9': + resolution: {integrity: sha512-yoxstj7Rg9dlNn9UQxzk4fcNivwv4nUYz7fYXBaKxvw/lnmPuOm/ikoELygbYq68Bls3D/D+NBPHiLwZdZZ4HA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-unicode-sets-regex@7.24.1': - resolution: {integrity: sha512-fqj4WuzzS+ukpgerpAoOnMfQXwUHFxXUZUE84oL2Kao2N8uSlvcpnAidKASgsNgzZHBsHWvcm8s9FPWUhAb8fA==} + '@babel/plugin-transform-unicode-sets-regex@7.25.9': + resolution: {integrity: sha512-8BYqO3GeVNHtx69fdPshN3fnzUNLrWdHhk/icSwigksJGczKSizZ+Z6SBCxTs723Fr5VSNorTIK7a+R2tISvwQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/preset-env@7.24.5': - resolution: {integrity: sha512-UGK2ifKtcC8i5AI4cH+sbLLuLc2ktYSFJgBAXorKAsHUZmrQ1q6aQ6i3BvU24wWs2AAKqQB6kq3N9V9Gw1HiMQ==} + '@babel/preset-env@7.26.9': + resolution: {integrity: sha512-vX3qPGE8sEKEAZCWk05k3cpTAE3/nOYca++JA+Rd0z2NCNzabmYvEiSShKzm10zdquOIAVXsy2Ei/DTW34KlKQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -772,41 +688,38 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 || ^8.0.0-0 <8.0.0 - '@babel/regjsgen@0.8.0': - resolution: {integrity: sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==} - - '@babel/runtime@7.25.6': - resolution: {integrity: sha512-VBj9MYyDb9tuLq7yzqjgzt6Q+IBQLrGZfdjOekyEirZPHxXWoTSGUTMrpsfi58Up73d13NfYLv8HT9vmznjzhQ==} + '@babel/runtime@7.27.0': + resolution: {integrity: sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw==} engines: {node: '>=6.9.0'} - '@babel/template@7.25.9': - resolution: {integrity: sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==} + '@babel/template@7.27.0': + resolution: {integrity: sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA==} engines: {node: '>=6.9.0'} - '@babel/traverse@7.26.3': - resolution: {integrity: sha512-yTmc8J+Sj8yLzwr4PD5Xb/WF3bOYu2C2OoSZPzbuqRm4n98XirsbzaX+GloeO376UnSYIYJ4NCanwV5/ugZkwA==} + '@babel/traverse@7.27.0': + resolution: {integrity: sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA==} engines: {node: '>=6.9.0'} - '@babel/types@7.26.3': - resolution: {integrity: sha512-vN5p+1kl59GVKMvTHt55NzzmYVxprfJD+ql7U9NFIfKCBkYE55LYtS+WtPlaYOyzydrKI8Nezd+aZextrd+FMA==} + '@babel/types@7.27.0': + resolution: {integrity: sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==} engines: {node: '>=6.9.0'} - '@clack/core@0.3.4': - resolution: {integrity: sha512-H4hxZDXgHtWTwV3RAVenqcC4VbJZNegbBjlPvzOzCouXtS2y3sDvlO3IsbrPNWuLWPPlYVYPghQdSF64683Ldw==} + '@clack/core@0.3.5': + resolution: {integrity: sha512-5cfhQNH+1VQ2xLQlmzXMqUoiaH0lRBq9/CLW9lTyMbuKLC3+xEK01tHVvyut++mLOn5urSHmkm6I0Lg9MaJSTQ==} - '@csstools/color-helpers@5.0.1': - resolution: {integrity: sha512-MKtmkA0BX87PKaO1NFRTFH+UnkgnmySQOvNxJubsadusqPEC2aJ9MOQiMceZJJ6oitUl/i0L6u0M1IrmAOmgBA==} + '@csstools/color-helpers@5.0.2': + resolution: {integrity: sha512-JqWH1vsgdGcw2RR6VliXXdA0/59LttzlU8UlRT/iUUsEeWfYq8I+K0yhihEUTTHLRm1EXvpsCx3083EU15ecsA==} engines: {node: '>=18'} - '@csstools/css-calc@2.1.1': - resolution: {integrity: sha512-rL7kaUnTkL9K+Cvo2pnCieqNpTKgQzy5f+N+5Iuko9HAoasP+xgprVh7KN/MaJVvVL1l0EzQq2MoqBHKSrDrag==} + '@csstools/css-calc@2.1.2': + resolution: {integrity: sha512-TklMyb3uBB28b5uQdxjReG4L80NxAqgrECqLZFQbyLekwwlcDDS8r3f07DKqeo8C4926Br0gf/ZDe17Zv4wIuw==} engines: {node: '>=18'} peerDependencies: '@csstools/css-parser-algorithms': ^3.0.4 '@csstools/css-tokenizer': ^3.0.3 - '@csstools/css-color-parser@3.0.7': - resolution: {integrity: sha512-nkMp2mTICw32uE5NN+EsJ4f5N+IGFeCFu4bGpiKgb2Pq/7J/MpyLBeQ5ry4KKtRFZaYs6sTmcMYrSRIyj5DFKA==} + '@csstools/css-color-parser@3.0.8': + resolution: {integrity: sha512-pdwotQjCCnRPuNi06jFuP68cykU1f3ZWExLe/8MQ1LOs8Xq+fTkYgd+2V8mWUWMrOn9iS2HftPVaMZDaXzGbhQ==} engines: {node: '>=18'} peerDependencies: '@csstools/css-parser-algorithms': ^3.0.4 @@ -826,8 +739,8 @@ packages: resolution: {integrity: sha512-WyOx8cJQ+FQus4Mm4uPIZA64gbk3Wxh0so5Lcii0aJifqwoVOlfFtorjLE0Hen4OYyHZMXDWqMmaQemBhgxFRQ==} engines: {node: '>=14'} - '@emnapi/runtime@1.2.0': - resolution: {integrity: sha512-bV21/9LQmcQeCPEg3BDFtvwL6cwiTMksYNWQQ4KOxCZikEGalWtenoZ0wCiukJINlGCIi2KXx01g4FoH/LxpzQ==} + '@emnapi/runtime@1.3.1': + resolution: {integrity: sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw==} '@esbuild/aix-ppc64@0.21.5': resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} @@ -1102,8 +1015,8 @@ packages: cpu: [x64] os: [win32] - '@jridgewell/gen-mapping@0.3.5': - resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} + '@jridgewell/gen-mapping@0.3.8': + resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==} engines: {node: '>=6.0.0'} '@jridgewell/resolve-uri@3.1.2': @@ -1165,31 +1078,31 @@ packages: '@oslojs/encoding@1.1.0': resolution: {integrity: sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ==} - '@pagefind/darwin-arm64@1.1.1': - resolution: {integrity: sha512-tZ9tysUmQpFs2EqWG2+E1gc+opDAhSyZSsgKmFzhnWfkK02YHZhvL5XJXEZDqYy3s1FAKhwjTg8XDxneuBlDZQ==} + '@pagefind/darwin-arm64@1.3.0': + resolution: {integrity: sha512-365BEGl6ChOsauRjyVpBjXybflXAOvoMROw3TucAROHIcdBvXk9/2AmEvGFU0r75+vdQI4LJdJdpH4Y6Yqaj4A==} cpu: [arm64] os: [darwin] - '@pagefind/darwin-x64@1.1.1': - resolution: {integrity: sha512-ChohLQ39dLwaxQv0jIQB/SavP3TM5K5ENfDTqIdzLkmfs3+JlzSDyQKcJFjTHYcCzQOZVeieeGq8PdqvLJxJxQ==} + '@pagefind/darwin-x64@1.3.0': + resolution: {integrity: sha512-zlGHA23uuXmS8z3XxEGmbHpWDxXfPZ47QS06tGUq0HDcZjXjXHeLG+cboOy828QIV5FXsm9MjfkP5e4ZNbOkow==} cpu: [x64] os: [darwin] - '@pagefind/default-ui@1.1.1': - resolution: {integrity: sha512-ZM0zDatWDnac/VGHhQCiM7UgA4ca8jpjA+VfuTJyHJBaxGqZMQnm4WoTz9E0KFcue1Bh9kxpu7uWFZfwpZZk0A==} + '@pagefind/default-ui@1.3.0': + resolution: {integrity: sha512-CGKT9ccd3+oRK6STXGgfH+m0DbOKayX6QGlq38TfE1ZfUcPc5+ulTuzDbZUnMo+bubsEOIypm4Pl2iEyzZ1cNg==} - '@pagefind/linux-arm64@1.1.1': - resolution: {integrity: sha512-H5P6wDoCoAbdsWp0Zx0DxnLUrwTGWGLu/VI1rcN2CyFdY2EGSvPQsbGBMrseKRNuIrJDFtxHHHyjZ7UbzaM9EA==} + '@pagefind/linux-arm64@1.3.0': + resolution: {integrity: sha512-8lsxNAiBRUk72JvetSBXs4WRpYrQrVJXjlRRnOL6UCdBN9Nlsz0t7hWstRk36+JqHpGWOKYiuHLzGYqYAqoOnQ==} cpu: [arm64] os: [linux] - '@pagefind/linux-x64@1.1.1': - resolution: {integrity: sha512-yJs7tTYbL2MI3HT+ngs9E1BfUbY9M4/YzA0yEM5xBo4Xl8Yu8Qg2xZTOQ1/F6gwvMrjCUFo8EoACs6LRDhtMrQ==} + '@pagefind/linux-x64@1.3.0': + resolution: {integrity: sha512-hAvqdPJv7A20Ucb6FQGE6jhjqy+vZ6pf+s2tFMNtMBG+fzcdc91uTw7aP/1Vo5plD0dAOHwdxfkyw0ugal4kcQ==} cpu: [x64] os: [linux] - '@pagefind/windows-x64@1.1.1': - resolution: {integrity: sha512-b7/qPqgIl+lMzkQ8fJt51SfguB396xbIIR+VZ3YrL2tLuyifDJ1wL5mEm+ddmHxJ2Fki340paPcDan9en5OmAw==} + '@pagefind/windows-x64@1.3.0': + resolution: {integrity: sha512-BR1bIRWOMqkf8IoU576YDhij1Wd/Zf2kX/kCI0b2qzCKC8wcc2GQJaaRMCpzvCCrmliO4vtJ6RITp/AnoYUUmQ==} cpu: [x64] os: [win32] @@ -1303,8 +1216,8 @@ packages: peerDependencies: rollup: ^1.20.0||^2.0.0 - '@rollup/pluginutils@5.1.3': - resolution: {integrity: sha512-Pnsb6f32CD2W3uCaLZIzDmeFyQ2b8UWMFI7xtwUezpcGBDVDW6y9XgAWIlARiGAo6eNF5FK5aQTr0LFyNyqq5A==} + '@rollup/pluginutils@5.1.4': + resolution: {integrity: sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ==} engines: {node: '>=14.0.0'} peerDependencies: rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 @@ -1312,116 +1225,126 @@ packages: rollup: optional: true - '@rollup/rollup-android-arm-eabi@4.28.0': - resolution: {integrity: sha512-wLJuPLT6grGZsy34g4N1yRfYeouklTgPhH1gWXCYspenKYD0s3cR99ZevOGw5BexMNywkbV3UkjADisozBmpPQ==} + '@rollup/rollup-android-arm-eabi@4.37.0': + resolution: {integrity: sha512-l7StVw6WAa8l3vA1ov80jyetOAEo1FtHvZDbzXDO/02Sq/QVvqlHkYoFwDJPIMj0GKiistsBudfx5tGFnwYWDQ==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.28.0': - resolution: {integrity: sha512-eiNkznlo0dLmVG/6wf+Ifi/v78G4d4QxRhuUl+s8EWZpDewgk7PX3ZyECUXU0Zq/Ca+8nU8cQpNC4Xgn2gFNDA==} + '@rollup/rollup-android-arm64@4.37.0': + resolution: {integrity: sha512-6U3SlVyMxezt8Y+/iEBcbp945uZjJwjZimu76xoG7tO1av9VO691z8PkhzQ85ith2I8R2RddEPeSfcbyPfD4hA==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.28.0': - resolution: {integrity: sha512-lmKx9yHsppblnLQZOGxdO66gT77bvdBtr/0P+TPOseowE7D9AJoBw8ZDULRasXRWf1Z86/gcOdpBrV6VDUY36Q==} + '@rollup/rollup-darwin-arm64@4.37.0': + resolution: {integrity: sha512-+iTQ5YHuGmPt10NTzEyMPbayiNTcOZDWsbxZYR1ZnmLnZxG17ivrPSWFO9j6GalY0+gV3Jtwrrs12DBscxnlYA==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.28.0': - resolution: {integrity: sha512-8hxgfReVs7k9Js1uAIhS6zq3I+wKQETInnWQtgzt8JfGx51R1N6DRVy3F4o0lQwumbErRz52YqwjfvuwRxGv1w==} + '@rollup/rollup-darwin-x64@4.37.0': + resolution: {integrity: sha512-m8W2UbxLDcmRKVjgl5J/k4B8d7qX2EcJve3Sut7YGrQoPtCIQGPH5AMzuFvYRWZi0FVS0zEY4c8uttPfX6bwYQ==} cpu: [x64] os: [darwin] - '@rollup/rollup-freebsd-arm64@4.28.0': - resolution: {integrity: sha512-lA1zZB3bFx5oxu9fYud4+g1mt+lYXCoch0M0V/xhqLoGatbzVse0wlSQ1UYOWKpuSu3gyN4qEc0Dxf/DII1bhQ==} + '@rollup/rollup-freebsd-arm64@4.37.0': + resolution: {integrity: sha512-FOMXGmH15OmtQWEt174v9P1JqqhlgYge/bUjIbiVD1nI1NeJ30HYT9SJlZMqdo1uQFyt9cz748F1BHghWaDnVA==} cpu: [arm64] os: [freebsd] - '@rollup/rollup-freebsd-x64@4.28.0': - resolution: {integrity: sha512-aI2plavbUDjCQB/sRbeUZWX9qp12GfYkYSJOrdYTL/C5D53bsE2/nBPuoiJKoWp5SN78v2Vr8ZPnB+/VbQ2pFA==} + '@rollup/rollup-freebsd-x64@4.37.0': + resolution: {integrity: sha512-SZMxNttjPKvV14Hjck5t70xS3l63sbVwl98g3FlVVx2YIDmfUIy29jQrsw06ewEYQ8lQSuY9mpAPlmgRD2iSsA==} cpu: [x64] os: [freebsd] - '@rollup/rollup-linux-arm-gnueabihf@4.28.0': - resolution: {integrity: sha512-WXveUPKtfqtaNvpf0iOb0M6xC64GzUX/OowbqfiCSXTdi/jLlOmH0Ba94/OkiY2yTGTwteo4/dsHRfh5bDCZ+w==} + '@rollup/rollup-linux-arm-gnueabihf@4.37.0': + resolution: {integrity: sha512-hhAALKJPidCwZcj+g+iN+38SIOkhK2a9bqtJR+EtyxrKKSt1ynCBeqrQy31z0oWU6thRZzdx53hVgEbRkuI19w==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm-musleabihf@4.28.0': - resolution: {integrity: sha512-yLc3O2NtOQR67lI79zsSc7lk31xjwcaocvdD1twL64PK1yNaIqCeWI9L5B4MFPAVGEVjH5k1oWSGuYX1Wutxpg==} + '@rollup/rollup-linux-arm-musleabihf@4.37.0': + resolution: {integrity: sha512-jUb/kmn/Gd8epbHKEqkRAxq5c2EwRt0DqhSGWjPFxLeFvldFdHQs/n8lQ9x85oAeVb6bHcS8irhTJX2FCOd8Ag==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm64-gnu@4.28.0': - resolution: {integrity: sha512-+P9G9hjEpHucHRXqesY+3X9hD2wh0iNnJXX/QhS/J5vTdG6VhNYMxJ2rJkQOxRUd17u5mbMLHM7yWGZdAASfcg==} + '@rollup/rollup-linux-arm64-gnu@4.37.0': + resolution: {integrity: sha512-oNrJxcQT9IcbcmKlkF+Yz2tmOxZgG9D9GRq+1OE6XCQwCVwxixYAa38Z8qqPzQvzt1FCfmrHX03E0pWoXm1DqA==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-arm64-musl@4.28.0': - resolution: {integrity: sha512-1xsm2rCKSTpKzi5/ypT5wfc+4bOGa/9yI/eaOLW0oMs7qpC542APWhl4A37AENGZ6St6GBMWhCCMM6tXgTIplw==} + '@rollup/rollup-linux-arm64-musl@4.37.0': + resolution: {integrity: sha512-pfxLBMls+28Ey2enpX3JvjEjaJMBX5XlPCZNGxj4kdJyHduPBXtxYeb8alo0a7bqOoWZW2uKynhHxF/MWoHaGQ==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-powerpc64le-gnu@4.28.0': - resolution: {integrity: sha512-zgWxMq8neVQeXL+ouSf6S7DoNeo6EPgi1eeqHXVKQxqPy1B2NvTbaOUWPn/7CfMKL7xvhV0/+fq/Z/J69g1WAQ==} + '@rollup/rollup-linux-loongarch64-gnu@4.37.0': + resolution: {integrity: sha512-yCE0NnutTC/7IGUq/PUHmoeZbIwq3KRh02e9SfFh7Vmc1Z7atuJRYWhRME5fKgT8aS20mwi1RyChA23qSyRGpA==} + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-powerpc64le-gnu@4.37.0': + resolution: {integrity: sha512-NxcICptHk06E2Lh3a4Pu+2PEdZ6ahNHuK7o6Np9zcWkrBMuv21j10SQDJW3C9Yf/A/P7cutWoC/DptNLVsZ0VQ==} cpu: [ppc64] os: [linux] - '@rollup/rollup-linux-riscv64-gnu@4.28.0': - resolution: {integrity: sha512-VEdVYacLniRxbRJLNtzwGt5vwS0ycYshofI7cWAfj7Vg5asqj+pt+Q6x4n+AONSZW/kVm+5nklde0qs2EUwU2g==} + '@rollup/rollup-linux-riscv64-gnu@4.37.0': + resolution: {integrity: sha512-PpWwHMPCVpFZLTfLq7EWJWvrmEuLdGn1GMYcm5MV7PaRgwCEYJAwiN94uBuZev0/J/hFIIJCsYw4nLmXA9J7Pw==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-riscv64-musl@4.37.0': + resolution: {integrity: sha512-DTNwl6a3CfhGTAOYZ4KtYbdS8b+275LSLqJVJIrPa5/JuIufWWZ/QFvkxp52gpmguN95eujrM68ZG+zVxa8zHA==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-s390x-gnu@4.28.0': - resolution: {integrity: sha512-LQlP5t2hcDJh8HV8RELD9/xlYtEzJkm/aWGsauvdO2ulfl3QYRjqrKW+mGAIWP5kdNCBheqqqYIGElSRCaXfpw==} + '@rollup/rollup-linux-s390x-gnu@4.37.0': + resolution: {integrity: sha512-hZDDU5fgWvDdHFuExN1gBOhCuzo/8TMpidfOR+1cPZJflcEzXdCy1LjnklQdW8/Et9sryOPJAKAQRw8Jq7Tg+A==} cpu: [s390x] os: [linux] - '@rollup/rollup-linux-x64-gnu@4.28.0': - resolution: {integrity: sha512-Nl4KIzteVEKE9BdAvYoTkW19pa7LR/RBrT6F1dJCV/3pbjwDcaOq+edkP0LXuJ9kflW/xOK414X78r+K84+msw==} + '@rollup/rollup-linux-x64-gnu@4.37.0': + resolution: {integrity: sha512-pKivGpgJM5g8dwj0ywBwe/HeVAUSuVVJhUTa/URXjxvoyTT/AxsLTAbkHkDHG7qQxLoW2s3apEIl26uUe08LVQ==} cpu: [x64] os: [linux] - '@rollup/rollup-linux-x64-musl@4.28.0': - resolution: {integrity: sha512-eKpJr4vBDOi4goT75MvW+0dXcNUqisK4jvibY9vDdlgLx+yekxSm55StsHbxUsRxSTt3JEQvlr3cGDkzcSP8bw==} + '@rollup/rollup-linux-x64-musl@4.37.0': + resolution: {integrity: sha512-E2lPrLKE8sQbY/2bEkVTGDEk4/49UYRVWgj90MY8yPjpnGBQ+Xi1Qnr7b7UIWw1NOggdFQFOLZ8+5CzCiz143w==} cpu: [x64] os: [linux] - '@rollup/rollup-win32-arm64-msvc@4.28.0': - resolution: {integrity: sha512-Vi+WR62xWGsE/Oj+mD0FNAPY2MEox3cfyG0zLpotZdehPFXwz6lypkGs5y38Jd/NVSbOD02aVad6q6QYF7i8Bg==} + '@rollup/rollup-win32-arm64-msvc@4.37.0': + resolution: {integrity: sha512-Jm7biMazjNzTU4PrQtr7VS8ibeys9Pn29/1bm4ph7CP2kf21950LgN+BaE2mJ1QujnvOc6p54eWWiVvn05SOBg==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.28.0': - resolution: {integrity: sha512-kN/Vpip8emMLn/eOza+4JwqDZBL6MPNpkdaEsgUtW1NYN3DZvZqSQrbKzJcTL6hd8YNmFTn7XGWMwccOcJBL0A==} + '@rollup/rollup-win32-ia32-msvc@4.37.0': + resolution: {integrity: sha512-e3/1SFm1OjefWICB2Ucstg2dxYDkDTZGDYgwufcbsxTHyqQps1UQf33dFEChBNmeSsTOyrjw2JJq0zbG5GF6RA==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.28.0': - resolution: {integrity: sha512-Bvno2/aZT6usSa7lRDL2+hMjVAGjuqaymF1ApZm31JXzniR/hvr14jpU+/z4X6Gt5BPlzosscyJZGUvguXIqeQ==} + '@rollup/rollup-win32-x64-msvc@4.37.0': + resolution: {integrity: sha512-LWbXUBwn/bcLx2sSsqy7pK5o+Nr+VCoRoAohfJ5C/aBio9nfJmGQqHAhU6pwxV/RmyTk5AqdySma7uwWGlmeuA==} cpu: [x64] os: [win32] - '@shikijs/core@1.26.1': - resolution: {integrity: sha512-yeo7sG+WZQblKPclUOKRPwkv1PyoHYkJ4gP9DzhFJbTdueKR7wYTI1vfF/bFi1NTgc545yG/DzvVhZgueVOXMA==} + '@shikijs/core@1.29.2': + resolution: {integrity: sha512-vju0lY9r27jJfOY4Z7+Rt/nIOjzJpZ3y+nYpqtUZInVoXQ/TJZcfGnNOGnKjFdVZb8qexiCuSlZRKcGfhhTTZQ==} - '@shikijs/engine-javascript@1.26.1': - resolution: {integrity: sha512-CRhA0b8CaSLxS0E9A4Bzcb3LKBNpykfo9F85ozlNyArxjo2NkijtiwrJZ6eHa+NT5I9Kox2IXVdjUsP4dilsmw==} + '@shikijs/engine-javascript@1.29.2': + resolution: {integrity: sha512-iNEZv4IrLYPv64Q6k7EPpOCE/nuvGiKl7zxdq0WFuRPF5PAE9PRo2JGq/d8crLusM59BRemJ4eOqrFrC4wiQ+A==} - '@shikijs/engine-oniguruma@1.26.1': - resolution: {integrity: sha512-F5XuxN1HljLuvfXv7d+mlTkV7XukC1cawdtOo+7pKgPD83CAB1Sf8uHqP3PK0u7njFH0ZhoXE1r+0JzEgAQ+kg==} + '@shikijs/engine-oniguruma@1.29.2': + resolution: {integrity: sha512-7iiOx3SG8+g1MnlzZVDYiaeHe7Ez2Kf2HrJzdmGwkRisT7r4rak0e655AcM/tF9JG/kg5fMNYlLLKglbN7gBqA==} - '@shikijs/langs@1.26.1': - resolution: {integrity: sha512-oz/TQiIqZejEIZbGtn68hbJijAOTtYH4TMMSWkWYozwqdpKR3EXgILneQy26WItmJjp3xVspHdiUxUCws4gtuw==} + '@shikijs/langs@1.29.2': + resolution: {integrity: sha512-FIBA7N3LZ+223U7cJDUYd5shmciFQlYkFXlkKVaHsCPgfVLiO+e12FmQE6Tf9vuyEsFe3dIl8qGWKXgEHL9wmQ==} - '@shikijs/themes@1.26.1': - resolution: {integrity: sha512-JDxVn+z+wgLCiUhBGx2OQrLCkKZQGzNH3nAxFir4PjUcYiyD8Jdms9izyxIogYmSwmoPTatFTdzyrRKbKlSfPA==} + '@shikijs/themes@1.29.2': + resolution: {integrity: sha512-i9TNZlsq4uoyqSbluIcZkmPL9Bfi3djVxRnofUHwvx/h6SRW3cwgBC5SML7vsDcWyukY0eCzVN980rqP6qNl9g==} - '@shikijs/types@1.26.1': - resolution: {integrity: sha512-d4B00TKKAMaHuFYgRf3L0gwtvqpW4hVdVwKcZYbBfAAQXspgkbWqnFfuFl3MDH6gLbsubOcr+prcnsqah3ny7Q==} + '@shikijs/types@1.29.2': + resolution: {integrity: sha512-VJjK0eIijTZf0QSTODEXCqinjBn0joAHQ+aPSBzrv4O2d/QSbsMw+ZeSRx03kV34Hy7NzUvV/7NqfYGRLrASmw==} - '@shikijs/vscode-textmate@10.0.1': - resolution: {integrity: sha512-fTIQwLF+Qhuws31iw7Ncl1R3HUDtGwIipiJ9iU+UsDUwMhegFcQKQHd51nZjb7CArq0MvON8rbgCGQYWHUKAdg==} + '@shikijs/vscode-textmate@10.0.2': + resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==} '@surma/rollup-plugin-off-main-thread@2.2.3': resolution: {integrity: sha512-lR8q/9W7hZpMWweNiAKU7NQerBnzQQLvi8qnTDU/fxItPhtZVMbPV3lbCwjhIlNBe9Bbr5V+KHshvWmVSG9cxQ==} @@ -1491,9 +1414,6 @@ packages: engines: {node: '>= 10'} hasBin: true - '@types/acorn@4.0.6': - resolution: {integrity: sha512-veQTnWP+1D/xbxVrPC3zHnCZRjSrKfhbMUlEA43iMZLu7EsnTtkJklIuwrCPbOi8YkvDQAiW05VQQFvvz9oieQ==} - '@types/babel__core@7.20.5': resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} @@ -1503,8 +1423,8 @@ packages: '@types/babel__template@7.4.4': resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} - '@types/babel__traverse@7.20.6': - resolution: {integrity: sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==} + '@types/babel__traverse@7.20.7': + resolution: {integrity: sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng==} '@types/cookie@0.6.0': resolution: {integrity: sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==} @@ -1521,6 +1441,9 @@ packages: '@types/estree@1.0.6': resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} + '@types/estree@1.0.7': + resolution: {integrity: sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==} + '@types/hast@3.0.4': resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==} @@ -1533,8 +1456,8 @@ packages: '@types/mdx@2.0.13': resolution: {integrity: sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==} - '@types/ms@0.7.34': - resolution: {integrity: sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==} + '@types/ms@2.1.0': + resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} '@types/nlcst@2.0.3': resolution: {integrity: sha512-vSYNSDe6Ix3q+6Z7ri9lyWqgGhJTmzRjZRqyq15N0Z/1/UnVsno9G/N40NBijoYx2seFDIl0+B2mgAb9mezUCA==} @@ -1545,6 +1468,9 @@ packages: '@types/node@22.13.10': resolution: {integrity: sha512-I6LPUvlRH+O6VRUqYOcMudhaIdUVWfsjnZavnsraHvpBwaEyMN29ry+0UVJhImYL16xsscu0aske3yA+uPOWfw==} + '@types/node@22.13.13': + resolution: {integrity: sha512-ClsL5nMwKaBRwPcCvH8E7+nU4GxHVx1axNvMZTFHMEfNI7oahimt26P5zjVCRrjiIWj6YFXfE1v3dEp94wLcGQ==} + '@types/picomatch@2.3.3': resolution: {integrity: sha512-Yll76ZHikRFCyz/pffKGjrCwe/le2CDwOP5F210KQo27kpRE46U2rDnzikNlVn6/ezH3Mhn46bJMTfeVTtcYMg==} @@ -1566,16 +1492,16 @@ packages: '@types/unist@3.0.3': resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} - '@ungap/structured-clone@1.2.0': - resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} + '@ungap/structured-clone@1.3.0': + resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==} acorn-jsx@5.3.2: resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - acorn@8.14.0: - resolution: {integrity: sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==} + acorn@8.14.1: + resolution: {integrity: sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==} engines: {node: '>=0.4.0'} hasBin: true @@ -1583,8 +1509,8 @@ packages: resolution: {integrity: sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==} engines: {node: '>= 14'} - ajv@8.13.0: - resolution: {integrity: sha512-PRA911Blj99jR5RMeTunVbNXMF6Lp4vZXnk5GQjcnUWUTsrXtekg/pnmFFI2u/I36Y/2bITGS30GZCXei6uNkA==} + ajv@8.17.1: + resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} ansi-align@3.0.1: resolution: {integrity: sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==} @@ -1618,15 +1544,15 @@ packages: resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==} engines: {node: '>= 0.4'} - array-buffer-byte-length@1.0.1: - resolution: {integrity: sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==} + array-buffer-byte-length@1.0.2: + resolution: {integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==} engines: {node: '>= 0.4'} array-iterate@2.0.1: resolution: {integrity: sha512-I1jXZMjAgCMmxT4qxXfPXa6SthSoE8h6gkSI9BGGNv8mP8G/v0blc+qFnZu6K42vTOiuME596QaLO0TP3Lk0xg==} - arraybuffer.prototype.slice@1.0.3: - resolution: {integrity: sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==} + arraybuffer.prototype.slice@1.0.4: + resolution: {integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==} engines: {node: '>= 0.4'} ast-types@0.16.1: @@ -1670,8 +1596,12 @@ packages: peerDependencies: astro: '>=4.0.0' - async@3.2.5: - resolution: {integrity: sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==} + async-function@1.0.0: + resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==} + engines: {node: '>= 0.4'} + + async@3.2.6: + resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} @@ -1688,18 +1618,18 @@ packages: resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} engines: {node: '>= 0.4'} - babel-plugin-polyfill-corejs2@0.4.11: - resolution: {integrity: sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==} + babel-plugin-polyfill-corejs2@0.4.13: + resolution: {integrity: sha512-3sX/eOms8kd3q2KZ6DAhKPc0dgm525Gqq5NtWKZ7QYYZEv57OQ54KtblzJzH1lQF/eQxO8KjWGIK9IPUJNus5g==} peerDependencies: '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 - babel-plugin-polyfill-corejs3@0.10.4: - resolution: {integrity: sha512-25J6I8NGfa5YkCDogHRID3fVCadIR8/pGl1/spvCkzb6lVn6SR3ojpx9nOn9iEBcUsjY24AmdKm5khcfKdylcg==} + babel-plugin-polyfill-corejs3@0.11.1: + resolution: {integrity: sha512-yGCqvBT4rwMczo28xkH/noxJ6MZ4nJfkVYdoDaC/utLtWrXxv27HVrzAeSbqR8SxDsp46n0YF47EbHoixy6rXQ==} peerDependencies: '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 - babel-plugin-polyfill-regenerator@0.6.2: - resolution: {integrity: sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg==} + babel-plugin-polyfill-regenerator@0.6.4: + resolution: {integrity: sha512-7gD3pRadPrbjhjLyxebmx/WrFYcuSjZ0XbdUujQMZ/fcE9oeewk2U/7PCvez84UeuK3oSjmPZ0Ch0dlupQvGzw==} peerDependencies: '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 @@ -1735,8 +1665,8 @@ packages: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} - browserslist@4.24.2: - resolution: {integrity: sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==} + browserslist@4.24.4: + resolution: {integrity: sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true @@ -1747,16 +1677,24 @@ packages: resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} engines: {node: '>=6'} - call-bind@1.0.7: - resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} + call-bind-apply-helpers@1.0.2: + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} + + call-bind@1.0.8: + resolution: {integrity: sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==} + engines: {node: '>= 0.4'} + + call-bound@1.0.4: + resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} engines: {node: '>= 0.4'} camelcase@8.0.0: resolution: {integrity: sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==} engines: {node: '>=16'} - caniuse-lite@1.0.30001686: - resolution: {integrity: sha512-Y7deg0Aergpa24M3qLC5xjNklnKnhsmSyR/V89dLZ1n0ucJIFNs7PgR2Yfa/Zf6W79SbBicgtGxZr2juHkEUIA==} + caniuse-lite@1.0.30001707: + resolution: {integrity: sha512-3qtRjw/HQSMlDWf+X79N206fepf4SOOU6SQLMaq/0KkZLmSjPxAkBOQQ+FxbHKfHmYLZFfdWsO3KA90ceHPSnw==} ccount@2.0.1: resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} @@ -1765,8 +1703,8 @@ packages: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} - chalk@5.3.0: - resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==} + chalk@5.4.1: + resolution: {integrity: sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==} engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} character-entities-html4@2.1.0: @@ -1785,8 +1723,8 @@ packages: resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} engines: {node: '>= 14.16.0'} - ci-info@4.1.0: - resolution: {integrity: sha512-HutrvTNsF48wnxkzERIXOe5/mlcfFcbfCmwcg6CJnizbSue78AbDt+1cgl26zwn61WFxhcPykPfZrbqjGmBb4A==} + ci-info@4.2.0: + resolution: {integrity: sha512-cYY9mypksY8NRqgDB1XD1RiJL338v/551niynFTGkZOO2LHuB2OmOYxDIe/ttN9AHwrqdum1360G3ald0W9kCg==} engines: {node: '>=8'} cli-boxes@3.0.0: @@ -1849,43 +1787,43 @@ packages: resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} engines: {node: '>= 0.6'} - core-js-compat@3.37.1: - resolution: {integrity: sha512-9TNiImhKvQqSUkOvk/mMRZzOANTiEVC7WaBNhHcKM7x+/5E1l5NvsysR19zuDQScE8k+kfQXWRN3AtS/eOSHpg==} + core-js-compat@3.41.0: + resolution: {integrity: sha512-RFsU9LySVue9RTwdDVX/T0e2Y6jRYWXERKElIjpuEOEnxaXffI0X7RUwVzfYLfzuLXSNJDYoRYUAmRUcyln20A==} crypto-random-string@2.0.0: resolution: {integrity: sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==} engines: {node: '>=8'} - css-selector-parser@3.0.5: - resolution: {integrity: sha512-3itoDFbKUNx1eKmVpYMFyqKX04Ww9osZ+dLgrk6GEv6KMVeXUhUnp4I5X+evw+u3ZxVU6RFXSSRxlTeMh8bA+g==} + css-selector-parser@3.1.1: + resolution: {integrity: sha512-Y+DuvJ7JAjpL1f4DeILe5sXCC3kRXMl0DxM4lAWbS8/jEZ29o3V0L5TL6zIifj4Csmj6c+jiF2ENjida2OVOGA==} cssesc@3.0.0: resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} engines: {node: '>=4'} hasBin: true - cssstyle@4.2.1: - resolution: {integrity: sha512-9+vem03dMXG7gDmZ62uqmRiMRNtinIZ9ZyuF6BdxzfOD+FdN5hretzynkn0ReS2DO2GSw76RWHs0UmJPI2zUjw==} + cssstyle@4.3.0: + resolution: {integrity: sha512-6r0NiY0xizYqfBvWp1G7WXJ06/bZyrk7Dc6PHql82C/pKGUTKu4yAX4Y8JPamb1ob9nBKuxWzCGTRuGwU3yxJQ==} engines: {node: '>=18'} data-urls@5.0.0: resolution: {integrity: sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==} engines: {node: '>=18'} - data-view-buffer@1.0.1: - resolution: {integrity: sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==} + data-view-buffer@1.0.2: + resolution: {integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==} engines: {node: '>= 0.4'} - data-view-byte-length@1.0.1: - resolution: {integrity: sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==} + data-view-byte-length@1.0.2: + resolution: {integrity: sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==} engines: {node: '>= 0.4'} - data-view-byte-offset@1.0.0: - resolution: {integrity: sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==} + data-view-byte-offset@1.0.1: + resolution: {integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==} engines: {node: '>= 0.4'} - debug@4.3.7: - resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==} + debug@4.4.0: + resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==} engines: {node: '>=6.0'} peerDependencies: supports-color: '*' @@ -1893,11 +1831,11 @@ packages: supports-color: optional: true - decimal.js@10.4.3: - resolution: {integrity: sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==} + decimal.js@10.5.0: + resolution: {integrity: sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw==} - decode-named-character-reference@1.0.2: - resolution: {integrity: sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==} + decode-named-character-reference@1.1.0: + resolution: {integrity: sha512-Wy+JTSbFThEOXQIR2L6mxJvEs+veIzpmqD7ynWxMXGpnk3smkHQOp6forLdHsKpAMW9iJpaBBIxz285t1n1C3w==} deepmerge@4.3.1: resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} @@ -1953,13 +1891,17 @@ packages: resolution: {integrity: sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA==} engines: {node: '>=4'} + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + ejs@3.1.10: resolution: {integrity: sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==} engines: {node: '>=0.10.0'} hasBin: true - electron-to-chromium@1.5.70: - resolution: {integrity: sha512-P6FPqAWIZrC3sHDAwBitJBs7N7IF58m39XVny7DFseQXK2eiMn7nNQizFf63mWDDUnFvaqsM8FI0+ZZfLkdUGA==} + electron-to-chromium@1.5.125: + resolution: {integrity: sha512-A2+qEsSUc95QvyFDl7PNwkDDNphIKBVfBBtWWkPGRbiWEgzLo0SvLygYF6HgzVduHd+4WGPB/WD64POFgwzY3g==} emoji-regex-xs@1.0.0: resolution: {integrity: sha512-LRlerrMYoIDrT6jgpeZ2YYl/L8EulRTt5hQcYjy5AInh7HWXKimpqx68aknBFpGL2+/IcogTcaydJEgaTmOpDg==} @@ -1974,31 +1916,31 @@ packages: resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} engines: {node: '>=0.12'} - es-abstract@1.23.3: - resolution: {integrity: sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==} + es-abstract@1.23.9: + resolution: {integrity: sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA==} engines: {node: '>= 0.4'} - es-define-property@1.0.0: - resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==} + es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} engines: {node: '>= 0.4'} es-errors@1.3.0: resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} engines: {node: '>= 0.4'} - es-module-lexer@1.5.4: - resolution: {integrity: sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==} + es-module-lexer@1.6.0: + resolution: {integrity: sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==} - es-object-atoms@1.0.0: - resolution: {integrity: sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==} + es-object-atoms@1.1.1: + resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} engines: {node: '>= 0.4'} - es-set-tostringtag@2.0.3: - resolution: {integrity: sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==} + es-set-tostringtag@2.1.0: + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} engines: {node: '>= 0.4'} - es-to-primitive@1.2.1: - resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} + es-to-primitive@1.3.0: + resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==} engines: {node: '>= 0.4'} esast-util-from-estree@2.0.0: @@ -2197,19 +2139,22 @@ packages: fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - fast-glob@3.3.2: - resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} + fast-glob@3.3.3: + resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} engines: {node: '>=8.6.0'} fast-json-stable-stringify@2.1.0: resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} - fast-xml-parser@4.5.1: - resolution: {integrity: sha512-y655CeyUQ+jj7KBbYMc4FG01V8ZQqjN+gDYGJ50RtfsUB8iG9AmwmwoAgeKLJdmueKKMrH1RJ7yXHTSoczdv5w==} + fast-uri@3.0.6: + resolution: {integrity: sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==} + + fast-xml-parser@4.5.3: + resolution: {integrity: sha512-RKihhV+SHsIUGXObeVy9AXiBbFwkVk7Syp8XgwN5U3JV416+Gwp/GO9i0JYKmikykgz/UHRrrV4ROuZEo/T0ig==} hasBin: true - fastq@1.17.1: - resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} + fastq@1.19.1: + resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} filelist@1.0.4: resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==} @@ -2218,8 +2163,8 @@ packages: resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} - find-up-simple@1.0.0: - resolution: {integrity: sha512-q7Us7kcjj2VMePAa02hDAF6d+MzsdsAWEwYyOpwUtlerRBkOEPBCRZrAV4XfcSN8fHAgaD0hP7miwoay6DCprw==} + find-up-simple@1.0.1: + resolution: {integrity: sha512-afd4O7zpqHeRyg4PfDQsXmlDe2PfdHtJt6Akt8jOWaApLOZk5JXs6VMR29lz03pRe9mpykrRCYIYxaJYcfpncQ==} engines: {node: '>=18'} find-up@4.1.0: @@ -2233,11 +2178,12 @@ packages: resolution: {integrity: sha512-9UbaD6XdAL97+k/n+N7JwX46K/M6Zc6KcFYskrYL8wbBV/Uyk0CTAMY0VT+qiK5PM7AIc9aTWYtq65U7T+aCNQ==} engines: {node: '>=8'} - for-each@0.3.3: - resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} + for-each@0.3.5: + resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==} + engines: {node: '>= 0.4'} - form-data@4.0.1: - resolution: {integrity: sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==} + form-data@4.0.2: + resolution: {integrity: sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==} engines: {node: '>= 6'} fs-extra@9.1.0: @@ -2255,8 +2201,8 @@ packages: function-bind@1.1.2: resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - function.prototype.name@1.1.6: - resolution: {integrity: sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==} + function.prototype.name@1.1.8: + resolution: {integrity: sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==} engines: {node: '>= 0.4'} functions-have-names@1.2.3: @@ -2270,8 +2216,8 @@ packages: resolution: {integrity: sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==} engines: {node: '>=18'} - get-intrinsic@1.2.4: - resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} + get-intrinsic@1.3.0: + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} engines: {node: '>= 0.4'} get-own-enumerable-property-symbols@3.0.2: @@ -2281,8 +2227,12 @@ packages: resolution: {integrity: sha512-QB9NKEeDg3xxVwCCwJQ9+xycaz6pBB6iQ76wiWMl1927n0Kir6alPiP+yuiICLLU4jpMe08dXfpebuQppFA2zw==} engines: {node: '>=16'} - get-symbol-description@1.0.2: - resolution: {integrity: sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==} + get-proto@1.0.1: + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} + + get-symbol-description@1.1.0: + resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==} engines: {node: '>= 0.4'} github-slugger@2.0.0: @@ -2304,8 +2254,9 @@ packages: resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} engines: {node: '>= 0.4'} - gopd@1.0.1: - resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} @@ -2314,8 +2265,9 @@ packages: resolution: {integrity: sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==} engines: {node: '>=6.0'} - has-bigints@1.0.2: - resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} + has-bigints@1.1.0: + resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==} + engines: {node: '>= 0.4'} has-flag@4.0.0: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} @@ -2324,12 +2276,12 @@ packages: has-property-descriptors@1.0.2: resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} - has-proto@1.0.3: - resolution: {integrity: sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==} + has-proto@1.2.0: + resolution: {integrity: sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==} engines: {node: '>= 0.4'} - has-symbols@1.0.3: - resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} engines: {node: '>= 0.4'} has-tostringtag@1.0.2: @@ -2352,8 +2304,8 @@ packages: hast-util-from-html@2.0.3: resolution: {integrity: sha512-CUSRHXyKjzHov8yKsQjGOElXy/3EKpyX56ELnkHH34vDVw1N1XSQ1ZcAvTyAPtGqLTuKP/uxM+aLkSPqF/EtMw==} - hast-util-from-parse5@8.0.2: - resolution: {integrity: sha512-SfMzfdAi/zAoZ1KkFEyyeXBn7u/ShQrfd675ZEE9M3qj+PMFX05xubzRyF76CCSJu8au9jgVxDV1+okFvgZU4A==} + hast-util-from-parse5@8.0.3: + resolution: {integrity: sha512-3kxEVkEKt0zvcZ3hCRYI8rqrgwtlIOFMWkbclACvjlDw8Li9S2hk/d51OI0nr/gIpdMHNepwgOKqZ/sy0Clpyg==} hast-util-has-property@3.0.0: resolution: {integrity: sha512-MNilsvEKLFpV604hwfhVStK0usFY/QmM5zX16bo7EjnAEGofr5YyI37kzopBlZJkHD4t887i+q/C8/tr5Q94cA==} @@ -2361,14 +2313,14 @@ packages: hast-util-heading-rank@3.0.0: resolution: {integrity: sha512-EJKb8oMUXVHcWZTDepnr+WNbfnXKFNf9duMesmr4S8SXTJBJ9M4Yok08pu9vxdJwdlGRhVumk9mEhkEvKGifwA==} - hast-util-is-body-ok-link@3.0.0: - resolution: {integrity: sha512-VFHY5bo2nY8HiV6nir2ynmEB1XkxzuUffhEGeVx7orbu/B1KaGyeGgMZldvMVx5xWrDlLLG/kQ6YkJAMkBEx0w==} + hast-util-is-body-ok-link@3.0.1: + resolution: {integrity: sha512-0qpnzOBLztXHbHQenVB8uNuxTnm/QBFUOmdOSsEn7GnBtyY07+ENTWVFBAnXd/zEgd9/SUG3lRY7hSIBWRgGpQ==} hast-util-is-element@3.0.0: resolution: {integrity: sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==} - hast-util-minify-whitespace@1.0.0: - resolution: {integrity: sha512-gD1m4YJSIk62ij32TlhFNqsC3dOQvpA4QAhyZOZFAT4u8LfEfB6N+F0V9oXQGBWXoqrs0h9wQRKa8RCeo8j61g==} + hast-util-minify-whitespace@1.0.1: + resolution: {integrity: sha512-L96fPOVpnclQE0xzdWb/D12VT5FabA7SnZOUMtL1DbXmYiHJMXZvFkIZfiMmTCNJHUeO2K9UYNXoVyfz+QHuOw==} hast-util-parse-selector@4.0.0: resolution: {integrity: sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==} @@ -2376,29 +2328,29 @@ packages: hast-util-phrasing@3.0.1: resolution: {integrity: sha512-6h60VfI3uBQUxHqTyMymMZnEbNl1XmEGtOxxKYL7stY2o601COo62AWAYBQR9lZbYXYSBoxag8UpPRXK+9fqSQ==} - hast-util-raw@9.0.4: - resolution: {integrity: sha512-LHE65TD2YiNsHD3YuXcKPHXPLuYh/gjp12mOfU8jxSrm1f/yJpsb0F/KKljS6U9LJoP0Ux+tCe8iJ2AsPzTdgA==} + hast-util-raw@9.1.0: + resolution: {integrity: sha512-Y8/SBAHkZGoNkpzqqfCldijcuUKh7/su31kEBp67cFY09Wy0mTRgtsLYsiIxMJxlu0f6AA5SUTbDR8K0rxnbUw==} - hast-util-select@6.0.2: - resolution: {integrity: sha512-hT/SD/d/Meu+iobvgkffo1QecV8WeKWxwsNMzcTJsKw1cKTQKSR/7ArJeURLNJF9HDjp9nVoORyNNJxrvBye8Q==} + hast-util-select@6.0.4: + resolution: {integrity: sha512-RqGS1ZgI0MwxLaKLDxjprynNzINEkRHY2i8ln4DDjgv9ZhcYVIHN9rlpiYsqtFwrgpYU361SyWDQcGNIBVu3lw==} - hast-util-to-estree@3.1.0: - resolution: {integrity: sha512-lfX5g6hqVh9kjS/B9E2gSkvHH4SZNiQFiqWS0x9fENzEl+8W12RqdRxX6d/Cwxi30tPQs3bIO+aolQJNp1bIyw==} + hast-util-to-estree@3.1.3: + resolution: {integrity: sha512-48+B/rJWAp0jamNbAAf9M7Uf//UVqAoMmgXhBdxTDJLGKY+LRnZ99qcG+Qjl5HfMpYNzS5v4EAwVEF34LeAj7w==} hast-util-to-html@9.0.3: resolution: {integrity: sha512-M17uBDzMJ9RPCqLMO92gNNUDuBSq10a25SDBI08iCCxmorf4Yy6sYHK57n9WAbRAAaU+DuR4W6GN9K4DFZesYg==} - hast-util-to-html@9.0.4: - resolution: {integrity: sha512-wxQzXtdbhiwGAUKrnQJXlOPmHnEehzphwkK7aluUPQ+lEc1xefC8pblMgpp2w5ldBTEfveRIrADcrhGIWrlTDA==} + hast-util-to-html@9.0.5: + resolution: {integrity: sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==} - hast-util-to-jsx-runtime@2.3.0: - resolution: {integrity: sha512-H/y0+IWPdsLLS738P8tDnrQ8Z+dj12zQQ6WC11TIM21C8WFVoIxcqWXf2H3hiTVZjF1AWqoimGwrTWecWrnmRQ==} + hast-util-to-jsx-runtime@2.3.6: + resolution: {integrity: sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg==} hast-util-to-parse5@8.0.0: resolution: {integrity: sha512-3KKrV5ZVI8if87DVSi1vDeByYrkGzg4mEfeu4alwgmmIeARiBLKCZS2uw5Gb6nU9x9Yufyj3iudm6i7nl52PFw==} - hast-util-to-string@3.0.0: - resolution: {integrity: sha512-OGkAxX1Ua3cbcW6EJ5pT/tslVb90uViVkcJ4ZZIMW/R33DX/AkcJcRrPebPwJkHYwlDHXz4aIwvAAaAdtrACFA==} + hast-util-to-string@3.0.1: + resolution: {integrity: sha512-XelQVTDWvqcl3axRfI0xSeoVKzyIFPwsAGSLIsKdJKQMXDYJS4WYrBNF/8J7RdhIcFI2BOHgAifggsvsxp/3+A==} hast-util-to-text@4.0.2: resolution: {integrity: sha512-KK6y/BN8lbaq654j7JgBydev7wuNMcID54lkRav1P0CaE1e47P72AWWPiGKXTJU271ooYzcvTAn/Zt0REnvc7A==} @@ -2406,8 +2358,8 @@ packages: hast-util-whitespace@3.0.0: resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==} - hastscript@9.0.0: - resolution: {integrity: sha512-jzaLBGavEDKHrc5EfFImKN7nZKKBdSLIdGvCwDZ9TfzbF2ffXiov8CKE445L2Z1Ek2t/m4SKQ2j6Ipv7NyUolw==} + hastscript@9.0.1: + resolution: {integrity: sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w==} html-encoding-sniffer@4.0.0: resolution: {integrity: sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==} @@ -2419,8 +2371,8 @@ packages: html-void-elements@3.0.0: resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==} - html-whitespace-sensitive-tag-names@3.0.0: - resolution: {integrity: sha512-KlClZ3/Qy5UgvpvVvDomGhnQhNWH5INE8GwvSIQ9CWt1K0zbbXrl7eN5bWaafOZgtmO3jMPwUqmrmEwinhPq1w==} + html-whitespace-sensitive-tag-names@3.0.1: + resolution: {integrity: sha512-q+310vW8zmymYHALr1da4HyXUQ0zgiIwIicEfotYPWGN0OJVEN/58IJ3A4GBYcEq3LGAZqKb+ugvP0GNB9CEAA==} http-cache-semantics@4.1.1: resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==} @@ -2433,8 +2385,8 @@ packages: resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} engines: {node: '>= 14'} - i18next@23.15.1: - resolution: {integrity: sha512-wB4abZ3uK7EWodYisHl/asf8UYEhrI/vj/8aoSsrj/ZDxj4/UXPOa1KvFt1Fq5hkUHquNqwFlDprmjZ8iySgYA==} + i18next@23.16.8: + resolution: {integrity: sha512-06r/TitrM88Mg5FdUXAKL96dJMzgqLE5dv3ryBAra4KCwD9mJ4ndOTS95ZuymIGoE+2hzfdaMak2X11/es7ZWg==} iconv-lite@0.6.3: resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} @@ -2443,8 +2395,8 @@ packages: idb@7.1.1: resolution: {integrity: sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==} - immutable@5.0.3: - resolution: {integrity: sha512-P8IdPQHq3lA1xVeBRi5VPqUm5HDgKnx0Ru51wZz5mjxHr5n3RWhjIpOFU7ybkUxfB+5IToy+OLaHYDBIWsv+uw==} + immutable@5.1.1: + resolution: {integrity: sha512-3jatXi9ObIsPGr3N5hGw/vWWcTkq6hUYhpQz4k0wLC+owqWi/LiugIw9x0EdNZ2yGedKN/HzePiBvaJRXa0Ujg==} import-meta-resolve@4.1.0: resolution: {integrity: sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw==} @@ -2456,14 +2408,11 @@ packages: inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - inline-style-parser@0.1.1: - resolution: {integrity: sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==} - inline-style-parser@0.2.4: resolution: {integrity: sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q==} - internal-slot@1.0.7: - resolution: {integrity: sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==} + internal-slot@1.1.0: + resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} engines: {node: '>= 0.4'} is-absolute-url@4.0.1: @@ -2476,34 +2425,39 @@ packages: is-alphanumerical@2.0.1: resolution: {integrity: sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==} - is-array-buffer@3.0.4: - resolution: {integrity: sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==} + is-array-buffer@3.0.5: + resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==} engines: {node: '>= 0.4'} is-arrayish@0.3.2: resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} - is-bigint@1.0.4: - resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} + is-async-function@2.1.1: + resolution: {integrity: sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==} + engines: {node: '>= 0.4'} + + is-bigint@1.1.0: + resolution: {integrity: sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==} + engines: {node: '>= 0.4'} - is-boolean-object@1.1.2: - resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} + is-boolean-object@1.2.2: + resolution: {integrity: sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==} engines: {node: '>= 0.4'} is-callable@1.2.7: resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} engines: {node: '>= 0.4'} - is-core-module@2.14.0: - resolution: {integrity: sha512-a5dFJih5ZLYlRtDc0dZWP7RiKr6xIKzmn/oAYCDvdLThadVgyJwlaoQPmRtMSpz+rk0OGAgIu+TcM9HUF0fk1A==} + is-core-module@2.16.1: + resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} engines: {node: '>= 0.4'} - is-data-view@1.0.1: - resolution: {integrity: sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==} + is-data-view@1.0.2: + resolution: {integrity: sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==} engines: {node: '>= 0.4'} - is-date-object@1.0.5: - resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} + is-date-object@1.1.0: + resolution: {integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==} engines: {node: '>= 0.4'} is-decimal@2.0.1: @@ -2522,10 +2476,18 @@ packages: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} + is-finalizationregistry@1.1.1: + resolution: {integrity: sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==} + engines: {node: '>= 0.4'} + is-fullwidth-code-point@3.0.0: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} + is-generator-function@1.1.0: + resolution: {integrity: sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==} + engines: {node: '>= 0.4'} + is-glob@4.0.3: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} @@ -2542,15 +2504,15 @@ packages: resolution: {integrity: sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==} engines: {node: '>=12'} + is-map@2.0.3: + resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} + engines: {node: '>= 0.4'} + is-module@1.0.0: resolution: {integrity: sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==} - is-negative-zero@2.0.3: - resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==} - engines: {node: '>= 0.4'} - - is-number-object@1.0.7: - resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} + is-number-object@1.1.1: + resolution: {integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==} engines: {node: '>= 0.4'} is-number@7.0.0: @@ -2568,32 +2530,36 @@ packages: is-potential-custom-element-name@1.0.1: resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} - is-regex@1.1.4: - resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} + is-regex@1.2.1: + resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==} engines: {node: '>= 0.4'} is-regexp@1.0.0: resolution: {integrity: sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==} engines: {node: '>=0.10.0'} - is-shared-array-buffer@1.0.3: - resolution: {integrity: sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==} + is-set@2.0.3: + resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==} + engines: {node: '>= 0.4'} + + is-shared-array-buffer@1.0.4: + resolution: {integrity: sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==} engines: {node: '>= 0.4'} is-stream@2.0.1: resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} engines: {node: '>=8'} - is-string@1.0.7: - resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} + is-string@1.1.1: + resolution: {integrity: sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==} engines: {node: '>= 0.4'} - is-symbol@1.0.4: - resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} + is-symbol@1.1.1: + resolution: {integrity: sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==} engines: {node: '>= 0.4'} - is-typed-array@1.1.13: - resolution: {integrity: sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==} + is-typed-array@1.1.15: + resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==} engines: {node: '>= 0.4'} is-unicode-supported@1.3.0: @@ -2604,8 +2570,17 @@ packages: resolution: {integrity: sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==} engines: {node: '>=18'} - is-weakref@1.0.2: - resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} + is-weakmap@2.0.2: + resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} + engines: {node: '>= 0.4'} + + is-weakref@1.1.1: + resolution: {integrity: sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==} + engines: {node: '>= 0.4'} + + is-weakset@2.0.4: + resolution: {integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==} + engines: {node: '>= 0.4'} is-wsl@3.1.0: resolution: {integrity: sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==} @@ -2614,8 +2589,8 @@ packages: isarray@2.0.5: resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} - jake@10.9.1: - resolution: {integrity: sha512-61btcOHNnLnsOdtLgA5efqQWjnSi/vow5HbI7HMdKKWqvrKR1bLK3BPlJn9gcSaP2ewuamUSMB5XEy76KUIS2w==} + jake@10.9.2: + resolution: {integrity: sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==} engines: {node: '>=10'} hasBin: true @@ -2623,8 +2598,8 @@ packages: resolution: {integrity: sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==} engines: {node: '>= 10.13.0'} - jiti@1.21.6: - resolution: {integrity: sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==} + jiti@1.21.7: + resolution: {integrity: sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==} hasBin: true js-tokens@4.0.0: @@ -2647,15 +2622,16 @@ packages: canvas: optional: true - jsesc@0.5.0: - resolution: {integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==} - hasBin: true - jsesc@3.0.2: resolution: {integrity: sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==} engines: {node: '>=6'} hasBin: true + jsesc@3.1.0: + resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} + engines: {node: '>=6'} + hasBin: true + json-schema-traverse@1.0.0: resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} @@ -2717,9 +2693,8 @@ packages: longest-streak@3.1.0: resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==} - lru-cache@11.0.2: - resolution: {integrity: sha512-123qHRfJBmo2jXDbo/a5YOQrJoHF/GNQTLzQ5+IdK5pWpceK17yRc6ozlWd25FxvGKQbIUs91fDFkXmDHTKcyA==} - engines: {node: 20 || >=22} + lru-cache@10.4.3: + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} @@ -2730,8 +2705,8 @@ packages: magic-string@0.25.9: resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==} - magic-string@0.30.14: - resolution: {integrity: sha512-5c99P1WKTed11ZC0HMJOj6CDIue6F8ySu+bJL+85q1zBEIY8IklrJ1eiKC2NDRh3Ct3FcvmJPyQHb9erXMTJNw==} + magic-string@0.30.17: + resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==} magicast@0.3.5: resolution: {integrity: sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==} @@ -2744,8 +2719,8 @@ packages: resolution: {integrity: sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==} hasBin: true - markdown-table@3.0.3: - resolution: {integrity: sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw==} + markdown-table@3.0.4: + resolution: {integrity: sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==} marked-footnote@1.2.4: resolution: {integrity: sha512-DB2Kl+wFh6YwZd70qABMY6WUkG1UuyqoNTFoDfGyG79Pz24neYtLBkB+45a7o72V7gkfvbC3CGzIYFobxfMT1Q==} @@ -2757,33 +2732,37 @@ packages: peerDependencies: marked: '>=7.0.0' - marked-smartypants@1.1.8: - resolution: {integrity: sha512-2n8oSjL2gSkH6M0dSdRIyLgqqky03iKQkdmoaylmIzwIhYTW204S7ry6zP2iqwSl0zSlJH2xmWgxlZ/4XB1CdQ==} + marked-smartypants@1.1.9: + resolution: {integrity: sha512-VPeuaUr5IWptI7nJdgQ9ugrLWYGv13NdzEXTtKY3cmB4aRWOI2RzhLlf+xQp6Wnob9SAPO2sNVlfSJr+nflk/A==} peerDependencies: - marked: '>=4 <15' + marked: '>=4 <16' marked@12.0.2: resolution: {integrity: sha512-qXUm7e/YKFoqFPYPa3Ukg9xlI5cyAtGmyEIzMfW//m6kXwCy2Ps9DYf5ioijFKQ8qyuscrHoY04iJGctu2Kg0Q==} engines: {node: '>= 18'} hasBin: true + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + mdast-util-definitions@6.0.0: resolution: {integrity: sha512-scTllyX6pnYNZH/AIp/0ePz6s4cZtARxImwoPJ7kS42n+MnVsI4XbnG6d4ibehRIldYMWM2LD7ImQblVhUejVQ==} - mdast-util-directive@3.0.0: - resolution: {integrity: sha512-JUpYOqKI4mM3sZcNxmF/ox04XYFFkNwr0CFlrQIkCwbvH0xzMCqkMqAde9wRd80VAhaUrwFwKm2nxretdT1h7Q==} + mdast-util-directive@3.1.0: + resolution: {integrity: sha512-I3fNFt+DHmpWCYAT7quoM6lHf9wuqtI+oCOfvILnoicNIqjh5E3dEJWiXuYME2gNe8vl1iMQwyUHa7bgFmak6Q==} - mdast-util-find-and-replace@3.0.1: - resolution: {integrity: sha512-SG21kZHGC3XRTSUhtofZkBzZTJNM5ecCi0SK2IMKmSXR8vO3peL+kb1O0z7Zl83jKtutG4k5Wv/W7V3/YHvzPA==} + mdast-util-find-and-replace@3.0.2: + resolution: {integrity: sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==} - mdast-util-from-markdown@2.0.1: - resolution: {integrity: sha512-aJEUyzZ6TzlsX2s5B4Of7lN7EQtAxvtradMMglCQDyaTFgse6CmtmdJ15ElnVRlCg1vpNyVtbem0PWzlNieZsA==} + mdast-util-from-markdown@2.0.2: + resolution: {integrity: sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==} mdast-util-gfm-autolink-literal@2.0.1: resolution: {integrity: sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==} - mdast-util-gfm-footnote@2.0.0: - resolution: {integrity: sha512-5jOT2boTSVkMnQ7LTrd6n/18kqwjmuYqo7JUPe+tRCY6O7dAuTFMtTPauYYrMPpox9hlN0uOx/FL8XvEfG9/mQ==} + mdast-util-gfm-footnote@2.1.0: + resolution: {integrity: sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ==} mdast-util-gfm-strikethrough@2.0.0: resolution: {integrity: sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==} @@ -2794,14 +2773,14 @@ packages: mdast-util-gfm-task-list-item@2.0.0: resolution: {integrity: sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==} - mdast-util-gfm@3.0.0: - resolution: {integrity: sha512-dgQEX5Amaq+DuUqf26jJqSK9qgixgd6rYDHAv4aTBuA92cTknZlKpPfa86Z/s8Dj8xsAQpFfBmPUHWJBWqS4Bw==} + mdast-util-gfm@3.1.0: + resolution: {integrity: sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==} mdast-util-mdx-expression@2.0.1: resolution: {integrity: sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==} - mdast-util-mdx-jsx@3.1.3: - resolution: {integrity: sha512-bfOjvNt+1AcbPLTFMFWY149nJz0OjmewJs3LQQ5pIyVGxP4CdOqNVJL6kTaM5c68p8q82Xv3nCyFfUnuEcH3UQ==} + mdast-util-mdx-jsx@3.2.0: + resolution: {integrity: sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==} mdast-util-mdx@3.0.0: resolution: {integrity: sha512-JfbYLAW7XnYTTbUsmpu0kdBUVe+yKVJZBItEjwyYJiDJuZ9w4eeaqks4HQO+R7objWgS2ymV60GYpI14Ug554w==} @@ -2815,8 +2794,8 @@ packages: mdast-util-to-hast@13.2.0: resolution: {integrity: sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==} - mdast-util-to-markdown@2.1.0: - resolution: {integrity: sha512-SR2VnIEdVNCJbP6y7kVTJgPLifdr8WEU440fQec7qHoHOUz/oJ2jmNRqdDQ3rbiStOXb2mCDGTuwsK5OPUgYlQ==} + mdast-util-to-markdown@2.1.2: + resolution: {integrity: sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==} mdast-util-to-string@4.0.0: resolution: {integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==} @@ -2831,8 +2810,8 @@ packages: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} - micromark-core-commonmark@2.0.1: - resolution: {integrity: sha512-CUQyKr1e///ZODyD1U3xit6zXwy1a8q2a1S1HKtIlmgvurrEpaw/Y9y6KSIbF8P59cn/NjzHyO+Q2fAyYLQrAA==} + micromark-core-commonmark@2.0.3: + resolution: {integrity: sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==} micromark-extension-directive@3.0.2: resolution: {integrity: sha512-wjcXHgk+PPdmvR58Le9d7zQYWy+vKEU9Se44p2CrCDPiLr2FMyiT4Fyb5UFKFC66wGB3kPlgD7q3TnoqPS7SZA==} @@ -2846,8 +2825,8 @@ packages: micromark-extension-gfm-strikethrough@2.1.0: resolution: {integrity: sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==} - micromark-extension-gfm-table@2.1.0: - resolution: {integrity: sha512-Ub2ncQv+fwD70/l4ou27b4YzfNaCJOvyX4HxXU15m7mpYY+rjuWzsLIPZHJL253Z643RpbcP1oeIJlQ/SKW67g==} + micromark-extension-gfm-table@2.1.1: + resolution: {integrity: sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==} micromark-extension-gfm-tagfilter@2.0.0: resolution: {integrity: sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==} @@ -2858,11 +2837,11 @@ packages: micromark-extension-gfm@3.0.0: resolution: {integrity: sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==} - micromark-extension-mdx-expression@3.0.0: - resolution: {integrity: sha512-sI0nwhUDz97xyzqJAbHQhp5TfaxEvZZZ2JDqUo+7NvyIYG6BZ5CPPqj2ogUoPJlmXHBnyZUzISg9+oUmU6tUjQ==} + micromark-extension-mdx-expression@3.0.1: + resolution: {integrity: sha512-dD/ADLJ1AeMvSAKBwO22zG22N4ybhe7kFIZ3LsDI0GlsNr2A3KYxb0LdC1u5rj4Nw+CHKY0RVdnHX8vj8ejm4Q==} - micromark-extension-mdx-jsx@3.0.1: - resolution: {integrity: sha512-vNuFb9czP8QCtAQcEJn0UJQJZA8Dk6DXKBqx+bg/w0WGuSxDxNr7hErW89tHUY31dUW4NqEOWwmEUNhjTFmHkg==} + micromark-extension-mdx-jsx@3.0.2: + resolution: {integrity: sha512-e5+q1DjMh62LZAJOnDraSSbDMvGJ8x3cbjygy2qFEi7HCeUT4BDKCvMozPozcD6WmOt6sVvYDNBKhFSz3kjOVQ==} micromark-extension-mdx-md@2.0.0: resolution: {integrity: sha512-EpAiszsB3blw4Rpba7xTOUptcFeBFi+6PY8VnJ2hhimH+vCQDirWgsMpz7w1XcZE7LVrSAUGb9VJpG9ghlYvYQ==} @@ -2873,71 +2852,71 @@ packages: micromark-extension-mdxjs@3.0.0: resolution: {integrity: sha512-A873fJfhnJ2siZyUrJ31l34Uqwy4xIFmvPY1oj+Ean5PHcPBYzEsvqvWGaWcfEIr11O5Dlw3p2y0tZWpKHDejQ==} - micromark-factory-destination@2.0.0: - resolution: {integrity: sha512-j9DGrQLm/Uhl2tCzcbLhy5kXsgkHUrjJHg4fFAeoMRwJmJerT9aw4FEhIbZStWN8A3qMwOp1uzHr4UL8AInxtA==} + micromark-factory-destination@2.0.1: + resolution: {integrity: sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==} - micromark-factory-label@2.0.0: - resolution: {integrity: sha512-RR3i96ohZGde//4WSe/dJsxOX6vxIg9TimLAS3i4EhBAFx8Sm5SmqVfR8E87DPSR31nEAjZfbt91OMZWcNgdZw==} + micromark-factory-label@2.0.1: + resolution: {integrity: sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==} - micromark-factory-mdx-expression@2.0.2: - resolution: {integrity: sha512-5E5I2pFzJyg2CtemqAbcyCktpHXuJbABnsb32wX2U8IQKhhVFBqkcZR5LRm1WVoFqa4kTueZK4abep7wdo9nrw==} + micromark-factory-mdx-expression@2.0.3: + resolution: {integrity: sha512-kQnEtA3vzucU2BkrIa8/VaSAsP+EJ3CKOvhMuJgOEGg9KDC6OAY6nSnNDVRiVNRqj7Y4SlSzcStaH/5jge8JdQ==} - micromark-factory-space@2.0.0: - resolution: {integrity: sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==} + micromark-factory-space@2.0.1: + resolution: {integrity: sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==} - micromark-factory-title@2.0.0: - resolution: {integrity: sha512-jY8CSxmpWLOxS+t8W+FG3Xigc0RDQA9bKMY/EwILvsesiRniiVMejYTE4wumNc2f4UbAa4WsHqe3J1QS1sli+A==} + micromark-factory-title@2.0.1: + resolution: {integrity: sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==} - micromark-factory-whitespace@2.0.0: - resolution: {integrity: sha512-28kbwaBjc5yAI1XadbdPYHX/eDnqaUFVikLwrO7FDnKG7lpgxnvk/XGRhX/PN0mOZ+dBSZ+LgunHS+6tYQAzhA==} + micromark-factory-whitespace@2.0.1: + resolution: {integrity: sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==} - micromark-util-character@2.1.0: - resolution: {integrity: sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==} + micromark-util-character@2.1.1: + resolution: {integrity: sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==} - micromark-util-chunked@2.0.0: - resolution: {integrity: sha512-anK8SWmNphkXdaKgz5hJvGa7l00qmcaUQoMYsBwDlSKFKjc6gjGXPDw3FNL3Nbwq5L8gE+RCbGqTw49FK5Qyvg==} + micromark-util-chunked@2.0.1: + resolution: {integrity: sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==} - micromark-util-classify-character@2.0.0: - resolution: {integrity: sha512-S0ze2R9GH+fu41FA7pbSqNWObo/kzwf8rN/+IGlW/4tC6oACOs8B++bh+i9bVyNnwCcuksbFwsBme5OCKXCwIw==} + micromark-util-classify-character@2.0.1: + resolution: {integrity: sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==} - micromark-util-combine-extensions@2.0.0: - resolution: {integrity: sha512-vZZio48k7ON0fVS3CUgFatWHoKbbLTK/rT7pzpJ4Bjp5JjkZeasRfrS9wsBdDJK2cJLHMckXZdzPSSr1B8a4oQ==} + micromark-util-combine-extensions@2.0.1: + resolution: {integrity: sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==} - micromark-util-decode-numeric-character-reference@2.0.1: - resolution: {integrity: sha512-bmkNc7z8Wn6kgjZmVHOX3SowGmVdhYS7yBpMnuMnPzDq/6xwVA604DuOXMZTO1lvq01g+Adfa0pE2UKGlxL1XQ==} + micromark-util-decode-numeric-character-reference@2.0.2: + resolution: {integrity: sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==} - micromark-util-decode-string@2.0.0: - resolution: {integrity: sha512-r4Sc6leeUTn3P6gk20aFMj2ntPwn6qpDZqWvYmAG6NgvFTIlj4WtrAudLi65qYoaGdXYViXYw2pkmn7QnIFasA==} + micromark-util-decode-string@2.0.1: + resolution: {integrity: sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==} - micromark-util-encode@2.0.0: - resolution: {integrity: sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA==} + micromark-util-encode@2.0.1: + resolution: {integrity: sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==} - micromark-util-events-to-acorn@2.0.2: - resolution: {integrity: sha512-Fk+xmBrOv9QZnEDguL9OI9/NQQp6Hz4FuQ4YmCb/5V7+9eAh1s6AYSvL20kHkD67YIg7EpE54TiSlcsf3vyZgA==} + micromark-util-events-to-acorn@2.0.3: + resolution: {integrity: sha512-jmsiEIiZ1n7X1Rr5k8wVExBQCg5jy4UXVADItHmNk1zkwEVhBuIUKRu3fqv+hs4nxLISi2DQGlqIOGiFxgbfHg==} - micromark-util-html-tag-name@2.0.0: - resolution: {integrity: sha512-xNn4Pqkj2puRhKdKTm8t1YHC/BAjx6CEwRFXntTaRf/x16aqka6ouVoutm+QdkISTlT7e2zU7U4ZdlDLJd2Mcw==} + micromark-util-html-tag-name@2.0.1: + resolution: {integrity: sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==} - micromark-util-normalize-identifier@2.0.0: - resolution: {integrity: sha512-2xhYT0sfo85FMrUPtHcPo2rrp1lwbDEEzpx7jiH2xXJLqBuy4H0GgXk5ToU8IEwoROtXuL8ND0ttVa4rNqYK3w==} + micromark-util-normalize-identifier@2.0.1: + resolution: {integrity: sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==} - micromark-util-resolve-all@2.0.0: - resolution: {integrity: sha512-6KU6qO7DZ7GJkaCgwBNtplXCvGkJToU86ybBAUdavvgsCiG8lSSvYxr9MhwmQ+udpzywHsl4RpGJsYWG1pDOcA==} + micromark-util-resolve-all@2.0.1: + resolution: {integrity: sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==} - micromark-util-sanitize-uri@2.0.0: - resolution: {integrity: sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw==} + micromark-util-sanitize-uri@2.0.1: + resolution: {integrity: sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==} - micromark-util-subtokenize@2.0.1: - resolution: {integrity: sha512-jZNtiFl/1aY73yS3UGQkutD0UbhTt68qnRpw2Pifmz5wV9h8gOVsN70v+Lq/f1rKaU/W8pxRe8y8Q9FX1AOe1Q==} + micromark-util-subtokenize@2.1.0: + resolution: {integrity: sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==} - micromark-util-symbol@2.0.0: - resolution: {integrity: sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==} + micromark-util-symbol@2.0.1: + resolution: {integrity: sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==} - micromark-util-types@2.0.0: - resolution: {integrity: sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w==} + micromark-util-types@2.0.2: + resolution: {integrity: sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==} - micromark@4.0.0: - resolution: {integrity: sha512-o/sd0nMof8kYff+TqcDx3VSrgBTcZpSvYcAHIfHhv5VAuNmisCxjhx6YmxS8PFEpb9z5WKWKPdzf0jM23ro3RQ==} + micromark@4.0.2: + resolution: {integrity: sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==} micromatch@4.0.8: resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} @@ -2966,15 +2945,15 @@ packages: resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} engines: {node: '>=16 || 14 >=14.17'} - mrmime@2.0.0: - resolution: {integrity: sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==} + mrmime@2.0.1: + resolution: {integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==} engines: {node: '>=10'} ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - nanoid@3.3.8: - resolution: {integrity: sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==} + nanoid@3.3.11: + resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true @@ -2988,27 +2967,25 @@ packages: node-addon-api@7.1.1: resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==} - node-releases@2.0.18: - resolution: {integrity: sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==} - - not@0.1.0: - resolution: {integrity: sha512-5PDmaAsVfnWUgTUbJ3ERwn7u79Z0dYxN9ErxCpVJJqe2RK0PJ3z+iFUxuqjwtlDDegXvtWoxD/3Fzxox7tFGWA==} + node-releases@2.0.19: + resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==} nth-check@2.1.1: resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} - nwsapi@2.2.16: - resolution: {integrity: sha512-F1I/bimDpj3ncaNDhfyMWuFqmQDBwDB0Fogc2qpL3BWvkQteFD/8BzWuIRl83rq0DXfm8SGt/HFhLXZyljTXcQ==} + nwsapi@2.2.19: + resolution: {integrity: sha512-94bcyI3RsqiZufXjkr3ltkI86iEl+I7uiHVDtcq9wJUTwYQJ5odHDeSzkkrRzi80jJ8MaeZgqKjH1bAWAFw9bA==} - object-inspect@1.13.1: - resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==} + object-inspect@1.13.4: + resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} + engines: {node: '>= 0.4'} object-keys@1.1.1: resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} engines: {node: '>= 0.4'} - object.assign@4.1.5: - resolution: {integrity: sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==} + object.assign@4.1.7: + resolution: {integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==} engines: {node: '>= 0.4'} once@1.4.0: @@ -3018,43 +2995,47 @@ packages: resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==} engines: {node: '>=18'} - oniguruma-to-es@0.10.0: - resolution: {integrity: sha512-zapyOUOCJxt+xhiNRPPMtfJkHGsZ98HHB9qJEkdT8BGytO/+kpe4m1Ngf0MzbzTmhacn11w9yGeDP6tzDhnCdg==} + oniguruma-to-es@2.3.0: + resolution: {integrity: sha512-bwALDxriqfKGfUufKGGepCzu9x7nJQuoRoAFp4AnwehhC2crqrDIAP/uN2qdlsAvSMpeRC3+Yzhqc7hLmle5+g==} - ora@8.1.1: - resolution: {integrity: sha512-YWielGi1XzG1UTvOaCFaNgEnuhZVMSHYkW/FQ7UX8O26PtlpdM84c0f7wLPlkvx2RfiQmnzd61d/MGxmpQeJPw==} + ora@8.2.0: + resolution: {integrity: sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw==} engines: {node: '>=18'} + own-keys@1.0.1: + resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==} + engines: {node: '>= 0.4'} + p-limit@2.3.0: resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} engines: {node: '>=6'} - p-limit@6.1.0: - resolution: {integrity: sha512-H0jc0q1vOzlEk0TqAKXKZxdl7kX3OFUzCnNVUnq5Pc3DGo0kpeaMuPqxQn235HibwBEb0/pm9dgKTjXy66fBkg==} + p-limit@6.2.0: + resolution: {integrity: sha512-kuUqqHNUqoIWp/c467RI4X6mmyuojY5jGutNU0wVTmEOOfcuwLqyMVoAi9MKi2Ak+5i9+nhmrK4ufZE8069kHA==} engines: {node: '>=18'} p-locate@4.1.0: resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} engines: {node: '>=8'} - p-queue@8.0.1: - resolution: {integrity: sha512-NXzu9aQJTAzbBqOt2hwsR63ea7yvxJc0PwN/zobNAudYfb1B7R08SzB4TsLeSbUCuG467NhnoT0oO6w1qRO+BA==} + p-queue@8.1.0: + resolution: {integrity: sha512-mxLDbbGIBEXTJL0zEx8JIylaj3xQ7Z/7eEVjcF9fJX4DBiH9oqe+oahYnlKKxm0Ci9TlWTyhSHgygxMxjIB2jw==} engines: {node: '>=18'} - p-timeout@6.1.3: - resolution: {integrity: sha512-UJUyfKbwvr/uZSV6btANfb+0t/mOhKV/KXcCUTp8FcQI+v/0d+wXqH4htrW0E4rR6WiEO/EPvUFiV9D5OI4vlw==} + p-timeout@6.1.4: + resolution: {integrity: sha512-MyIV3ZA/PmyBN/ud8vV9XzwTrNtR4jFrObymZYnZqMmW0zA8Z17vnT0rBgFE/TlohB+YCHqXMgZzb3Csp49vqg==} engines: {node: '>=14.16'} p-try@2.2.0: resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} engines: {node: '>=6'} - pagefind@1.1.1: - resolution: {integrity: sha512-U2YR0dQN5B2fbIXrLtt/UXNS0yWSSYfePaad1KcBPTi0p+zRtsVjwmoPaMQgTks5DnHNbmDxyJUL5TGaLljK3A==} + pagefind@1.3.0: + resolution: {integrity: sha512-8KPLGT5g9s+olKMRTU9LFekLizkVIu9tes90O1/aigJ0T5LmyPqTzGJrETnSw3meSYg58YH7JTzhTTW/3z6VAw==} hasBin: true - parse-entities@4.0.1: - resolution: {integrity: sha512-SWzvYcSJh4d/SGLIOQfZ/CoNv6BTlI6YEQ7Nj82oDVnRpwe/Z/F1EMx42x3JAOwGBlCjeCH0BRJQbQ/opHL17w==} + parse-entities@4.0.2: + resolution: {integrity: sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==} parse-latin@7.0.0: resolution: {integrity: sha512-mhHgobPPua5kZ98EF4HWiH167JWBfl4pvAIXXdbaVohtK7a6YBOy56kvhCqduqyo/f3yrHFWmqmiMg/BkBkYYQ==} @@ -3098,8 +3079,8 @@ packages: resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} engines: {node: '>=8'} - possible-typed-array-names@1.0.0: - resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} + possible-typed-array-names@1.1.0: + resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==} engines: {node: '>= 0.4'} postcss-nested@6.2.0: @@ -3112,20 +3093,20 @@ packages: resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==} engines: {node: '>=4'} - postcss@8.4.49: - resolution: {integrity: sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==} + postcss@8.5.3: + resolution: {integrity: sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==} engines: {node: ^10 || ^12 || >=14} - preferred-pm@4.0.0: - resolution: {integrity: sha512-gYBeFTZLu055D8Vv3cSPox/0iTPtkzxpLroSYYA7WXgRi31WCJ51Uyl8ZiPeUUjyvs2MBzK+S8v9JVUgHU/Sqw==} + preferred-pm@4.1.1: + resolution: {integrity: sha512-rU+ZAv1Ur9jAUZtGPebQVQPzdGhNzaEiQ7VL9+cjsAWPHFYOccNXPNiev1CCDSOg/2j7UujM7ojNhpkuILEVNQ==} engines: {node: '>=18.12'} prettier-plugin-astro@0.14.1: resolution: {integrity: sha512-RiBETaaP9veVstE4vUwSIcdATj6dKmXljouXc/DDNwBSPTp8FRkLGDSGFClKsAFeeg+13SB0Z1JZvbD76bigJw==} engines: {node: ^14.15.0 || >=16.0.0} - prettier@3.4.2: - resolution: {integrity: sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==} + prettier@3.5.3: + resolution: {integrity: sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==} engines: {node: '>=14'} hasBin: true @@ -3133,8 +3114,8 @@ packages: resolution: {integrity: sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==} engines: {node: '>=6'} - prismjs@1.29.0: - resolution: {integrity: sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==} + prismjs@1.30.0: + resolution: {integrity: sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==} engines: {node: '>=6'} prompts@2.4.2: @@ -3144,6 +3125,9 @@ packages: property-information@6.5.0: resolution: {integrity: sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==} + property-information@7.0.0: + resolution: {integrity: sha512-7D/qOz/+Y4X/rzSB6jKxKUsQnphO046ei8qxG59mtM3RG3DHgTK81HrxrmoDVINJb8NKT5ZsRbwHvQ6B68Iyhg==} + punycode.js@2.3.1: resolution: {integrity: sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==} engines: {node: '>=6'} @@ -3158,12 +3142,12 @@ packages: randombytes@2.1.0: resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} - readdirp@4.1.1: - resolution: {integrity: sha512-h80JrZu/MHUZCyHu5ciuoI0+WxsCxzxJTILn6Fs8rxSnFPh+UVHYfeIxK1nVGugMqkfC4vJcBOYbkfkwYK0+gw==} + readdirp@4.1.2: + resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} engines: {node: '>= 14.18.0'} - recast@0.23.9: - resolution: {integrity: sha512-Hx/BGIbwj+Des3+xy5uAtAbdCyqK9y9wbBcDFDYanLS9JnMqf7OeF87HQwUimE87OEc72mr6tkKUKMBBL+hF9Q==} + recast@0.23.11: + resolution: {integrity: sha512-YTUo+Flmw4ZXiWfQKGcwwc11KnoRAYgzAE2E7mXKCjSviTKShtxBsN6YUUBB2gtaBzKzeKunxhUwNHQuRryhWA==} engines: {node: '>= 4'} recma-build-jsx@1.0.0: @@ -3178,8 +3162,12 @@ packages: recma-stringify@1.0.0: resolution: {integrity: sha512-cjwII1MdIIVloKvC9ErQ+OgAtwHBmcZ0Bg4ciz78FtbT8In39aAYbaA7zvxQ61xVMSPE8WxhLwLbhif4Js2C+g==} - regenerate-unicode-properties@10.1.1: - resolution: {integrity: sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==} + reflect.getprototypeof@1.0.10: + resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==} + engines: {node: '>= 0.4'} + + regenerate-unicode-properties@10.2.0: + resolution: {integrity: sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA==} engines: {node: '>=4'} regenerate@1.4.2: @@ -3200,16 +3188,19 @@ packages: regex@5.1.1: resolution: {integrity: sha512-dN5I359AVGPnwzJm2jN1k0W9LPZ+ePvoOeVMMfqIMFz53sSwXkxaJoxr50ptnsC771lK95BnTrVSZxq0b9yCGw==} - regexp.prototype.flags@1.5.2: - resolution: {integrity: sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==} + regexp.prototype.flags@1.5.4: + resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==} engines: {node: '>= 0.4'} - regexpu-core@5.3.2: - resolution: {integrity: sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==} + regexpu-core@6.2.0: + resolution: {integrity: sha512-H66BPQMrv+V16t8xtmq+UC0CBpiTBA60V8ibS1QVReIp8T1z8hwFxqcGzm9K6lgsN7sB5edVH8a+ze6Fqm4weA==} engines: {node: '>=4'} - regjsparser@0.9.1: - resolution: {integrity: sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==} + regjsgen@0.8.0: + resolution: {integrity: sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==} + + regjsparser@0.12.0: + resolution: {integrity: sha512-cnE+y8bz4NhMjISKbgeVJtqNbtf5QpjZP+Bslo+UqkIt9QPnX9q095eiRRASJG1/tz6dlNr6Z5NsBiWYokp6EQ==} hasBin: true rehype-autolink-headings@7.1.0: @@ -3236,14 +3227,14 @@ packages: rehype@13.0.2: resolution: {integrity: sha512-j31mdaRFrwFRUIlxGeuPXXKWQxet52RBQRvCmzl5eCefn/KGbomK5GMHNMsOJf55fgo3qw5tST5neDuarDYR2A==} - remark-directive@3.0.0: - resolution: {integrity: sha512-l1UyWJ6Eg1VPU7Hm/9tt0zKtReJQNOA4+iDMAxTyZNWnJnFlbS/7zhiel/rogTLQ2vMYwDzSJa4BiVNqGlqIMA==} + remark-directive@3.0.1: + resolution: {integrity: sha512-gwglrEQEZcZYgVyG1tQuA+h58EZfq5CSULw7J90AFuCTyib1thgHPoqQ+h9iFvU6R+vnZ5oNFQR5QKgGpk741A==} - remark-gfm@4.0.0: - resolution: {integrity: sha512-U92vJgBPkbw4Zfu/IiW2oTZLSL3Zpv+uI7My2eq8JxKgqraFdU8YUGicEJCEgSbeaG+QDFqIcwwfMTOEelPxuA==} + remark-gfm@4.0.1: + resolution: {integrity: sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==} - remark-mdx@3.0.1: - resolution: {integrity: sha512-3Pz3yPQ5Rht2pM5R+0J2MrGoBSrzf+tJG94N+t/ilfdh8YLyyKYtidAYwTveB20BoHAcwIopOUqhcmh2F7hGYA==} + remark-mdx@3.1.0: + resolution: {integrity: sha512-Ngl/H3YXyBV9RcRNdlYsZujAmhsxwzxpDzpDEhFBVAGthS4GDgnctpDjgFl/ULx5UEDzqtW1cyBSNKqYYrqLBA==} remark-parse@11.0.0: resolution: {integrity: sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==} @@ -3262,8 +3253,9 @@ packages: resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} engines: {node: '>=0.10.0'} - resolve@1.22.8: - resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} + resolve@1.22.10: + resolution: {integrity: sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==} + engines: {node: '>= 0.4'} hasBin: true restore-cursor@5.1.0: @@ -3282,8 +3274,8 @@ packages: retext@9.0.0: resolution: {integrity: sha512-sbMDcpHCNjvlheSgMfEcVrZko3cDzdbe1x/e7G66dFp0Ff7Mldvi2uv6JkJQzdRcvLYE8CA8Oe8siQx8ZOgTcA==} - reusify@1.0.4: - resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + reusify@1.1.0: + resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} rollup-plugin-terser@7.0.2: @@ -3292,13 +3284,13 @@ packages: peerDependencies: rollup: ^2.0.0 - rollup@2.79.1: - resolution: {integrity: sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==} + rollup@2.79.2: + resolution: {integrity: sha512-fS6iqSPZDs3dr/y7Od6y5nha8dW1YnbgtsyotCVvoFGKbERG++CVRFv1meyGDE1SNItQA8BrnCw7ScdAhRJ3XQ==} engines: {node: '>=10.0.0'} hasBin: true - rollup@4.28.0: - resolution: {integrity: sha512-G9GOrmgWHBma4YfCcX8PjH0qhXSdH8B4HDE2o4/jaxj93S4DPCIDoLcXz99eWMji4hB29UFCEd7B2gwGJDR9cQ==} + rollup@4.37.0: + resolution: {integrity: sha512-iAtQy/L4QFU+rTJ1YUjXqJOJzuwEghqWzCEYD2FEghT7Gsy1VdABntrO4CLopA5IkflTyqNiLNwPcOJ3S7UKLg==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true @@ -3311,15 +3303,19 @@ packages: s.color@0.0.15: resolution: {integrity: sha512-AUNrbEUHeKY8XsYr/DYpl+qk5+aM+DChopnWOPEzn8YKzOhv4l2zH6LzZms3tOZP3wwdOyc0RmTciyi46HLIuA==} - safe-array-concat@1.1.2: - resolution: {integrity: sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==} + safe-array-concat@1.1.3: + resolution: {integrity: sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==} engines: {node: '>=0.4'} safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - safe-regex-test@1.0.3: - resolution: {integrity: sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==} + safe-push-apply@1.0.0: + resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==} + engines: {node: '>= 0.4'} + + safe-regex-test@1.1.0: + resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==} engines: {node: '>= 0.4'} safer-buffer@2.1.2: @@ -3328,8 +3324,8 @@ packages: sass-formatter@0.7.9: resolution: {integrity: sha512-CWZ8XiSim+fJVG0cFLStwDvft1VI7uvXdCNJYXhDvowiv+DsbD1nXLiQ4zrE5UBvj5DWZJ93cwN0NX5PMsr1Pw==} - sass@1.83.4: - resolution: {integrity: sha512-B1bozCeNQiOgDcLd33e2Cs2U60wZwjUUXzh900ZyQF5qUasvMdDZYbQ566LJu7cqR+sAHlAfO6RMkaID5s6qpA==} + sass@1.86.0: + resolution: {integrity: sha512-zV8vGUld/+mP4KbMLJMX7TyGCuUp7hnkOScgCMsWuHtns8CWBoz+vmEhoGMXsaJrbUP8gj+F1dLvVe79sK8UdA==} engines: {node: '>=14.0.0'} hasBin: true @@ -3353,6 +3349,11 @@ packages: engines: {node: '>=10'} hasBin: true + semver@7.7.1: + resolution: {integrity: sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==} + engines: {node: '>=10'} + hasBin: true + serialize-javascript@4.0.0: resolution: {integrity: sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==} @@ -3364,15 +3365,31 @@ packages: resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} engines: {node: '>= 0.4'} + set-proto@1.0.0: + resolution: {integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==} + engines: {node: '>= 0.4'} + sharp@0.33.5: resolution: {integrity: sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - shiki@1.26.1: - resolution: {integrity: sha512-Gqg6DSTk3wYqaZ5OaYtzjcdxcBvX5kCy24yvRJEgjT5U+WHlmqCThLuBUx0juyxQBi+6ug53IGeuQS07DWwpcw==} + shiki@1.29.2: + resolution: {integrity: sha512-njXuliz/cP+67jU2hukkxCNuH1yUi4QfdZZY+sMr5PPrIyXSu5iTb/qYC4BiWWB0vZ+7TbdvYUCeL23zpwCfbg==} + + side-channel-list@1.0.0: + resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==} + engines: {node: '>= 0.4'} + + side-channel-map@1.0.1: + resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} + engines: {node: '>= 0.4'} + + side-channel-weakmap@1.0.2: + resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} + engines: {node: '>= 0.4'} - side-channel@1.0.6: - resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==} + side-channel@1.1.0: + resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} engines: {node: '>= 0.4'} signal-exit@4.1.0: @@ -3388,9 +3405,9 @@ packages: sisteransi@1.0.5: resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} - sitemap@7.1.2: - resolution: {integrity: sha512-ARCqzHJ0p4gWt+j7NlU5eDlIO9+Rkr/JhPFZKKQ1l5GCus7rJH4UdrlVAh0xC/gDS/Qir2UMxqYNHtsKr2rpCw==} - engines: {node: '>=12.0.0', npm: '>=5.6.0'} + sitemap@8.0.0: + resolution: {integrity: sha512-+AbdxhM9kJsHtruUF39bwS/B0Fytw6Fr1o4ZAIAEqA6cke2xcoO2GleBw9Zw7nRzILVEgz7zBM5GiTJjie1G9A==} + engines: {node: '>=14.0.0', npm: '>=6.0.0'} hasBin: true smartypants@0.2.2: @@ -3454,16 +3471,17 @@ packages: resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} engines: {node: '>=18'} - string.prototype.matchall@4.0.11: - resolution: {integrity: sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==} + string.prototype.matchall@4.0.12: + resolution: {integrity: sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==} engines: {node: '>= 0.4'} - string.prototype.trim@1.2.9: - resolution: {integrity: sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==} + string.prototype.trim@1.2.10: + resolution: {integrity: sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==} engines: {node: '>= 0.4'} - string.prototype.trimend@1.0.8: - resolution: {integrity: sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==} + string.prototype.trimend@1.0.9: + resolution: {integrity: sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==} + engines: {node: '>= 0.4'} string.prototype.trimstart@1.0.8: resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} @@ -3496,11 +3514,11 @@ packages: resolution: {integrity: sha512-ZprKx+bBLXv067WTCALv8SSz5l2+XhpYCsVtSqlMnkAXMWDq+/ekVbl1ghqP9rUHTzv6sm/DwCOiYutU/yp1fw==} engines: {node: '>=10'} - strnum@1.0.5: - resolution: {integrity: sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==} + strnum@1.1.2: + resolution: {integrity: sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA==} - style-to-object@0.4.4: - resolution: {integrity: sha512-HYNoHZa2GorYNyqiCaBgsxvcJIn7OHq6inEga+E6Ke3m5JkoqpQbnFssk4jwe+K7AhGa2fcha4wSOf1Kn01dMg==} + style-to-js@1.1.16: + resolution: {integrity: sha512-/Q6ld50hKYPH3d/r6nr117TZkHR0w0kGGIVfpG9N6D8NymRPM9RqCUv4pRpJ62E5DqOYx2AFpbZMyCPnjQCnOw==} style-to-object@1.0.8: resolution: {integrity: sha512-xT47I/Eo0rwJmaXC4oilDGDWLohVhR6o/xAQcPQN8q6QBuZVL8qMYL85kLmST5cPjAorwvqIA4qXTRQoYHaL6g==} @@ -3527,37 +3545,37 @@ packages: resolution: {integrity: sha512-G13vtMYPT/J8A4X2SjdtBTphZlrp1gKv6hZiOjw14RCWg6GbHuQBGtjlx75xLbYV/wEc0D7G5K4rxKP/cXk8Bw==} engines: {node: '>=10'} - terser@5.31.0: - resolution: {integrity: sha512-Q1JFAoUKE5IMfI4Z/lkE/E6+SwgzO+x4tq4v1AyBLRj8VSYvRO6A/rQrPg1yud4g0En9EKI1TvFRF2tQFcoUkg==} + terser@5.39.0: + resolution: {integrity: sha512-LBAhFyLho16harJoWMg/nZsQYgTrg5jXOn2nCYjRUcZZEdE3qa2zb8QEDRUGVZBW4rlazf2fxkg8tztybTaqWw==} engines: {node: '>=10'} hasBin: true tiny-invariant@1.3.3: resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==} - tinyexec@0.3.1: - resolution: {integrity: sha512-WiCJLEECkO18gwqIp6+hJg0//p23HXp4S+gGtAKu3mI2F2/sXC4FvHvXvB0zJVVaTPhx1/tOwdbRsa1sOBIKqQ==} + tinyexec@0.3.2: + resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} - tldts-core@6.1.47: - resolution: {integrity: sha512-6SWyFMnlst1fEt7GQVAAu16EGgFK0cLouH/2Mk6Ftlwhv3Ol40L0dlpGMcnnNiiOMyD2EV/aF3S+U2nKvvLvrA==} + tldts-core@6.1.85: + resolution: {integrity: sha512-DTjUVvxckL1fIoPSb3KE7ISNtkWSawZdpfxGxwiIrZoO6EbHVDXXUIlIuWympPaeS+BLGyggozX/HTMsRAdsoA==} - tldts@6.1.47: - resolution: {integrity: sha512-R/K2tZ5MiY+mVrnSkNJkwqYT2vUv1lcT6wJvd2emGaMJ7PHUGRY4e3tUsdFCXgqxi2QgbHjL3yJgXCo40v9Hxw==} + tldts@6.1.85: + resolution: {integrity: sha512-gBdZ1RjCSevRPFix/hpaUWeak2/RNUZB4/8frF1r5uYMHjFptkiT0JXIebWvgI/0ZHXvxaUDDJshiA0j6GdL3w==} hasBin: true to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} - tough-cookie@5.0.0: - resolution: {integrity: sha512-FRKsF7cz96xIIeMZ82ehjC3xW2E+O2+v11udrDYewUbszngYhsGa8z6YUMMzO9QJZzzyd0nGGXnML/TReX6W8Q==} + tough-cookie@5.1.2: + resolution: {integrity: sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==} engines: {node: '>=16'} tr46@1.0.1: resolution: {integrity: sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==} - tr46@5.0.0: - resolution: {integrity: sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==} + tr46@5.1.0: + resolution: {integrity: sha512-IUWnUK7ADYR5Sl1fZlO1INDUhVhatWl7BtJWsIhwJ0UAK7ilzzIa8uIqOO/aYVWHZPJkKbEL+362wrzoeRF7bw==} engines: {node: '>=18'} trim-lines@3.0.1: @@ -3566,8 +3584,8 @@ packages: trough@2.2.0: resolution: {integrity: sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==} - tsconfck@3.1.4: - resolution: {integrity: sha512-kdqWFGVJqe+KGYvlSO9NIaWn9jT1Ny4oKVzAJsKii5eoE9snzTJzL4+MMVOMn+fikWGFmKEylcXL710V/kIPJQ==} + tsconfck@3.1.5: + resolution: {integrity: sha512-CLDfGgUp7XPswWnezWwsCRxNmgQjhYq3VXHM0/XIRxhVrKw0M1if9agzryh1QS3nxjCROvV+xWxoJO1YctzzWg==} engines: {node: ^18 || >=20} hasBin: true peerDependencies: @@ -3576,8 +3594,8 @@ packages: typescript: optional: true - tslib@2.6.3: - resolution: {integrity: sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==} + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} tsm@2.3.0: resolution: {integrity: sha512-++0HFnmmR+gMpDtKTnW3XJ4yv9kVGi20n+NfyQWB9qwJvTaIWY9kBmzek2YUQK5APTQ/1DTrXmm4QtFPmW9Rzw==} @@ -3588,24 +3606,24 @@ packages: resolution: {integrity: sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==} engines: {node: '>=10'} - type-fest@4.30.0: - resolution: {integrity: sha512-G6zXWS1dLj6eagy6sVhOMQiLtJdxQBHIA9Z6HFUNLOlr6MFOgzV8wvmidtPONfPtEUv0uZsy77XJNzTAfwPDaA==} + type-fest@4.38.0: + resolution: {integrity: sha512-2dBz5D5ycHIoliLYLi0Q2V7KRaDlH0uWIvmk7TYlAg5slqwiPv1ezJdZm1QEM0xgk29oYWMCbIG7E6gHpvChlg==} engines: {node: '>=16'} - typed-array-buffer@1.0.2: - resolution: {integrity: sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==} + typed-array-buffer@1.0.3: + resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==} engines: {node: '>= 0.4'} - typed-array-byte-length@1.0.1: - resolution: {integrity: sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==} + typed-array-byte-length@1.0.3: + resolution: {integrity: sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==} engines: {node: '>= 0.4'} - typed-array-byte-offset@1.0.2: - resolution: {integrity: sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==} + typed-array-byte-offset@1.0.4: + resolution: {integrity: sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==} engines: {node: '>= 0.4'} - typed-array-length@1.0.6: - resolution: {integrity: sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==} + typed-array-length@1.0.7: + resolution: {integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==} engines: {node: '>= 0.4'} typedoc-plugin-markdown@4.2.10: @@ -3640,22 +3658,23 @@ packages: ultramatter@0.0.4: resolution: {integrity: sha512-1f/hO3mR+/Hgue4eInOF/Qm/wzDqwhYha4DxM0hre9YIUyso3fE2XtrAU6B4njLqTC8CM49EZaYgsVSa+dXHGw==} - unbox-primitive@1.0.2: - resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} + unbox-primitive@1.1.0: + resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==} + engines: {node: '>= 0.4'} undici-types@6.20.0: resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==} - unicode-canonical-property-names-ecmascript@2.0.0: - resolution: {integrity: sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==} + unicode-canonical-property-names-ecmascript@2.0.1: + resolution: {integrity: sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==} engines: {node: '>=4'} unicode-match-property-ecmascript@2.0.0: resolution: {integrity: sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==} engines: {node: '>=4'} - unicode-match-property-value-ecmascript@2.1.0: - resolution: {integrity: sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==} + unicode-match-property-value-ecmascript@2.2.0: + resolution: {integrity: sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg==} engines: {node: '>=4'} unicode-property-aliases-ecmascript@2.1.0: @@ -3707,15 +3726,12 @@ packages: resolution: {integrity: sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==} engines: {node: '>=4'} - update-browserslist-db@1.1.1: - resolution: {integrity: sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==} + update-browserslist-db@1.1.3: + resolution: {integrity: sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==} hasBin: true peerDependencies: browserslist: '>= 4.21.0' - uri-js@4.4.1: - resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} - util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} @@ -3728,8 +3744,8 @@ packages: vfile@6.0.3: resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==} - vite@5.4.11: - resolution: {integrity: sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q==} + vite@5.4.15: + resolution: {integrity: sha512-6ANcZRivqL/4WtwPGTKNaosuNJr5tWiftOC7liM7G9+rMb8+oeJeyzymDu4rTN93seySBmbjSfsS3Vzr19KNtA==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true peerDependencies: @@ -3759,8 +3775,8 @@ packages: terser: optional: true - vitefu@1.0.4: - resolution: {integrity: sha512-y6zEE3PQf6uu/Mt6DTJ9ih+kyJLr4XcSgHR2zUkM8SWDhuixEJxfJ6CZGMHh1Ec3vPLoEA0IHU5oWzVqw8ulow==} + vitefu@1.0.6: + resolution: {integrity: sha512-+Rex1GlappUyNN6UfwbVZne/9cYC4+R2XDk9xkNXBKMw6HQagdX9PgZ8V2v1WUSK1wfBLp7qbI1+XSNIlB1xmA==} peerDependencies: vite: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 peerDependenciesMeta: @@ -3789,26 +3805,35 @@ packages: resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==} engines: {node: '>=18'} - whatwg-url@14.1.0: - resolution: {integrity: sha512-jlf/foYIKywAt3x/XWKZ/3rz8OSJPiWktjmk891alJUEjiVxKX9LEO92qH3hv4aJ0mN3MWPvGMCy8jQi95xK4w==} + whatwg-url@14.2.0: + resolution: {integrity: sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==} engines: {node: '>=18'} whatwg-url@7.1.0: resolution: {integrity: sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==} - which-boxed-primitive@1.0.2: - resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} + which-boxed-primitive@1.1.1: + resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==} + engines: {node: '>= 0.4'} + + which-builtin-type@1.2.1: + resolution: {integrity: sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==} + engines: {node: '>= 0.4'} + + which-collection@1.0.2: + resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==} + engines: {node: '>= 0.4'} which-pm-runs@1.1.0: resolution: {integrity: sha512-n1brCuqClxfFfq/Rb0ICg9giSZqCS+pLtccdag6C2HyufBrh3fBOiy9nb6ggRMvWOVH5GrdJskj5iGTZNxd7SA==} engines: {node: '>=4'} - which-pm@3.0.0: - resolution: {integrity: sha512-ysVYmw6+ZBhx3+ZkcPwRuJi38ZOTLJJ33PSHaitLxSKUMsh0LkKd0nC69zZCwt5D+AYUcMK2hhw4yWny20vSGg==} + which-pm@3.0.1: + resolution: {integrity: sha512-v2JrMq0waAI4ju1xU5x3blsxBBMgdgZve580iYMN5frDaLGjbA24fok7wKCsya8KLVO19Ju4XDc5+zTZCJkQfg==} engines: {node: '>=18.12'} - which-typed-array@1.1.15: - resolution: {integrity: sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==} + which-typed-array@1.1.19: + resolution: {integrity: sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==} engines: {node: '>= 0.4'} widest-line@5.0.0: @@ -3873,8 +3898,8 @@ packages: wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - ws@8.18.0: - resolution: {integrity: sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==} + ws@8.18.1: + resolution: {integrity: sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==} engines: {node: '>=10.0.0'} peerDependencies: bufferutil: ^4.0.1 @@ -3907,14 +3932,14 @@ packages: resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} engines: {node: '>=12'} - yocto-queue@1.1.1: - resolution: {integrity: sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==} + yocto-queue@1.2.1: + resolution: {integrity: sha512-AyeEbWOu/TAXdxlV9wmGcR0+yh2j3vYPGOECcIj2S7MkrLyC7ne+oye2BKTItt0ii2PHk4cDy+95+LshzbXnGg==} engines: {node: '>=12.20'} - zod-to-json-schema@3.23.5: - resolution: {integrity: sha512-5wlSS0bXfF/BrL4jPAbz9da5hDlDptdEppYfe+x4eIJ7jioqKG9uUxOwPzqof09u/XeVdrgFu29lZi+8XNDJtA==} + zod-to-json-schema@3.24.5: + resolution: {integrity: sha512-/AuWwMP+YqiPbsJx5D6TfgRTc4kTLjsh5SOcd4bLsfUg2RcEXrFMJl1DGgdHy2aCfsIA/cr/1JM0xcB2GZji8g==} peerDependencies: - zod: ^3.23.3 + zod: ^3.24.1 zod-to-ts@1.2.0: resolution: {integrity: sha512-x30XE43V+InwGpvTySRNz9kB7qFU8DlyEy7BsSTCHPH1R0QasMmHWZDCzYm6bVXtj/9NNJAZF3jW8rzFvH5OFA==} @@ -3922,8 +3947,8 @@ packages: typescript: ^4.9.4 || ^5.0.2 zod: ^3 - zod@3.23.8: - resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==} + zod@3.24.2: + resolution: {integrity: sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ==} zwitch@2.0.4: resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} @@ -3932,25 +3957,25 @@ snapshots: '@ampproject/remapping@2.3.0': dependencies: - '@jridgewell/gen-mapping': 0.3.5 + '@jridgewell/gen-mapping': 0.3.8 '@jridgewell/trace-mapping': 0.3.25 - '@apideck/better-ajv-errors@0.3.6(ajv@8.13.0)': + '@apideck/better-ajv-errors@0.3.6(ajv@8.17.1)': dependencies: - ajv: 8.13.0 + ajv: 8.17.1 json-schema: 0.4.0 jsonpointer: 5.0.1 leven: 3.1.0 - '@asamuzakjp/css-color@2.8.2': + '@asamuzakjp/css-color@3.1.1': dependencies: - '@csstools/css-calc': 2.1.1(@csstools/css-parser-algorithms@3.0.4(@csstools/css-tokenizer@3.0.3))(@csstools/css-tokenizer@3.0.3) - '@csstools/css-color-parser': 3.0.7(@csstools/css-parser-algorithms@3.0.4(@csstools/css-tokenizer@3.0.3))(@csstools/css-tokenizer@3.0.3) + '@csstools/css-calc': 2.1.2(@csstools/css-parser-algorithms@3.0.4(@csstools/css-tokenizer@3.0.3))(@csstools/css-tokenizer@3.0.3) + '@csstools/css-color-parser': 3.0.8(@csstools/css-parser-algorithms@3.0.4(@csstools/css-tokenizer@3.0.3))(@csstools/css-tokenizer@3.0.3) '@csstools/css-parser-algorithms': 3.0.4(@csstools/css-tokenizer@3.0.3) '@csstools/css-tokenizer': 3.0.3 - lru-cache: 11.0.2 + lru-cache: 10.4.3 - '@astrojs/compiler@2.10.3': {} + '@astrojs/compiler@2.11.0': {} '@astrojs/internal-helpers@0.4.1': {} @@ -3964,11 +3989,11 @@ snapshots: mdast-util-definitions: 6.0.0 rehype-raw: 7.0.0 rehype-stringify: 10.0.1 - remark-gfm: 4.0.0 + remark-gfm: 4.0.1 remark-parse: 11.0.0 remark-rehype: 11.1.1 remark-smartypants: 3.0.2 - shiki: 1.26.1 + shiki: 1.29.2 unified: 11.0.5 unist-util-remove-position: 5.0.0 unist-util-visit: 5.0.0 @@ -3977,19 +4002,19 @@ snapshots: transitivePeerDependencies: - supports-color - '@astrojs/mdx@3.1.9(astro@4.16.18(@types/node@22.13.10)(rollup@2.79.1)(sass@1.83.4)(terser@5.31.0)(typescript@5.7.3))': + '@astrojs/mdx@3.1.9(astro@4.16.18(@types/node@22.13.13)(rollup@2.79.2)(sass@1.86.0)(terser@5.39.0)(typescript@5.7.3))': dependencies: '@astrojs/markdown-remark': 5.3.0 - '@mdx-js/mdx': 3.1.0(acorn@8.14.0) - acorn: 8.14.0 - astro: 4.16.18(@types/node@22.13.10)(rollup@2.79.1)(sass@1.83.4)(terser@5.31.0)(typescript@5.7.3) - es-module-lexer: 1.5.4 + '@mdx-js/mdx': 3.1.0(acorn@8.14.1) + acorn: 8.14.1 + astro: 4.16.18(@types/node@22.13.13)(rollup@2.79.2)(sass@1.86.0)(terser@5.39.0)(typescript@5.7.3) + es-module-lexer: 1.6.0 estree-util-visit: 2.0.0 gray-matter: 4.0.3 - hast-util-to-html: 9.0.4 + hast-util-to-html: 9.0.5 kleur: 4.1.5 rehype-raw: 7.0.0 - remark-gfm: 4.0.0 + remark-gfm: 4.0.1 remark-smartypants: 3.0.2 source-map: 0.7.4 unist-util-visit: 5.0.0 @@ -3999,47 +4024,47 @@ snapshots: '@astrojs/prism@3.1.0': dependencies: - prismjs: 1.29.0 + prismjs: 1.30.0 '@astrojs/rss@4.0.11': dependencies: - fast-xml-parser: 4.5.1 + fast-xml-parser: 4.5.3 kleur: 4.1.5 '@astrojs/rss@4.0.5': dependencies: - fast-xml-parser: 4.5.1 + fast-xml-parser: 4.5.3 kleur: 4.1.5 - '@astrojs/sitemap@3.1.6': + '@astrojs/sitemap@3.3.0': dependencies: - sitemap: 7.1.2 + sitemap: 8.0.0 stream-replace-string: 2.0.0 - zod: 3.23.8 + zod: 3.24.2 - '@astrojs/starlight@0.29.2(patch_hash=cce5b634885e07791c60f64102f8e7a74def815cdbc19d8aa069b9f4602f2890)(astro@4.16.18(@types/node@22.13.10)(rollup@2.79.1)(sass@1.83.4)(terser@5.31.0)(typescript@5.7.3))': + '@astrojs/starlight@0.29.2(patch_hash=cce5b634885e07791c60f64102f8e7a74def815cdbc19d8aa069b9f4602f2890)(astro@4.16.18(@types/node@22.13.13)(rollup@2.79.2)(sass@1.86.0)(terser@5.39.0)(typescript@5.7.3))': dependencies: - '@astrojs/mdx': 3.1.9(astro@4.16.18(@types/node@22.13.10)(rollup@2.79.1)(sass@1.83.4)(terser@5.31.0)(typescript@5.7.3)) - '@astrojs/sitemap': 3.1.6 - '@pagefind/default-ui': 1.1.1 + '@astrojs/mdx': 3.1.9(astro@4.16.18(@types/node@22.13.13)(rollup@2.79.2)(sass@1.86.0)(terser@5.39.0)(typescript@5.7.3)) + '@astrojs/sitemap': 3.3.0 + '@pagefind/default-ui': 1.3.0 '@types/hast': 3.0.4 '@types/mdast': 4.0.4 - astro: 4.16.18(@types/node@22.13.10)(rollup@2.79.1)(sass@1.83.4)(terser@5.31.0)(typescript@5.7.3) - astro-expressive-code: 0.38.3(astro@4.16.18(@types/node@22.13.10)(rollup@2.79.1)(sass@1.83.4)(terser@5.31.0)(typescript@5.7.3)) + astro: 4.16.18(@types/node@22.13.13)(rollup@2.79.2)(sass@1.86.0)(terser@5.39.0)(typescript@5.7.3) + astro-expressive-code: 0.38.3(astro@4.16.18(@types/node@22.13.13)(rollup@2.79.2)(sass@1.86.0)(terser@5.39.0)(typescript@5.7.3)) bcp-47: 2.1.0 hast-util-from-html: 2.0.3 - hast-util-select: 6.0.2 - hast-util-to-string: 3.0.0 - hastscript: 9.0.0 - i18next: 23.15.1 + hast-util-select: 6.0.4 + hast-util-to-string: 3.0.1 + hastscript: 9.0.1 + i18next: 23.16.8 js-yaml: 4.1.0 - mdast-util-directive: 3.0.0 - mdast-util-to-markdown: 2.1.0 + mdast-util-directive: 3.1.0 + mdast-util-to-markdown: 2.1.2 mdast-util-to-string: 4.0.0 - pagefind: 1.1.1 + pagefind: 1.3.0 rehype: 13.0.2 rehype-format: 5.0.1 - remark-directive: 3.0.0 + remark-directive: 3.0.1 unified: 11.0.5 unist-util-visit: 5.0.0 vfile: 6.0.3 @@ -4048,8 +4073,8 @@ snapshots: '@astrojs/telemetry@3.1.0': dependencies: - ci-info: 4.1.0 - debug: 4.3.7 + ci-info: 4.2.0 + debug: 4.4.0 dlv: 1.1.3 dset: 3.1.4 is-docker: 3.0.0 @@ -4064,150 +4089,132 @@ snapshots: js-tokens: 4.0.0 picocolors: 1.1.1 - '@babel/compat-data@7.26.3': {} + '@babel/compat-data@7.26.8': {} - '@babel/core@7.26.0': + '@babel/core@7.26.10': dependencies: '@ampproject/remapping': 2.3.0 '@babel/code-frame': 7.26.2 - '@babel/generator': 7.26.3 - '@babel/helper-compilation-targets': 7.25.9 - '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.0) - '@babel/helpers': 7.26.0 - '@babel/parser': 7.26.3 - '@babel/template': 7.25.9 - '@babel/traverse': 7.26.3 - '@babel/types': 7.26.3 + '@babel/generator': 7.27.0 + '@babel/helper-compilation-targets': 7.27.0 + '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.10) + '@babel/helpers': 7.27.0 + '@babel/parser': 7.27.0 + '@babel/template': 7.27.0 + '@babel/traverse': 7.27.0 + '@babel/types': 7.27.0 convert-source-map: 2.0.0 - debug: 4.3.7 + debug: 4.4.0 gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 transitivePeerDependencies: - supports-color - '@babel/generator@7.26.3': + '@babel/generator@7.27.0': dependencies: - '@babel/parser': 7.26.3 - '@babel/types': 7.26.3 - '@jridgewell/gen-mapping': 0.3.5 + '@babel/parser': 7.27.0 + '@babel/types': 7.27.0 + '@jridgewell/gen-mapping': 0.3.8 '@jridgewell/trace-mapping': 0.3.25 - jsesc: 3.0.2 + jsesc: 3.1.0 '@babel/helper-annotate-as-pure@7.25.9': dependencies: - '@babel/types': 7.26.3 - - '@babel/helper-builder-binary-assignment-operator-visitor@7.22.15': - dependencies: - '@babel/types': 7.26.3 + '@babel/types': 7.27.0 - '@babel/helper-compilation-targets@7.25.9': + '@babel/helper-compilation-targets@7.27.0': dependencies: - '@babel/compat-data': 7.26.3 + '@babel/compat-data': 7.26.8 '@babel/helper-validator-option': 7.25.9 - browserslist: 4.24.2 + browserslist: 4.24.4 lru-cache: 5.1.1 semver: 6.3.1 - '@babel/helper-create-class-features-plugin@7.24.5(@babel/core@7.26.0)': + '@babel/helper-create-class-features-plugin@7.27.0(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.26.0 + '@babel/core': 7.26.10 '@babel/helper-annotate-as-pure': 7.25.9 - '@babel/helper-environment-visitor': 7.24.7 - '@babel/helper-function-name': 7.24.7 - '@babel/helper-member-expression-to-functions': 7.24.5 - '@babel/helper-optimise-call-expression': 7.22.5 - '@babel/helper-replace-supers': 7.24.1(@babel/core@7.26.0) - '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 - '@babel/helper-split-export-declaration': 7.24.7 + '@babel/helper-member-expression-to-functions': 7.25.9 + '@babel/helper-optimise-call-expression': 7.25.9 + '@babel/helper-replace-supers': 7.26.5(@babel/core@7.26.10) + '@babel/helper-skip-transparent-expression-wrappers': 7.25.9 + '@babel/traverse': 7.27.0 semver: 6.3.1 + transitivePeerDependencies: + - supports-color - '@babel/helper-create-regexp-features-plugin@7.22.15(@babel/core@7.26.0)': + '@babel/helper-create-regexp-features-plugin@7.27.0(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.26.0 + '@babel/core': 7.26.10 '@babel/helper-annotate-as-pure': 7.25.9 - regexpu-core: 5.3.2 + regexpu-core: 6.2.0 semver: 6.3.1 - '@babel/helper-define-polyfill-provider@0.6.2(@babel/core@7.26.0)': + '@babel/helper-define-polyfill-provider@0.6.4(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-compilation-targets': 7.25.9 - '@babel/helper-plugin-utils': 7.25.9 - debug: 4.3.7 + '@babel/core': 7.26.10 + '@babel/helper-compilation-targets': 7.27.0 + '@babel/helper-plugin-utils': 7.26.5 + debug: 4.4.0 lodash.debounce: 4.0.8 - resolve: 1.22.8 + resolve: 1.22.10 transitivePeerDependencies: - supports-color - '@babel/helper-environment-visitor@7.24.7': + '@babel/helper-member-expression-to-functions@7.25.9': dependencies: - '@babel/types': 7.26.3 - - '@babel/helper-function-name@7.24.7': - dependencies: - '@babel/template': 7.25.9 - '@babel/types': 7.26.3 - - '@babel/helper-hoist-variables@7.24.7': - dependencies: - '@babel/types': 7.26.3 - - '@babel/helper-member-expression-to-functions@7.24.5': - dependencies: - '@babel/types': 7.26.3 + '@babel/traverse': 7.27.0 + '@babel/types': 7.27.0 + transitivePeerDependencies: + - supports-color '@babel/helper-module-imports@7.25.9': dependencies: - '@babel/traverse': 7.26.3 - '@babel/types': 7.26.3 + '@babel/traverse': 7.27.0 + '@babel/types': 7.27.0 transitivePeerDependencies: - supports-color - '@babel/helper-module-transforms@7.26.0(@babel/core@7.26.0)': + '@babel/helper-module-transforms@7.26.0(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.26.0 + '@babel/core': 7.26.10 '@babel/helper-module-imports': 7.25.9 '@babel/helper-validator-identifier': 7.25.9 - '@babel/traverse': 7.26.3 + '@babel/traverse': 7.27.0 transitivePeerDependencies: - supports-color - '@babel/helper-optimise-call-expression@7.22.5': + '@babel/helper-optimise-call-expression@7.25.9': dependencies: - '@babel/types': 7.26.3 + '@babel/types': 7.27.0 - '@babel/helper-plugin-utils@7.25.9': {} + '@babel/helper-plugin-utils@7.26.5': {} - '@babel/helper-remap-async-to-generator@7.22.20(@babel/core@7.26.0)': + '@babel/helper-remap-async-to-generator@7.25.9(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.26.0 + '@babel/core': 7.26.10 '@babel/helper-annotate-as-pure': 7.25.9 - '@babel/helper-environment-visitor': 7.24.7 - '@babel/helper-wrap-function': 7.24.5 - - '@babel/helper-replace-supers@7.24.1(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-environment-visitor': 7.24.7 - '@babel/helper-member-expression-to-functions': 7.24.5 - '@babel/helper-optimise-call-expression': 7.22.5 - - '@babel/helper-simple-access@7.25.9': - dependencies: - '@babel/traverse': 7.26.3 - '@babel/types': 7.26.3 + '@babel/helper-wrap-function': 7.25.9 + '@babel/traverse': 7.27.0 transitivePeerDependencies: - supports-color - '@babel/helper-skip-transparent-expression-wrappers@7.22.5': + '@babel/helper-replace-supers@7.26.5(@babel/core@7.26.10)': dependencies: - '@babel/types': 7.26.3 + '@babel/core': 7.26.10 + '@babel/helper-member-expression-to-functions': 7.25.9 + '@babel/helper-optimise-call-expression': 7.25.9 + '@babel/traverse': 7.27.0 + transitivePeerDependencies: + - supports-color - '@babel/helper-split-export-declaration@7.24.7': + '@babel/helper-skip-transparent-expression-wrappers@7.25.9': dependencies: - '@babel/types': 7.26.3 + '@babel/traverse': 7.27.0 + '@babel/types': 7.27.0 + transitivePeerDependencies: + - supports-color '@babel/helper-string-parser@7.25.9': {} @@ -4215,596 +4222,538 @@ snapshots: '@babel/helper-validator-option@7.25.9': {} - '@babel/helper-wrap-function@7.24.5': - dependencies: - '@babel/helper-function-name': 7.24.7 - '@babel/template': 7.25.9 - '@babel/types': 7.26.3 - - '@babel/helpers@7.26.0': - dependencies: - '@babel/template': 7.25.9 - '@babel/types': 7.26.3 - - '@babel/parser@7.26.3': - dependencies: - '@babel/types': 7.26.3 - - '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.24.5(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-environment-visitor': 7.24.7 - '@babel/helper-plugin-utils': 7.25.9 - - '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.24.1(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - - '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.24.1(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 - '@babel/plugin-transform-optional-chaining': 7.24.5(@babel/core@7.26.0) - - '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.24.1(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-environment-visitor': 7.24.7 - '@babel/helper-plugin-utils': 7.25.9 - - '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - - '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - - '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - - '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - - '@babel/plugin-syntax-dynamic-import@7.8.3(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - - '@babel/plugin-syntax-export-namespace-from@7.8.3(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - - '@babel/plugin-syntax-import-assertions@7.24.1(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - - '@babel/plugin-syntax-import-attributes@7.24.1(@babel/core@7.26.0)': + '@babel/helper-wrap-function@7.25.9': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/template': 7.27.0 + '@babel/traverse': 7.27.0 + '@babel/types': 7.27.0 + transitivePeerDependencies: + - supports-color - '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.26.0)': + '@babel/helpers@7.27.0': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/template': 7.27.0 + '@babel/types': 7.27.0 - '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.26.0)': + '@babel/parser@7.27.0': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/types': 7.27.0 - '@babel/plugin-syntax-jsx@7.25.9(@babel/core@7.26.0)': + '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.25.9(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/traverse': 7.27.0 + transitivePeerDependencies: + - supports-color - '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.26.0)': + '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.25.9(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.26.0)': + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.25.9(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.26.0)': + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.25.9(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/helper-skip-transparent-expression-wrappers': 7.25.9 + '@babel/plugin-transform-optional-chaining': 7.25.9(@babel/core@7.26.10) + transitivePeerDependencies: + - supports-color - '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.26.0)': + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.25.9(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/traverse': 7.27.0 + transitivePeerDependencies: + - supports-color - '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.26.0)': + '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/core': 7.26.10 - '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.26.0)': + '@babel/plugin-syntax-import-assertions@7.26.0(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.26.0)': + '@babel/plugin-syntax-import-attributes@7.26.0(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.26.0)': + '@babel/plugin-syntax-jsx@7.25.9(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.26.0)': + '@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.26.0) - '@babel/helper-plugin-utils': 7.25.9 + '@babel/core': 7.26.10 + '@babel/helper-create-regexp-features-plugin': 7.27.0(@babel/core@7.26.10) + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-transform-arrow-functions@7.24.1(@babel/core@7.26.0)': + '@babel/plugin-transform-arrow-functions@7.25.9(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-transform-async-generator-functions@7.24.3(@babel/core@7.26.0)': + '@babel/plugin-transform-async-generator-functions@7.26.8(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-environment-visitor': 7.24.7 - '@babel/helper-plugin-utils': 7.25.9 - '@babel/helper-remap-async-to-generator': 7.22.20(@babel/core@7.26.0) - '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.26.0) + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/helper-remap-async-to-generator': 7.25.9(@babel/core@7.26.10) + '@babel/traverse': 7.27.0 + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-async-to-generator@7.24.1(@babel/core@7.26.0)': + '@babel/plugin-transform-async-to-generator@7.25.9(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.26.0 + '@babel/core': 7.26.10 '@babel/helper-module-imports': 7.25.9 - '@babel/helper-plugin-utils': 7.25.9 - '@babel/helper-remap-async-to-generator': 7.22.20(@babel/core@7.26.0) + '@babel/helper-plugin-utils': 7.26.5 + '@babel/helper-remap-async-to-generator': 7.25.9(@babel/core@7.26.10) transitivePeerDependencies: - supports-color - '@babel/plugin-transform-block-scoped-functions@7.24.1(@babel/core@7.26.0)': + '@babel/plugin-transform-block-scoped-functions@7.26.5(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-transform-block-scoping@7.24.5(@babel/core@7.26.0)': + '@babel/plugin-transform-block-scoping@7.27.0(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-transform-class-properties@7.24.1(@babel/core@7.26.0)': + '@babel/plugin-transform-class-properties@7.25.9(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-create-class-features-plugin': 7.24.5(@babel/core@7.26.0) - '@babel/helper-plugin-utils': 7.25.9 + '@babel/core': 7.26.10 + '@babel/helper-create-class-features-plugin': 7.27.0(@babel/core@7.26.10) + '@babel/helper-plugin-utils': 7.26.5 + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-class-static-block@7.24.4(@babel/core@7.26.0)': + '@babel/plugin-transform-class-static-block@7.26.0(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-create-class-features-plugin': 7.24.5(@babel/core@7.26.0) - '@babel/helper-plugin-utils': 7.25.9 - '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.26.0) + '@babel/core': 7.26.10 + '@babel/helper-create-class-features-plugin': 7.27.0(@babel/core@7.26.10) + '@babel/helper-plugin-utils': 7.26.5 + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-classes@7.24.5(@babel/core@7.26.0)': + '@babel/plugin-transform-classes@7.25.9(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.26.0 + '@babel/core': 7.26.10 '@babel/helper-annotate-as-pure': 7.25.9 - '@babel/helper-compilation-targets': 7.25.9 - '@babel/helper-environment-visitor': 7.24.7 - '@babel/helper-function-name': 7.24.7 - '@babel/helper-plugin-utils': 7.25.9 - '@babel/helper-replace-supers': 7.24.1(@babel/core@7.26.0) - '@babel/helper-split-export-declaration': 7.24.7 + '@babel/helper-compilation-targets': 7.27.0 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/helper-replace-supers': 7.26.5(@babel/core@7.26.10) + '@babel/traverse': 7.27.0 globals: 11.12.0 + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-computed-properties@7.24.1(@babel/core@7.26.0)': + '@babel/plugin-transform-computed-properties@7.25.9(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - '@babel/template': 7.25.9 + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/template': 7.27.0 - '@babel/plugin-transform-destructuring@7.24.5(@babel/core@7.26.0)': + '@babel/plugin-transform-destructuring@7.25.9(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-transform-dotall-regex@7.24.1(@babel/core@7.26.0)': + '@babel/plugin-transform-dotall-regex@7.25.9(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.26.0) - '@babel/helper-plugin-utils': 7.25.9 + '@babel/core': 7.26.10 + '@babel/helper-create-regexp-features-plugin': 7.27.0(@babel/core@7.26.10) + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-transform-duplicate-keys@7.24.1(@babel/core@7.26.0)': + '@babel/plugin-transform-duplicate-keys@7.25.9(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-transform-dynamic-import@7.24.1(@babel/core@7.26.0)': + '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.25.9(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.26.0) + '@babel/core': 7.26.10 + '@babel/helper-create-regexp-features-plugin': 7.27.0(@babel/core@7.26.10) + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-transform-exponentiation-operator@7.24.1(@babel/core@7.26.0)': + '@babel/plugin-transform-dynamic-import@7.25.9(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-builder-binary-assignment-operator-visitor': 7.22.15 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-transform-export-namespace-from@7.24.1(@babel/core@7.26.0)': + '@babel/plugin-transform-exponentiation-operator@7.26.3(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.26.0) + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-transform-for-of@7.24.1(@babel/core@7.26.0)': + '@babel/plugin-transform-export-namespace-from@7.25.9(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-for-of@7.26.9(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/helper-skip-transparent-expression-wrappers': 7.25.9 + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-function-name@7.24.1(@babel/core@7.26.0)': + '@babel/plugin-transform-function-name@7.25.9(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-compilation-targets': 7.25.9 - '@babel/helper-function-name': 7.24.7 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/core': 7.26.10 + '@babel/helper-compilation-targets': 7.27.0 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/traverse': 7.27.0 + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-json-strings@7.24.1(@babel/core@7.26.0)': + '@babel/plugin-transform-json-strings@7.25.9(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.26.0) + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-transform-literals@7.24.1(@babel/core@7.26.0)': + '@babel/plugin-transform-literals@7.25.9(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-transform-logical-assignment-operators@7.24.1(@babel/core@7.26.0)': + '@babel/plugin-transform-logical-assignment-operators@7.25.9(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.26.0) + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-transform-member-expression-literals@7.24.1(@babel/core@7.26.0)': + '@babel/plugin-transform-member-expression-literals@7.25.9(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-transform-modules-amd@7.24.1(@babel/core@7.26.0)': + '@babel/plugin-transform-modules-amd@7.25.9(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.0) - '@babel/helper-plugin-utils': 7.25.9 + '@babel/core': 7.26.10 + '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.10) + '@babel/helper-plugin-utils': 7.26.5 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-modules-commonjs@7.24.1(@babel/core@7.26.0)': + '@babel/plugin-transform-modules-commonjs@7.26.3(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.0) - '@babel/helper-plugin-utils': 7.25.9 - '@babel/helper-simple-access': 7.25.9 + '@babel/core': 7.26.10 + '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.10) + '@babel/helper-plugin-utils': 7.26.5 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-modules-systemjs@7.24.1(@babel/core@7.26.0)': + '@babel/plugin-transform-modules-systemjs@7.25.9(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-hoist-variables': 7.24.7 - '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.0) - '@babel/helper-plugin-utils': 7.25.9 + '@babel/core': 7.26.10 + '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.10) + '@babel/helper-plugin-utils': 7.26.5 '@babel/helper-validator-identifier': 7.25.9 + '@babel/traverse': 7.27.0 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-modules-umd@7.24.1(@babel/core@7.26.0)': + '@babel/plugin-transform-modules-umd@7.25.9(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.0) - '@babel/helper-plugin-utils': 7.25.9 + '@babel/core': 7.26.10 + '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.10) + '@babel/helper-plugin-utils': 7.26.5 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-named-capturing-groups-regex@7.22.5(@babel/core@7.26.0)': + '@babel/plugin-transform-named-capturing-groups-regex@7.25.9(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.26.0) - '@babel/helper-plugin-utils': 7.25.9 + '@babel/core': 7.26.10 + '@babel/helper-create-regexp-features-plugin': 7.27.0(@babel/core@7.26.10) + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-transform-new-target@7.24.1(@babel/core@7.26.0)': + '@babel/plugin-transform-new-target@7.25.9(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-transform-nullish-coalescing-operator@7.24.1(@babel/core@7.26.0)': + '@babel/plugin-transform-nullish-coalescing-operator@7.26.6(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.26.0) + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-transform-numeric-separator@7.24.1(@babel/core@7.26.0)': + '@babel/plugin-transform-numeric-separator@7.25.9(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.26.0) + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-transform-object-rest-spread@7.24.5(@babel/core@7.26.0)': + '@babel/plugin-transform-object-rest-spread@7.25.9(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-compilation-targets': 7.25.9 - '@babel/helper-plugin-utils': 7.25.9 - '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.26.0) - '@babel/plugin-transform-parameters': 7.24.5(@babel/core@7.26.0) + '@babel/core': 7.26.10 + '@babel/helper-compilation-targets': 7.27.0 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/plugin-transform-parameters': 7.25.9(@babel/core@7.26.10) - '@babel/plugin-transform-object-super@7.24.1(@babel/core@7.26.0)': + '@babel/plugin-transform-object-super@7.25.9(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - '@babel/helper-replace-supers': 7.24.1(@babel/core@7.26.0) + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/helper-replace-supers': 7.26.5(@babel/core@7.26.10) + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-optional-catch-binding@7.24.1(@babel/core@7.26.0)': + '@babel/plugin-transform-optional-catch-binding@7.25.9(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.26.0) + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-transform-optional-chaining@7.24.5(@babel/core@7.26.0)': + '@babel/plugin-transform-optional-chaining@7.25.9(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.26.0) + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/helper-skip-transparent-expression-wrappers': 7.25.9 + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-parameters@7.24.5(@babel/core@7.26.0)': + '@babel/plugin-transform-parameters@7.25.9(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-transform-private-methods@7.24.1(@babel/core@7.26.0)': + '@babel/plugin-transform-private-methods@7.25.9(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-create-class-features-plugin': 7.24.5(@babel/core@7.26.0) - '@babel/helper-plugin-utils': 7.25.9 + '@babel/core': 7.26.10 + '@babel/helper-create-class-features-plugin': 7.27.0(@babel/core@7.26.10) + '@babel/helper-plugin-utils': 7.26.5 + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-private-property-in-object@7.24.5(@babel/core@7.26.0)': + '@babel/plugin-transform-private-property-in-object@7.25.9(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.26.0 + '@babel/core': 7.26.10 '@babel/helper-annotate-as-pure': 7.25.9 - '@babel/helper-create-class-features-plugin': 7.24.5(@babel/core@7.26.0) - '@babel/helper-plugin-utils': 7.25.9 - '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.26.0) + '@babel/helper-create-class-features-plugin': 7.27.0(@babel/core@7.26.10) + '@babel/helper-plugin-utils': 7.26.5 + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-property-literals@7.24.1(@babel/core@7.26.0)': + '@babel/plugin-transform-property-literals@7.25.9(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-transform-react-jsx@7.25.9(@babel/core@7.26.0)': + '@babel/plugin-transform-react-jsx@7.25.9(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.26.0 + '@babel/core': 7.26.10 '@babel/helper-annotate-as-pure': 7.25.9 '@babel/helper-module-imports': 7.25.9 - '@babel/helper-plugin-utils': 7.25.9 - '@babel/plugin-syntax-jsx': 7.25.9(@babel/core@7.26.0) - '@babel/types': 7.26.3 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/plugin-syntax-jsx': 7.25.9(@babel/core@7.26.10) + '@babel/types': 7.27.0 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-regenerator@7.24.1(@babel/core@7.26.0)': + '@babel/plugin-transform-regenerator@7.27.0(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 regenerator-transform: 0.15.2 - '@babel/plugin-transform-reserved-words@7.24.1(@babel/core@7.26.0)': + '@babel/plugin-transform-regexp-modifiers@7.26.0(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/core': 7.26.10 + '@babel/helper-create-regexp-features-plugin': 7.27.0(@babel/core@7.26.10) + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-transform-shorthand-properties@7.24.1(@babel/core@7.26.0)': + '@babel/plugin-transform-reserved-words@7.25.9(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-transform-spread@7.24.1(@babel/core@7.26.0)': + '@babel/plugin-transform-shorthand-properties@7.25.9(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-transform-sticky-regex@7.24.1(@babel/core@7.26.0)': + '@babel/plugin-transform-spread@7.25.9(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/helper-skip-transparent-expression-wrappers': 7.25.9 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-sticky-regex@7.25.9(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-transform-template-literals@7.24.1(@babel/core@7.26.0)': + '@babel/plugin-transform-template-literals@7.26.8(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-transform-typeof-symbol@7.24.5(@babel/core@7.26.0)': + '@babel/plugin-transform-typeof-symbol@7.27.0(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-transform-unicode-escapes@7.24.1(@babel/core@7.26.0)': + '@babel/plugin-transform-unicode-escapes@7.25.9(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-transform-unicode-property-regex@7.24.1(@babel/core@7.26.0)': + '@babel/plugin-transform-unicode-property-regex@7.25.9(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.26.0) - '@babel/helper-plugin-utils': 7.25.9 + '@babel/core': 7.26.10 + '@babel/helper-create-regexp-features-plugin': 7.27.0(@babel/core@7.26.10) + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-transform-unicode-regex@7.24.1(@babel/core@7.26.0)': + '@babel/plugin-transform-unicode-regex@7.25.9(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.26.0) - '@babel/helper-plugin-utils': 7.25.9 + '@babel/core': 7.26.10 + '@babel/helper-create-regexp-features-plugin': 7.27.0(@babel/core@7.26.10) + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-transform-unicode-sets-regex@7.24.1(@babel/core@7.26.0)': + '@babel/plugin-transform-unicode-sets-regex@7.25.9(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.26.0) - '@babel/helper-plugin-utils': 7.25.9 + '@babel/core': 7.26.10 + '@babel/helper-create-regexp-features-plugin': 7.27.0(@babel/core@7.26.10) + '@babel/helper-plugin-utils': 7.26.5 - '@babel/preset-env@7.24.5(@babel/core@7.26.0)': + '@babel/preset-env@7.26.9(@babel/core@7.26.10)': dependencies: - '@babel/compat-data': 7.26.3 - '@babel/core': 7.26.0 - '@babel/helper-compilation-targets': 7.25.9 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/compat-data': 7.26.8 + '@babel/core': 7.26.10 + '@babel/helper-compilation-targets': 7.27.0 + '@babel/helper-plugin-utils': 7.26.5 '@babel/helper-validator-option': 7.25.9 - '@babel/plugin-bugfix-firefox-class-in-computed-class-key': 7.24.5(@babel/core@7.26.0) - '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.24.1(@babel/core@7.26.0) - '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.24.1(@babel/core@7.26.0) - '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly': 7.24.1(@babel/core@7.26.0) - '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@7.26.0) - '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.26.0) - '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.26.0) - '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.26.0) - '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.26.0) - '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.26.0) - '@babel/plugin-syntax-import-assertions': 7.24.1(@babel/core@7.26.0) - '@babel/plugin-syntax-import-attributes': 7.24.1(@babel/core@7.26.0) - '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.26.0) - '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.26.0) - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.26.0) - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.26.0) - '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.26.0) - '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.26.0) - '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.26.0) - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.26.0) - '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.26.0) - '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.26.0) - '@babel/plugin-syntax-unicode-sets-regex': 7.18.6(@babel/core@7.26.0) - '@babel/plugin-transform-arrow-functions': 7.24.1(@babel/core@7.26.0) - '@babel/plugin-transform-async-generator-functions': 7.24.3(@babel/core@7.26.0) - '@babel/plugin-transform-async-to-generator': 7.24.1(@babel/core@7.26.0) - '@babel/plugin-transform-block-scoped-functions': 7.24.1(@babel/core@7.26.0) - '@babel/plugin-transform-block-scoping': 7.24.5(@babel/core@7.26.0) - '@babel/plugin-transform-class-properties': 7.24.1(@babel/core@7.26.0) - '@babel/plugin-transform-class-static-block': 7.24.4(@babel/core@7.26.0) - '@babel/plugin-transform-classes': 7.24.5(@babel/core@7.26.0) - '@babel/plugin-transform-computed-properties': 7.24.1(@babel/core@7.26.0) - '@babel/plugin-transform-destructuring': 7.24.5(@babel/core@7.26.0) - '@babel/plugin-transform-dotall-regex': 7.24.1(@babel/core@7.26.0) - '@babel/plugin-transform-duplicate-keys': 7.24.1(@babel/core@7.26.0) - '@babel/plugin-transform-dynamic-import': 7.24.1(@babel/core@7.26.0) - '@babel/plugin-transform-exponentiation-operator': 7.24.1(@babel/core@7.26.0) - '@babel/plugin-transform-export-namespace-from': 7.24.1(@babel/core@7.26.0) - '@babel/plugin-transform-for-of': 7.24.1(@babel/core@7.26.0) - '@babel/plugin-transform-function-name': 7.24.1(@babel/core@7.26.0) - '@babel/plugin-transform-json-strings': 7.24.1(@babel/core@7.26.0) - '@babel/plugin-transform-literals': 7.24.1(@babel/core@7.26.0) - '@babel/plugin-transform-logical-assignment-operators': 7.24.1(@babel/core@7.26.0) - '@babel/plugin-transform-member-expression-literals': 7.24.1(@babel/core@7.26.0) - '@babel/plugin-transform-modules-amd': 7.24.1(@babel/core@7.26.0) - '@babel/plugin-transform-modules-commonjs': 7.24.1(@babel/core@7.26.0) - '@babel/plugin-transform-modules-systemjs': 7.24.1(@babel/core@7.26.0) - '@babel/plugin-transform-modules-umd': 7.24.1(@babel/core@7.26.0) - '@babel/plugin-transform-named-capturing-groups-regex': 7.22.5(@babel/core@7.26.0) - '@babel/plugin-transform-new-target': 7.24.1(@babel/core@7.26.0) - '@babel/plugin-transform-nullish-coalescing-operator': 7.24.1(@babel/core@7.26.0) - '@babel/plugin-transform-numeric-separator': 7.24.1(@babel/core@7.26.0) - '@babel/plugin-transform-object-rest-spread': 7.24.5(@babel/core@7.26.0) - '@babel/plugin-transform-object-super': 7.24.1(@babel/core@7.26.0) - '@babel/plugin-transform-optional-catch-binding': 7.24.1(@babel/core@7.26.0) - '@babel/plugin-transform-optional-chaining': 7.24.5(@babel/core@7.26.0) - '@babel/plugin-transform-parameters': 7.24.5(@babel/core@7.26.0) - '@babel/plugin-transform-private-methods': 7.24.1(@babel/core@7.26.0) - '@babel/plugin-transform-private-property-in-object': 7.24.5(@babel/core@7.26.0) - '@babel/plugin-transform-property-literals': 7.24.1(@babel/core@7.26.0) - '@babel/plugin-transform-regenerator': 7.24.1(@babel/core@7.26.0) - '@babel/plugin-transform-reserved-words': 7.24.1(@babel/core@7.26.0) - '@babel/plugin-transform-shorthand-properties': 7.24.1(@babel/core@7.26.0) - '@babel/plugin-transform-spread': 7.24.1(@babel/core@7.26.0) - '@babel/plugin-transform-sticky-regex': 7.24.1(@babel/core@7.26.0) - '@babel/plugin-transform-template-literals': 7.24.1(@babel/core@7.26.0) - '@babel/plugin-transform-typeof-symbol': 7.24.5(@babel/core@7.26.0) - '@babel/plugin-transform-unicode-escapes': 7.24.1(@babel/core@7.26.0) - '@babel/plugin-transform-unicode-property-regex': 7.24.1(@babel/core@7.26.0) - '@babel/plugin-transform-unicode-regex': 7.24.1(@babel/core@7.26.0) - '@babel/plugin-transform-unicode-sets-regex': 7.24.1(@babel/core@7.26.0) - '@babel/preset-modules': 0.1.6-no-external-plugins(@babel/core@7.26.0) - babel-plugin-polyfill-corejs2: 0.4.11(@babel/core@7.26.0) - babel-plugin-polyfill-corejs3: 0.10.4(@babel/core@7.26.0) - babel-plugin-polyfill-regenerator: 0.6.2(@babel/core@7.26.0) - core-js-compat: 3.37.1 + '@babel/plugin-bugfix-firefox-class-in-computed-class-key': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-bugfix-safari-class-field-initializer-scope': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@7.26.10) + '@babel/plugin-syntax-import-assertions': 7.26.0(@babel/core@7.26.10) + '@babel/plugin-syntax-import-attributes': 7.26.0(@babel/core@7.26.10) + '@babel/plugin-syntax-unicode-sets-regex': 7.18.6(@babel/core@7.26.10) + '@babel/plugin-transform-arrow-functions': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-async-generator-functions': 7.26.8(@babel/core@7.26.10) + '@babel/plugin-transform-async-to-generator': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-block-scoped-functions': 7.26.5(@babel/core@7.26.10) + '@babel/plugin-transform-block-scoping': 7.27.0(@babel/core@7.26.10) + '@babel/plugin-transform-class-properties': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-class-static-block': 7.26.0(@babel/core@7.26.10) + '@babel/plugin-transform-classes': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-computed-properties': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-destructuring': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-dotall-regex': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-duplicate-keys': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-duplicate-named-capturing-groups-regex': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-dynamic-import': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-exponentiation-operator': 7.26.3(@babel/core@7.26.10) + '@babel/plugin-transform-export-namespace-from': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-for-of': 7.26.9(@babel/core@7.26.10) + '@babel/plugin-transform-function-name': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-json-strings': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-literals': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-logical-assignment-operators': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-member-expression-literals': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-modules-amd': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-modules-commonjs': 7.26.3(@babel/core@7.26.10) + '@babel/plugin-transform-modules-systemjs': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-modules-umd': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-named-capturing-groups-regex': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-new-target': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-nullish-coalescing-operator': 7.26.6(@babel/core@7.26.10) + '@babel/plugin-transform-numeric-separator': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-object-rest-spread': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-object-super': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-optional-catch-binding': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-optional-chaining': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-parameters': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-private-methods': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-private-property-in-object': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-property-literals': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-regenerator': 7.27.0(@babel/core@7.26.10) + '@babel/plugin-transform-regexp-modifiers': 7.26.0(@babel/core@7.26.10) + '@babel/plugin-transform-reserved-words': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-shorthand-properties': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-spread': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-sticky-regex': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-template-literals': 7.26.8(@babel/core@7.26.10) + '@babel/plugin-transform-typeof-symbol': 7.27.0(@babel/core@7.26.10) + '@babel/plugin-transform-unicode-escapes': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-unicode-property-regex': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-unicode-regex': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-unicode-sets-regex': 7.25.9(@babel/core@7.26.10) + '@babel/preset-modules': 0.1.6-no-external-plugins(@babel/core@7.26.10) + babel-plugin-polyfill-corejs2: 0.4.13(@babel/core@7.26.10) + babel-plugin-polyfill-corejs3: 0.11.1(@babel/core@7.26.10) + babel-plugin-polyfill-regenerator: 0.6.4(@babel/core@7.26.10) + core-js-compat: 3.41.0 semver: 6.3.1 transitivePeerDependencies: - supports-color - '@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.26.0)': + '@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - '@babel/types': 7.26.3 + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/types': 7.27.0 esutils: 2.0.3 - '@babel/regjsgen@0.8.0': {} - - '@babel/runtime@7.25.6': + '@babel/runtime@7.27.0': dependencies: regenerator-runtime: 0.14.1 - '@babel/template@7.25.9': + '@babel/template@7.27.0': dependencies: '@babel/code-frame': 7.26.2 - '@babel/parser': 7.26.3 - '@babel/types': 7.26.3 + '@babel/parser': 7.27.0 + '@babel/types': 7.27.0 - '@babel/traverse@7.26.3': + '@babel/traverse@7.27.0': dependencies: '@babel/code-frame': 7.26.2 - '@babel/generator': 7.26.3 - '@babel/parser': 7.26.3 - '@babel/template': 7.25.9 - '@babel/types': 7.26.3 - debug: 4.3.7 + '@babel/generator': 7.27.0 + '@babel/parser': 7.27.0 + '@babel/template': 7.27.0 + '@babel/types': 7.27.0 + debug: 4.4.0 globals: 11.12.0 transitivePeerDependencies: - supports-color - '@babel/types@7.26.3': + '@babel/types@7.27.0': dependencies: '@babel/helper-string-parser': 7.25.9 '@babel/helper-validator-identifier': 7.25.9 - '@clack/core@0.3.4': + '@clack/core@0.3.5': dependencies: picocolors: 1.1.1 sisteransi: 1.0.5 - '@csstools/color-helpers@5.0.1': {} + '@csstools/color-helpers@5.0.2': {} - '@csstools/css-calc@2.1.1(@csstools/css-parser-algorithms@3.0.4(@csstools/css-tokenizer@3.0.3))(@csstools/css-tokenizer@3.0.3)': + '@csstools/css-calc@2.1.2(@csstools/css-parser-algorithms@3.0.4(@csstools/css-tokenizer@3.0.3))(@csstools/css-tokenizer@3.0.3)': dependencies: '@csstools/css-parser-algorithms': 3.0.4(@csstools/css-tokenizer@3.0.3) '@csstools/css-tokenizer': 3.0.3 - '@csstools/css-color-parser@3.0.7(@csstools/css-parser-algorithms@3.0.4(@csstools/css-tokenizer@3.0.3))(@csstools/css-tokenizer@3.0.3)': + '@csstools/css-color-parser@3.0.8(@csstools/css-parser-algorithms@3.0.4(@csstools/css-tokenizer@3.0.3))(@csstools/css-tokenizer@3.0.3)': dependencies: - '@csstools/color-helpers': 5.0.1 - '@csstools/css-calc': 2.1.1(@csstools/css-parser-algorithms@3.0.4(@csstools/css-tokenizer@3.0.3))(@csstools/css-tokenizer@3.0.3) + '@csstools/color-helpers': 5.0.2 + '@csstools/css-calc': 2.1.2(@csstools/css-parser-algorithms@3.0.4(@csstools/css-tokenizer@3.0.3))(@csstools/css-tokenizer@3.0.3) '@csstools/css-parser-algorithms': 3.0.4(@csstools/css-tokenizer@3.0.3) '@csstools/css-tokenizer': 3.0.3 @@ -4816,9 +4765,9 @@ snapshots: '@ctrl/tinycolor@4.1.0': {} - '@emnapi/runtime@1.2.0': + '@emnapi/runtime@1.3.1': dependencies: - tslib: 2.6.3 + tslib: 2.8.1 optional: true '@esbuild/aix-ppc64@0.21.5': @@ -4899,12 +4848,12 @@ snapshots: '@expressive-code/core@0.38.3': dependencies: '@ctrl/tinycolor': 4.1.0 - hast-util-select: 6.0.2 - hast-util-to-html: 9.0.4 + hast-util-select: 6.0.4 + hast-util-to-html: 9.0.5 hast-util-to-text: 4.0.2 - hastscript: 9.0.0 - postcss: 8.4.49 - postcss-nested: 6.2.0(postcss@8.4.49) + hastscript: 9.0.1 + postcss: 8.5.3 + postcss-nested: 6.2.0(postcss@8.5.3) unist-util-visit: 5.0.0 unist-util-visit-parents: 6.0.1 @@ -4915,7 +4864,7 @@ snapshots: '@expressive-code/plugin-shiki@0.38.3': dependencies: '@expressive-code/core': 0.38.3 - shiki: 1.26.1 + shiki: 1.29.2 '@expressive-code/plugin-text-markers@0.38.3': dependencies: @@ -4991,7 +4940,7 @@ snapshots: '@img/sharp-wasm32@0.33.5': dependencies: - '@emnapi/runtime': 1.2.0 + '@emnapi/runtime': 1.3.1 optional: true '@img/sharp-win32-ia32@0.33.5': @@ -5000,7 +4949,7 @@ snapshots: '@img/sharp-win32-x64@0.33.5': optional: true - '@jridgewell/gen-mapping@0.3.5': + '@jridgewell/gen-mapping@0.3.8': dependencies: '@jridgewell/set-array': 1.2.1 '@jridgewell/sourcemap-codec': 1.5.0 @@ -5012,7 +4961,7 @@ snapshots: '@jridgewell/source-map@0.3.6': dependencies: - '@jridgewell/gen-mapping': 0.3.5 + '@jridgewell/gen-mapping': 0.3.8 '@jridgewell/trace-mapping': 0.3.25 '@jridgewell/sourcemap-codec@1.5.0': {} @@ -5024,44 +4973,44 @@ snapshots: '@kwsites/file-exists@1.1.1': dependencies: - debug: 4.3.7 + debug: 4.4.0 transitivePeerDependencies: - supports-color '@kwsites/promise-deferred@1.1.1': {} - '@lorenzo_lewis/starlight-utils@0.2.0(@astrojs/starlight@0.29.2(patch_hash=cce5b634885e07791c60f64102f8e7a74def815cdbc19d8aa069b9f4602f2890)(astro@4.16.18(@types/node@22.13.10)(rollup@2.79.1)(sass@1.83.4)(terser@5.31.0)(typescript@5.7.3)))(astro@4.16.18(@types/node@22.13.10)(rollup@2.79.1)(sass@1.83.4)(terser@5.31.0)(typescript@5.7.3))': + '@lorenzo_lewis/starlight-utils@0.2.0(@astrojs/starlight@0.29.2(patch_hash=cce5b634885e07791c60f64102f8e7a74def815cdbc19d8aa069b9f4602f2890)(astro@4.16.18(@types/node@22.13.13)(rollup@2.79.2)(sass@1.86.0)(terser@5.39.0)(typescript@5.7.3)))(astro@4.16.18(@types/node@22.13.13)(rollup@2.79.2)(sass@1.86.0)(terser@5.39.0)(typescript@5.7.3))': dependencies: - '@astrojs/starlight': 0.29.2(patch_hash=cce5b634885e07791c60f64102f8e7a74def815cdbc19d8aa069b9f4602f2890)(astro@4.16.18(@types/node@22.13.10)(rollup@2.79.1)(sass@1.83.4)(terser@5.31.0)(typescript@5.7.3)) - astro: 4.16.18(@types/node@22.13.10)(rollup@2.79.1)(sass@1.83.4)(terser@5.31.0)(typescript@5.7.3) - astro-integration-kit: 0.16.1(astro@4.16.18(@types/node@22.13.10)(rollup@2.79.1)(sass@1.83.4)(terser@5.31.0)(typescript@5.7.3)) + '@astrojs/starlight': 0.29.2(patch_hash=cce5b634885e07791c60f64102f8e7a74def815cdbc19d8aa069b9f4602f2890)(astro@4.16.18(@types/node@22.13.13)(rollup@2.79.2)(sass@1.86.0)(terser@5.39.0)(typescript@5.7.3)) + astro: 4.16.18(@types/node@22.13.13)(rollup@2.79.2)(sass@1.86.0)(terser@5.39.0)(typescript@5.7.3) + astro-integration-kit: 0.16.1(astro@4.16.18(@types/node@22.13.13)(rollup@2.79.2)(sass@1.86.0)(terser@5.39.0)(typescript@5.7.3)) '@lunariajs/core@0.1.1': dependencies: - '@clack/core': 0.3.4 - fast-glob: 3.3.2 + '@clack/core': 0.3.5 + fast-glob: 3.3.3 get-port: 7.1.0 - jiti: 1.21.6 + jiti: 1.21.7 micromatch: 4.0.8 path-to-regexp: 6.3.0 picocolors: 1.1.1 simple-git: 3.27.0 ultramatter: 0.0.4 - zod: 3.23.8 + zod: 3.24.2 transitivePeerDependencies: - supports-color - '@lunariajs/starlight@0.1.1(@astrojs/starlight@0.29.2(patch_hash=cce5b634885e07791c60f64102f8e7a74def815cdbc19d8aa069b9f4602f2890)(astro@4.16.18(@types/node@22.13.10)(rollup@2.79.1)(sass@1.83.4)(terser@5.31.0)(typescript@5.7.3)))(astro@4.16.18(@types/node@22.13.10)(rollup@2.79.1)(sass@1.83.4)(terser@5.31.0)(typescript@5.7.3))': + '@lunariajs/starlight@0.1.1(@astrojs/starlight@0.29.2(patch_hash=cce5b634885e07791c60f64102f8e7a74def815cdbc19d8aa069b9f4602f2890)(astro@4.16.18(@types/node@22.13.13)(rollup@2.79.2)(sass@1.86.0)(terser@5.39.0)(typescript@5.7.3)))(astro@4.16.18(@types/node@22.13.13)(rollup@2.79.2)(sass@1.86.0)(terser@5.39.0)(typescript@5.7.3))': dependencies: - '@astrojs/starlight': 0.29.2(patch_hash=cce5b634885e07791c60f64102f8e7a74def815cdbc19d8aa069b9f4602f2890)(astro@4.16.18(@types/node@22.13.10)(rollup@2.79.1)(sass@1.83.4)(terser@5.31.0)(typescript@5.7.3)) + '@astrojs/starlight': 0.29.2(patch_hash=cce5b634885e07791c60f64102f8e7a74def815cdbc19d8aa069b9f4602f2890)(astro@4.16.18(@types/node@22.13.13)(rollup@2.79.2)(sass@1.86.0)(terser@5.39.0)(typescript@5.7.3)) '@lunariajs/core': 0.1.1 - astro: 4.16.18(@types/node@22.13.10)(rollup@2.79.1)(sass@1.83.4)(terser@5.31.0)(typescript@5.7.3) + astro: 4.16.18(@types/node@22.13.13)(rollup@2.79.2)(sass@1.86.0)(terser@5.39.0)(typescript@5.7.3) transitivePeerDependencies: - supports-color - '@mdx-js/mdx@3.1.0(acorn@8.14.0)': + '@mdx-js/mdx@3.1.0(acorn@8.14.1)': dependencies: - '@types/estree': 1.0.6 + '@types/estree': 1.0.7 '@types/estree-jsx': 1.0.5 '@types/hast': 3.0.4 '@types/mdx': 2.0.13 @@ -5070,13 +5019,13 @@ snapshots: estree-util-is-identifier-name: 3.0.0 estree-util-scope: 1.0.0 estree-walker: 3.0.3 - hast-util-to-jsx-runtime: 2.3.0 + hast-util-to-jsx-runtime: 2.3.6 markdown-extensions: 2.0.0 recma-build-jsx: 1.0.0 - recma-jsx: 1.0.0(acorn@8.14.0) + recma-jsx: 1.0.0(acorn@8.14.1) recma-stringify: 1.0.0 rehype-recma: 1.0.0 - remark-mdx: 3.0.1 + remark-mdx: 3.1.0 remark-parse: 11.0.0 remark-rehype: 11.1.1 source-map: 0.7.4 @@ -5099,25 +5048,25 @@ snapshots: '@nodelib/fs.walk@1.2.8': dependencies: '@nodelib/fs.scandir': 2.1.5 - fastq: 1.17.1 + fastq: 1.19.1 '@oslojs/encoding@1.1.0': {} - '@pagefind/darwin-arm64@1.1.1': + '@pagefind/darwin-arm64@1.3.0': optional: true - '@pagefind/darwin-x64@1.1.1': + '@pagefind/darwin-x64@1.3.0': optional: true - '@pagefind/default-ui@1.1.1': {} + '@pagefind/default-ui@1.3.0': {} - '@pagefind/linux-arm64@1.1.1': + '@pagefind/linux-arm64@1.3.0': optional: true - '@pagefind/linux-x64@1.1.1': + '@pagefind/linux-x64@1.3.0': optional: true - '@pagefind/windows-x64@1.1.1': + '@pagefind/windows-x64@1.3.0': optional: true '@parcel/watcher-android-arm64@2.5.1': @@ -5181,143 +5130,149 @@ snapshots: '@parcel/watcher-win32-x64': 2.5.1 optional: true - '@rollup/plugin-babel@5.3.1(@babel/core@7.26.0)(@types/babel__core@7.20.5)(rollup@2.79.1)': + '@rollup/plugin-babel@5.3.1(@babel/core@7.26.10)(@types/babel__core@7.20.5)(rollup@2.79.2)': dependencies: - '@babel/core': 7.26.0 + '@babel/core': 7.26.10 '@babel/helper-module-imports': 7.25.9 - '@rollup/pluginutils': 3.1.0(rollup@2.79.1) - rollup: 2.79.1 + '@rollup/pluginutils': 3.1.0(rollup@2.79.2) + rollup: 2.79.2 optionalDependencies: '@types/babel__core': 7.20.5 transitivePeerDependencies: - supports-color - '@rollup/plugin-node-resolve@11.2.1(rollup@2.79.1)': + '@rollup/plugin-node-resolve@11.2.1(rollup@2.79.2)': dependencies: - '@rollup/pluginutils': 3.1.0(rollup@2.79.1) + '@rollup/pluginutils': 3.1.0(rollup@2.79.2) '@types/resolve': 1.17.1 builtin-modules: 3.3.0 deepmerge: 4.3.1 is-module: 1.0.0 - resolve: 1.22.8 - rollup: 2.79.1 + resolve: 1.22.10 + rollup: 2.79.2 - '@rollup/plugin-replace@2.4.2(rollup@2.79.1)': + '@rollup/plugin-replace@2.4.2(rollup@2.79.2)': dependencies: - '@rollup/pluginutils': 3.1.0(rollup@2.79.1) + '@rollup/pluginutils': 3.1.0(rollup@2.79.2) magic-string: 0.25.9 - rollup: 2.79.1 + rollup: 2.79.2 - '@rollup/pluginutils@3.1.0(rollup@2.79.1)': + '@rollup/pluginutils@3.1.0(rollup@2.79.2)': dependencies: '@types/estree': 0.0.39 estree-walker: 1.0.1 picomatch: 2.3.1 - rollup: 2.79.1 + rollup: 2.79.2 - '@rollup/pluginutils@5.1.3(rollup@2.79.1)': + '@rollup/pluginutils@5.1.4(rollup@2.79.2)': dependencies: - '@types/estree': 1.0.6 + '@types/estree': 1.0.7 estree-walker: 2.0.2 picomatch: 4.0.2 optionalDependencies: - rollup: 2.79.1 + rollup: 2.79.2 + + '@rollup/rollup-android-arm-eabi@4.37.0': + optional: true + + '@rollup/rollup-android-arm64@4.37.0': + optional: true - '@rollup/rollup-android-arm-eabi@4.28.0': + '@rollup/rollup-darwin-arm64@4.37.0': optional: true - '@rollup/rollup-android-arm64@4.28.0': + '@rollup/rollup-darwin-x64@4.37.0': optional: true - '@rollup/rollup-darwin-arm64@4.28.0': + '@rollup/rollup-freebsd-arm64@4.37.0': optional: true - '@rollup/rollup-darwin-x64@4.28.0': + '@rollup/rollup-freebsd-x64@4.37.0': optional: true - '@rollup/rollup-freebsd-arm64@4.28.0': + '@rollup/rollup-linux-arm-gnueabihf@4.37.0': optional: true - '@rollup/rollup-freebsd-x64@4.28.0': + '@rollup/rollup-linux-arm-musleabihf@4.37.0': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.28.0': + '@rollup/rollup-linux-arm64-gnu@4.37.0': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.28.0': + '@rollup/rollup-linux-arm64-musl@4.37.0': optional: true - '@rollup/rollup-linux-arm64-gnu@4.28.0': + '@rollup/rollup-linux-loongarch64-gnu@4.37.0': optional: true - '@rollup/rollup-linux-arm64-musl@4.28.0': + '@rollup/rollup-linux-powerpc64le-gnu@4.37.0': optional: true - '@rollup/rollup-linux-powerpc64le-gnu@4.28.0': + '@rollup/rollup-linux-riscv64-gnu@4.37.0': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.28.0': + '@rollup/rollup-linux-riscv64-musl@4.37.0': optional: true - '@rollup/rollup-linux-s390x-gnu@4.28.0': + '@rollup/rollup-linux-s390x-gnu@4.37.0': optional: true - '@rollup/rollup-linux-x64-gnu@4.28.0': + '@rollup/rollup-linux-x64-gnu@4.37.0': optional: true - '@rollup/rollup-linux-x64-musl@4.28.0': + '@rollup/rollup-linux-x64-musl@4.37.0': optional: true - '@rollup/rollup-win32-arm64-msvc@4.28.0': + '@rollup/rollup-win32-arm64-msvc@4.37.0': optional: true - '@rollup/rollup-win32-ia32-msvc@4.28.0': + '@rollup/rollup-win32-ia32-msvc@4.37.0': optional: true - '@rollup/rollup-win32-x64-msvc@4.28.0': + '@rollup/rollup-win32-x64-msvc@4.37.0': optional: true - '@shikijs/core@1.26.1': + '@shikijs/core@1.29.2': dependencies: - '@shikijs/engine-javascript': 1.26.1 - '@shikijs/engine-oniguruma': 1.26.1 - '@shikijs/types': 1.26.1 - '@shikijs/vscode-textmate': 10.0.1 + '@shikijs/engine-javascript': 1.29.2 + '@shikijs/engine-oniguruma': 1.29.2 + '@shikijs/types': 1.29.2 + '@shikijs/vscode-textmate': 10.0.2 '@types/hast': 3.0.4 - hast-util-to-html: 9.0.4 + hast-util-to-html: 9.0.5 - '@shikijs/engine-javascript@1.26.1': + '@shikijs/engine-javascript@1.29.2': dependencies: - '@shikijs/types': 1.26.1 - '@shikijs/vscode-textmate': 10.0.1 - oniguruma-to-es: 0.10.0 + '@shikijs/types': 1.29.2 + '@shikijs/vscode-textmate': 10.0.2 + oniguruma-to-es: 2.3.0 - '@shikijs/engine-oniguruma@1.26.1': + '@shikijs/engine-oniguruma@1.29.2': dependencies: - '@shikijs/types': 1.26.1 - '@shikijs/vscode-textmate': 10.0.1 + '@shikijs/types': 1.29.2 + '@shikijs/vscode-textmate': 10.0.2 - '@shikijs/langs@1.26.1': + '@shikijs/langs@1.29.2': dependencies: - '@shikijs/types': 1.26.1 + '@shikijs/types': 1.29.2 - '@shikijs/themes@1.26.1': + '@shikijs/themes@1.29.2': dependencies: - '@shikijs/types': 1.26.1 + '@shikijs/types': 1.29.2 - '@shikijs/types@1.26.1': + '@shikijs/types@1.29.2': dependencies: - '@shikijs/vscode-textmate': 10.0.1 + '@shikijs/vscode-textmate': 10.0.2 '@types/hast': 3.0.4 - '@shikijs/vscode-textmate@10.0.1': {} + '@shikijs/vscode-textmate@10.0.2': {} '@surma/rollup-plugin-off-main-thread@2.2.3': dependencies: ejs: 3.1.10 json5: 2.2.3 magic-string: 0.25.9 - string.prototype.matchall: 4.0.11 + string.prototype.matchall: 4.0.12 '@tauri-apps/cli-darwin-arm64@2.3.1': optional: true @@ -5362,45 +5317,43 @@ snapshots: '@tauri-apps/cli-win32-ia32-msvc': 2.3.1 '@tauri-apps/cli-win32-x64-msvc': 2.3.1 - '@types/acorn@4.0.6': - dependencies: - '@types/estree': 1.0.6 - '@types/babel__core@7.20.5': dependencies: - '@babel/parser': 7.26.3 - '@babel/types': 7.26.3 + '@babel/parser': 7.27.0 + '@babel/types': 7.27.0 '@types/babel__generator': 7.6.8 '@types/babel__template': 7.4.4 - '@types/babel__traverse': 7.20.6 + '@types/babel__traverse': 7.20.7 '@types/babel__generator@7.6.8': dependencies: - '@babel/types': 7.26.3 + '@babel/types': 7.27.0 '@types/babel__template@7.4.4': dependencies: - '@babel/parser': 7.26.3 - '@babel/types': 7.26.3 + '@babel/parser': 7.27.0 + '@babel/types': 7.27.0 - '@types/babel__traverse@7.20.6': + '@types/babel__traverse@7.20.7': dependencies: - '@babel/types': 7.26.3 + '@babel/types': 7.27.0 '@types/cookie@0.6.0': {} '@types/debug@4.1.12': dependencies: - '@types/ms': 0.7.34 + '@types/ms': 2.1.0 '@types/estree-jsx@1.0.5': dependencies: - '@types/estree': 1.0.6 + '@types/estree': 1.0.7 '@types/estree@0.0.39': {} '@types/estree@1.0.6': {} + '@types/estree@1.0.7': {} + '@types/hast@3.0.4': dependencies: '@types/unist': 3.0.3 @@ -5413,7 +5366,7 @@ snapshots: '@types/mdx@2.0.13': {} - '@types/ms@0.7.34': {} + '@types/ms@2.1.0': {} '@types/nlcst@2.0.3': dependencies: @@ -5425,15 +5378,19 @@ snapshots: dependencies: undici-types: 6.20.0 + '@types/node@22.13.13': + dependencies: + undici-types: 6.20.0 + '@types/picomatch@2.3.3': {} '@types/resolve@1.17.1': dependencies: - '@types/node': 22.13.10 + '@types/node': 22.13.13 '@types/sax@1.2.7': dependencies: - '@types/node': 22.13.10 + '@types/node': 17.0.45 '@types/semver@7.5.8': {} @@ -5443,22 +5400,22 @@ snapshots: '@types/unist@3.0.3': {} - '@ungap/structured-clone@1.2.0': {} + '@ungap/structured-clone@1.3.0': {} - acorn-jsx@5.3.2(acorn@8.14.0): + acorn-jsx@5.3.2(acorn@8.14.1): dependencies: - acorn: 8.14.0 + acorn: 8.14.1 - acorn@8.14.0: {} + acorn@8.14.1: {} agent-base@7.1.3: {} - ajv@8.13.0: + ajv@8.17.1: dependencies: fast-deep-equal: 3.1.3 + fast-uri: 3.0.6 json-schema-traverse: 1.0.0 require-from-string: 2.0.2 - uri-js: 4.4.1 ansi-align@3.0.1: dependencies: @@ -5484,92 +5441,91 @@ snapshots: aria-query@5.3.2: {} - array-buffer-byte-length@1.0.1: + array-buffer-byte-length@1.0.2: dependencies: - call-bind: 1.0.7 - is-array-buffer: 3.0.4 + call-bound: 1.0.4 + is-array-buffer: 3.0.5 array-iterate@2.0.1: {} - arraybuffer.prototype.slice@1.0.3: + arraybuffer.prototype.slice@1.0.4: dependencies: - array-buffer-byte-length: 1.0.1 - call-bind: 1.0.7 + array-buffer-byte-length: 1.0.2 + call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.23.3 + es-abstract: 1.23.9 es-errors: 1.3.0 - get-intrinsic: 1.2.4 - is-array-buffer: 3.0.4 - is-shared-array-buffer: 1.0.3 + get-intrinsic: 1.3.0 + is-array-buffer: 3.0.5 ast-types@0.16.1: dependencies: - tslib: 2.6.3 + tslib: 2.8.1 astring@1.9.0: {} - astro-d2@0.6.0(astro@4.16.18(@types/node@22.13.10)(rollup@2.79.1)(sass@1.83.4)(terser@5.31.0)(typescript@5.7.3)): + astro-d2@0.6.0(astro@4.16.18(@types/node@22.13.13)(rollup@2.79.2)(sass@1.86.0)(terser@5.39.0)(typescript@5.7.3)): dependencies: - astro: 4.16.18(@types/node@22.13.10)(rollup@2.79.1)(sass@1.83.4)(terser@5.31.0)(typescript@5.7.3) + astro: 4.16.18(@types/node@22.13.13)(rollup@2.79.2)(sass@1.86.0)(terser@5.39.0)(typescript@5.7.3) hast-util-from-html: 2.0.3 hast-util-to-html: 9.0.3 unist-util-visit: 5.0.0 - astro-expressive-code@0.38.3(astro@4.16.18(@types/node@22.13.10)(rollup@2.79.1)(sass@1.83.4)(terser@5.31.0)(typescript@5.7.3)): + astro-expressive-code@0.38.3(astro@4.16.18(@types/node@22.13.13)(rollup@2.79.2)(sass@1.86.0)(terser@5.39.0)(typescript@5.7.3)): dependencies: - astro: 4.16.18(@types/node@22.13.10)(rollup@2.79.1)(sass@1.83.4)(terser@5.31.0)(typescript@5.7.3) + astro: 4.16.18(@types/node@22.13.13)(rollup@2.79.2)(sass@1.86.0)(terser@5.39.0)(typescript@5.7.3) rehype-expressive-code: 0.38.3 astro-feelback@0.3.4: dependencies: '@feelback/js': 0.3.4 - astro-integration-kit@0.16.1(astro@4.16.18(@types/node@22.13.10)(rollup@2.79.1)(sass@1.83.4)(terser@5.31.0)(typescript@5.7.3)): + astro-integration-kit@0.16.1(astro@4.16.18(@types/node@22.13.13)(rollup@2.79.2)(sass@1.86.0)(terser@5.39.0)(typescript@5.7.3)): dependencies: - astro: 4.16.18(@types/node@22.13.10)(rollup@2.79.1)(sass@1.83.4)(terser@5.31.0)(typescript@5.7.3) + astro: 4.16.18(@types/node@22.13.13)(rollup@2.79.2)(sass@1.86.0)(terser@5.39.0)(typescript@5.7.3) pathe: 1.1.2 - recast: 0.23.9 + recast: 0.23.11 astro-remote@0.3.2: dependencies: entities: 4.5.0 marked: 12.0.2 marked-footnote: 1.2.4(marked@12.0.2) - marked-smartypants: 1.1.8(marked@12.0.2) + marked-smartypants: 1.1.9(marked@12.0.2) ultrahtml: 1.5.3 - astro@4.16.18(@types/node@22.13.10)(rollup@2.79.1)(sass@1.83.4)(terser@5.31.0)(typescript@5.7.3): + astro@4.16.18(@types/node@22.13.13)(rollup@2.79.2)(sass@1.86.0)(terser@5.39.0)(typescript@5.7.3): dependencies: - '@astrojs/compiler': 2.10.3 + '@astrojs/compiler': 2.11.0 '@astrojs/internal-helpers': 0.4.1 '@astrojs/markdown-remark': 5.3.0 '@astrojs/telemetry': 3.1.0 - '@babel/core': 7.26.0 - '@babel/plugin-transform-react-jsx': 7.25.9(@babel/core@7.26.0) - '@babel/types': 7.26.3 + '@babel/core': 7.26.10 + '@babel/plugin-transform-react-jsx': 7.25.9(@babel/core@7.26.10) + '@babel/types': 7.27.0 '@oslojs/encoding': 1.1.0 - '@rollup/pluginutils': 5.1.3(rollup@2.79.1) + '@rollup/pluginutils': 5.1.4(rollup@2.79.2) '@types/babel__core': 7.20.5 '@types/cookie': 0.6.0 - acorn: 8.14.0 + acorn: 8.14.1 aria-query: 5.3.2 axobject-query: 4.1.0 boxen: 8.0.1 - ci-info: 4.1.0 + ci-info: 4.2.0 clsx: 2.1.1 common-ancestor-path: 1.0.1 cookie: 0.7.2 cssesc: 3.0.0 - debug: 4.3.7 + debug: 4.4.0 deterministic-object-hash: 2.0.2 devalue: 5.1.1 diff: 5.2.0 dlv: 1.1.3 dset: 3.1.4 - es-module-lexer: 1.5.4 + es-module-lexer: 1.6.0 esbuild: 0.21.5 estree-walker: 3.0.3 - fast-glob: 3.3.2 + fast-glob: 3.3.3 flattie: 1.1.1 github-slugger: 2.0.0 gray-matter: 4.0.3 @@ -5577,31 +5533,31 @@ snapshots: http-cache-semantics: 4.1.1 js-yaml: 4.1.0 kleur: 4.1.5 - magic-string: 0.30.14 + magic-string: 0.30.17 magicast: 0.3.5 micromatch: 4.0.8 - mrmime: 2.0.0 + mrmime: 2.0.1 neotraverse: 0.6.18 - ora: 8.1.1 - p-limit: 6.1.0 - p-queue: 8.0.1 - preferred-pm: 4.0.0 + ora: 8.2.0 + p-limit: 6.2.0 + p-queue: 8.1.0 + preferred-pm: 4.1.1 prompts: 2.4.2 rehype: 13.0.2 - semver: 7.6.3 - shiki: 1.26.1 - tinyexec: 0.3.1 - tsconfck: 3.1.4(typescript@5.7.3) + semver: 7.7.1 + shiki: 1.29.2 + tinyexec: 0.3.2 + tsconfck: 3.1.5(typescript@5.7.3) unist-util-visit: 5.0.0 vfile: 6.0.3 - vite: 5.4.11(@types/node@22.13.10)(sass@1.83.4)(terser@5.31.0) - vitefu: 1.0.4(vite@5.4.11(@types/node@22.13.10)(sass@1.83.4)(terser@5.31.0)) - which-pm: 3.0.0 + vite: 5.4.15(@types/node@22.13.13)(sass@1.86.0)(terser@5.39.0) + vitefu: 1.0.6(vite@5.4.15(@types/node@22.13.13)(sass@1.86.0)(terser@5.39.0)) + which-pm: 3.0.1 xxhash-wasm: 1.1.0 yargs-parser: 21.1.1 - zod: 3.23.8 - zod-to-json-schema: 3.23.5(zod@3.23.8) - zod-to-ts: 1.2.0(typescript@5.7.3)(zod@3.23.8) + zod: 3.24.2 + zod-to-json-schema: 3.24.5(zod@3.24.2) + zod-to-ts: 1.2.0(typescript@5.7.3)(zod@3.24.2) optionalDependencies: sharp: 0.33.5 transitivePeerDependencies: @@ -5617,15 +5573,17 @@ snapshots: - terser - typescript - astrojs-service-worker@2.0.0(@types/babel__core@7.20.5)(astro@4.16.18(@types/node@22.13.10)(rollup@2.79.1)(sass@1.83.4)(terser@5.31.0)(typescript@5.7.3)): + astrojs-service-worker@2.0.0(@types/babel__core@7.20.5)(astro@4.16.18(@types/node@22.13.13)(rollup@2.79.2)(sass@1.86.0)(terser@5.39.0)(typescript@5.7.3)): dependencies: - astro: 4.16.18(@types/node@22.13.10)(rollup@2.79.1)(sass@1.83.4)(terser@5.31.0)(typescript@5.7.3) + astro: 4.16.18(@types/node@22.13.13)(rollup@2.79.2)(sass@1.86.0)(terser@5.39.0)(typescript@5.7.3) workbox-build: 6.6.0(@types/babel__core@7.20.5) transitivePeerDependencies: - '@types/babel__core' - supports-color - async@3.2.5: {} + async-function@1.0.0: {} + + async@3.2.6: {} asynckit@0.4.0: {} @@ -5633,31 +5591,31 @@ snapshots: available-typed-arrays@1.0.7: dependencies: - possible-typed-array-names: 1.0.0 + possible-typed-array-names: 1.1.0 axobject-query@4.1.0: {} - babel-plugin-polyfill-corejs2@0.4.11(@babel/core@7.26.0): + babel-plugin-polyfill-corejs2@0.4.13(@babel/core@7.26.10): dependencies: - '@babel/compat-data': 7.26.3 - '@babel/core': 7.26.0 - '@babel/helper-define-polyfill-provider': 0.6.2(@babel/core@7.26.0) + '@babel/compat-data': 7.26.8 + '@babel/core': 7.26.10 + '@babel/helper-define-polyfill-provider': 0.6.4(@babel/core@7.26.10) semver: 6.3.1 transitivePeerDependencies: - supports-color - babel-plugin-polyfill-corejs3@0.10.4(@babel/core@7.26.0): + babel-plugin-polyfill-corejs3@0.11.1(@babel/core@7.26.10): dependencies: - '@babel/core': 7.26.0 - '@babel/helper-define-polyfill-provider': 0.6.2(@babel/core@7.26.0) - core-js-compat: 3.37.1 + '@babel/core': 7.26.10 + '@babel/helper-define-polyfill-provider': 0.6.4(@babel/core@7.26.10) + core-js-compat: 3.41.0 transitivePeerDependencies: - supports-color - babel-plugin-polyfill-regenerator@0.6.2(@babel/core@7.26.0): + babel-plugin-polyfill-regenerator@0.6.4(@babel/core@7.26.10): dependencies: - '@babel/core': 7.26.0 - '@babel/helper-define-polyfill-provider': 0.6.2(@babel/core@7.26.0) + '@babel/core': 7.26.10 + '@babel/helper-define-polyfill-provider': 0.6.4(@babel/core@7.26.10) transitivePeerDependencies: - supports-color @@ -5681,10 +5639,10 @@ snapshots: dependencies: ansi-align: 3.0.1 camelcase: 8.0.0 - chalk: 5.3.0 + chalk: 5.4.1 cli-boxes: 3.0.0 string-width: 7.2.0 - type-fest: 4.30.0 + type-fest: 4.38.0 widest-line: 5.0.0 wrap-ansi: 9.0.0 @@ -5701,28 +5659,37 @@ snapshots: dependencies: fill-range: 7.1.1 - browserslist@4.24.2: + browserslist@4.24.4: dependencies: - caniuse-lite: 1.0.30001686 - electron-to-chromium: 1.5.70 - node-releases: 2.0.18 - update-browserslist-db: 1.1.1(browserslist@4.24.2) + caniuse-lite: 1.0.30001707 + electron-to-chromium: 1.5.125 + node-releases: 2.0.19 + update-browserslist-db: 1.1.3(browserslist@4.24.4) buffer-from@1.1.2: {} builtin-modules@3.3.0: {} - call-bind@1.0.7: + call-bind-apply-helpers@1.0.2: dependencies: - es-define-property: 1.0.0 es-errors: 1.3.0 function-bind: 1.1.2 - get-intrinsic: 1.2.4 + + call-bind@1.0.8: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + get-intrinsic: 1.3.0 set-function-length: 1.2.2 + call-bound@1.0.4: + dependencies: + call-bind-apply-helpers: 1.0.2 + get-intrinsic: 1.3.0 + camelcase@8.0.0: {} - caniuse-lite@1.0.30001686: {} + caniuse-lite@1.0.30001707: {} ccount@2.0.1: {} @@ -5731,7 +5698,7 @@ snapshots: ansi-styles: 4.3.0 supports-color: 7.2.0 - chalk@5.3.0: {} + chalk@5.4.1: {} character-entities-html4@2.1.0: {} @@ -5743,9 +5710,9 @@ snapshots: chokidar@4.0.3: dependencies: - readdirp: 4.1.1 + readdirp: 4.1.2 - ci-info@4.1.0: {} + ci-info@4.2.0: {} cli-boxes@3.0.0: {} @@ -5793,51 +5760,51 @@ snapshots: cookie@0.7.2: {} - core-js-compat@3.37.1: + core-js-compat@3.41.0: dependencies: - browserslist: 4.24.2 + browserslist: 4.24.4 crypto-random-string@2.0.0: {} - css-selector-parser@3.0.5: {} + css-selector-parser@3.1.1: {} cssesc@3.0.0: {} - cssstyle@4.2.1: + cssstyle@4.3.0: dependencies: - '@asamuzakjp/css-color': 2.8.2 + '@asamuzakjp/css-color': 3.1.1 rrweb-cssom: 0.8.0 data-urls@5.0.0: dependencies: whatwg-mimetype: 4.0.0 - whatwg-url: 14.1.0 + whatwg-url: 14.2.0 - data-view-buffer@1.0.1: + data-view-buffer@1.0.2: dependencies: - call-bind: 1.0.7 + call-bound: 1.0.4 es-errors: 1.3.0 - is-data-view: 1.0.1 + is-data-view: 1.0.2 - data-view-byte-length@1.0.1: + data-view-byte-length@1.0.2: dependencies: - call-bind: 1.0.7 + call-bound: 1.0.4 es-errors: 1.3.0 - is-data-view: 1.0.1 + is-data-view: 1.0.2 - data-view-byte-offset@1.0.0: + data-view-byte-offset@1.0.1: dependencies: - call-bind: 1.0.7 + call-bound: 1.0.4 es-errors: 1.3.0 - is-data-view: 1.0.1 + is-data-view: 1.0.2 - debug@4.3.7: + debug@4.4.0: dependencies: ms: 2.1.3 - decimal.js@10.4.3: {} + decimal.js@10.5.0: {} - decode-named-character-reference@1.0.2: + decode-named-character-reference@1.1.0: dependencies: character-entities: 2.0.2 @@ -5845,9 +5812,9 @@ snapshots: define-data-property@1.1.4: dependencies: - es-define-property: 1.0.0 + es-define-property: 1.0.1 es-errors: 1.3.0 - gopd: 1.0.1 + gopd: 1.2.0 define-properties@1.2.1: dependencies: @@ -5882,11 +5849,17 @@ snapshots: dset@3.1.4: {} + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + ejs@3.1.10: dependencies: - jake: 10.9.1 + jake: 10.9.2 - electron-to-chromium@1.5.70: {} + electron-to-chromium@1.5.125: {} emoji-regex-xs@1.0.0: {} @@ -5896,78 +5869,82 @@ snapshots: entities@4.5.0: {} - es-abstract@1.23.3: + es-abstract@1.23.9: dependencies: - array-buffer-byte-length: 1.0.1 - arraybuffer.prototype.slice: 1.0.3 + array-buffer-byte-length: 1.0.2 + arraybuffer.prototype.slice: 1.0.4 available-typed-arrays: 1.0.7 - call-bind: 1.0.7 - data-view-buffer: 1.0.1 - data-view-byte-length: 1.0.1 - data-view-byte-offset: 1.0.0 - es-define-property: 1.0.0 + call-bind: 1.0.8 + call-bound: 1.0.4 + data-view-buffer: 1.0.2 + data-view-byte-length: 1.0.2 + data-view-byte-offset: 1.0.1 + es-define-property: 1.0.1 es-errors: 1.3.0 - es-object-atoms: 1.0.0 - es-set-tostringtag: 2.0.3 - es-to-primitive: 1.2.1 - function.prototype.name: 1.1.6 - get-intrinsic: 1.2.4 - get-symbol-description: 1.0.2 + es-object-atoms: 1.1.1 + es-set-tostringtag: 2.1.0 + es-to-primitive: 1.3.0 + function.prototype.name: 1.1.8 + get-intrinsic: 1.3.0 + get-proto: 1.0.1 + get-symbol-description: 1.1.0 globalthis: 1.0.4 - gopd: 1.0.1 + gopd: 1.2.0 has-property-descriptors: 1.0.2 - has-proto: 1.0.3 - has-symbols: 1.0.3 + has-proto: 1.2.0 + has-symbols: 1.1.0 hasown: 2.0.2 - internal-slot: 1.0.7 - is-array-buffer: 3.0.4 + internal-slot: 1.1.0 + is-array-buffer: 3.0.5 is-callable: 1.2.7 - is-data-view: 1.0.1 - is-negative-zero: 2.0.3 - is-regex: 1.1.4 - is-shared-array-buffer: 1.0.3 - is-string: 1.0.7 - is-typed-array: 1.1.13 - is-weakref: 1.0.2 - object-inspect: 1.13.1 + is-data-view: 1.0.2 + is-regex: 1.2.1 + is-shared-array-buffer: 1.0.4 + is-string: 1.1.1 + is-typed-array: 1.1.15 + is-weakref: 1.1.1 + math-intrinsics: 1.1.0 + object-inspect: 1.13.4 object-keys: 1.1.1 - object.assign: 4.1.5 - regexp.prototype.flags: 1.5.2 - safe-array-concat: 1.1.2 - safe-regex-test: 1.0.3 - string.prototype.trim: 1.2.9 - string.prototype.trimend: 1.0.8 + object.assign: 4.1.7 + own-keys: 1.0.1 + regexp.prototype.flags: 1.5.4 + safe-array-concat: 1.1.3 + safe-push-apply: 1.0.0 + safe-regex-test: 1.1.0 + set-proto: 1.0.0 + string.prototype.trim: 1.2.10 + string.prototype.trimend: 1.0.9 string.prototype.trimstart: 1.0.8 - typed-array-buffer: 1.0.2 - typed-array-byte-length: 1.0.1 - typed-array-byte-offset: 1.0.2 - typed-array-length: 1.0.6 - unbox-primitive: 1.0.2 - which-typed-array: 1.1.15 + typed-array-buffer: 1.0.3 + typed-array-byte-length: 1.0.3 + typed-array-byte-offset: 1.0.4 + typed-array-length: 1.0.7 + unbox-primitive: 1.1.0 + which-typed-array: 1.1.19 - es-define-property@1.0.0: - dependencies: - get-intrinsic: 1.2.4 + es-define-property@1.0.1: {} es-errors@1.3.0: {} - es-module-lexer@1.5.4: {} + es-module-lexer@1.6.0: {} - es-object-atoms@1.0.0: + es-object-atoms@1.1.1: dependencies: es-errors: 1.3.0 - es-set-tostringtag@2.0.3: + es-set-tostringtag@2.1.0: dependencies: - get-intrinsic: 1.2.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 has-tostringtag: 1.0.2 hasown: 2.0.2 - es-to-primitive@1.2.1: + es-to-primitive@1.3.0: dependencies: is-callable: 1.2.7 - is-date-object: 1.0.5 - is-symbol: 1.0.4 + is-date-object: 1.1.0 + is-symbol: 1.1.1 esast-util-from-estree@2.0.0: dependencies: @@ -5979,7 +5956,7 @@ snapshots: esast-util-from-js@2.0.1: dependencies: '@types/estree-jsx': 1.0.5 - acorn: 8.14.0 + acorn: 8.14.1 esast-util-from-estree: 2.0.0 vfile-message: 4.0.2 @@ -6102,7 +6079,7 @@ snapshots: estree-util-attach-comments@3.0.0: dependencies: - '@types/estree': 1.0.6 + '@types/estree': 1.0.7 estree-util-build-jsx@3.0.1: dependencies: @@ -6115,7 +6092,7 @@ snapshots: estree-util-scope@1.0.0: dependencies: - '@types/estree': 1.0.6 + '@types/estree': 1.0.7 devlop: 1.1.0 estree-util-to-js@2.0.0: @@ -6135,7 +6112,7 @@ snapshots: estree-walker@3.0.3: dependencies: - '@types/estree': 1.0.6 + '@types/estree': 1.0.7 esutils@2.0.3: {} @@ -6156,7 +6133,7 @@ snapshots: fast-deep-equal@3.1.3: {} - fast-glob@3.3.2: + fast-glob@3.3.3: dependencies: '@nodelib/fs.stat': 2.0.5 '@nodelib/fs.walk': 1.2.8 @@ -6166,13 +6143,15 @@ snapshots: fast-json-stable-stringify@2.1.0: {} - fast-xml-parser@4.5.1: + fast-uri@3.0.6: {} + + fast-xml-parser@4.5.3: dependencies: - strnum: 1.0.5 + strnum: 1.1.2 - fastq@1.17.1: + fastq@1.19.1: dependencies: - reusify: 1.0.4 + reusify: 1.1.0 filelist@1.0.4: dependencies: @@ -6182,7 +6161,7 @@ snapshots: dependencies: to-regex-range: 5.0.1 - find-up-simple@1.0.0: {} + find-up-simple@1.0.1: {} find-up@4.1.0: dependencies: @@ -6196,14 +6175,15 @@ snapshots: flattie@1.1.1: {} - for-each@0.3.3: + for-each@0.3.5: dependencies: is-callable: 1.2.7 - form-data@4.0.1: + form-data@4.0.2: dependencies: asynckit: 0.4.0 combined-stream: 1.0.8 + es-set-tostringtag: 2.1.0 mime-types: 2.1.35 fs-extra@9.1.0: @@ -6220,12 +6200,14 @@ snapshots: function-bind@1.1.2: {} - function.prototype.name@1.1.6: + function.prototype.name@1.1.8: dependencies: - call-bind: 1.0.7 + call-bind: 1.0.8 + call-bound: 1.0.4 define-properties: 1.2.1 - es-abstract: 1.23.3 functions-have-names: 1.2.3 + hasown: 2.0.2 + is-callable: 1.2.7 functions-have-names@1.2.3: {} @@ -6233,23 +6215,33 @@ snapshots: get-east-asian-width@1.3.0: {} - get-intrinsic@1.2.4: + get-intrinsic@1.3.0: dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 es-errors: 1.3.0 + es-object-atoms: 1.1.1 function-bind: 1.1.2 - has-proto: 1.0.3 - has-symbols: 1.0.3 + get-proto: 1.0.1 + gopd: 1.2.0 + has-symbols: 1.1.0 hasown: 2.0.2 + math-intrinsics: 1.1.0 get-own-enumerable-property-symbols@3.0.2: {} get-port@7.1.0: {} - get-symbol-description@1.0.2: + get-proto@1.0.1: dependencies: - call-bind: 1.0.7 + dunder-proto: 1.0.1 + es-object-atoms: 1.1.1 + + get-symbol-description@1.1.0: + dependencies: + call-bound: 1.0.4 es-errors: 1.3.0 - get-intrinsic: 1.2.4 + get-intrinsic: 1.3.0 github-slugger@2.0.0: {} @@ -6271,11 +6263,9 @@ snapshots: globalthis@1.0.4: dependencies: define-properties: 1.2.1 - gopd: 1.0.1 + gopd: 1.2.0 - gopd@1.0.1: - dependencies: - get-intrinsic: 1.2.4 + gopd@1.2.0: {} graceful-fs@4.2.11: {} @@ -6286,21 +6276,23 @@ snapshots: section-matter: 1.0.0 strip-bom-string: 1.0.0 - has-bigints@1.0.2: {} + has-bigints@1.1.0: {} has-flag@4.0.0: {} has-property-descriptors@1.0.2: dependencies: - es-define-property: 1.0.0 + es-define-property: 1.0.1 - has-proto@1.0.3: {} + has-proto@1.2.0: + dependencies: + dunder-proto: 1.0.1 - has-symbols@1.0.3: {} + has-symbols@1.1.0: {} has-tostringtag@1.0.2: dependencies: - has-symbols: 1.0.3 + has-symbols: 1.1.0 hasown@2.0.2: dependencies: @@ -6315,17 +6307,17 @@ snapshots: dependencies: '@types/hast': 3.0.4 hast-util-embedded: 3.0.0 - hast-util-minify-whitespace: 1.0.0 + hast-util-minify-whitespace: 1.0.1 hast-util-phrasing: 3.0.1 hast-util-whitespace: 3.0.0 - html-whitespace-sensitive-tag-names: 3.0.0 + html-whitespace-sensitive-tag-names: 3.0.1 unist-util-visit-parents: 6.0.1 hast-util-from-html@2.0.1: dependencies: '@types/hast': 3.0.4 devlop: 1.1.0 - hast-util-from-parse5: 8.0.2 + hast-util-from-parse5: 8.0.3 parse5: 7.2.1 vfile: 6.0.3 vfile-message: 4.0.2 @@ -6334,18 +6326,18 @@ snapshots: dependencies: '@types/hast': 3.0.4 devlop: 1.1.0 - hast-util-from-parse5: 8.0.2 + hast-util-from-parse5: 8.0.3 parse5: 7.2.1 vfile: 6.0.3 vfile-message: 4.0.2 - hast-util-from-parse5@8.0.2: + hast-util-from-parse5@8.0.3: dependencies: '@types/hast': 3.0.4 '@types/unist': 3.0.3 devlop: 1.1.0 - hastscript: 9.0.0 - property-information: 6.5.0 + hastscript: 9.0.1 + property-information: 7.0.0 vfile: 6.0.3 vfile-location: 5.0.3 web-namespaces: 2.0.1 @@ -6358,7 +6350,7 @@ snapshots: dependencies: '@types/hast': 3.0.4 - hast-util-is-body-ok-link@3.0.0: + hast-util-is-body-ok-link@3.0.1: dependencies: '@types/hast': 3.0.4 @@ -6366,7 +6358,7 @@ snapshots: dependencies: '@types/hast': 3.0.4 - hast-util-minify-whitespace@1.0.0: + hast-util-minify-whitespace@1.0.1: dependencies: '@types/hast': 3.0.4 hast-util-embedded: 3.0.0 @@ -6383,15 +6375,15 @@ snapshots: '@types/hast': 3.0.4 hast-util-embedded: 3.0.0 hast-util-has-property: 3.0.0 - hast-util-is-body-ok-link: 3.0.0 + hast-util-is-body-ok-link: 3.0.1 hast-util-is-element: 3.0.0 - hast-util-raw@9.0.4: + hast-util-raw@9.1.0: dependencies: '@types/hast': 3.0.4 '@types/unist': 3.0.3 - '@ungap/structured-clone': 1.2.0 - hast-util-from-parse5: 8.0.2 + '@ungap/structured-clone': 1.3.0 + hast-util-from-parse5: 8.0.3 hast-util-to-parse5: 8.0.0 html-void-elements: 3.0.0 mdast-util-to-hast: 13.2.0 @@ -6402,28 +6394,27 @@ snapshots: web-namespaces: 2.0.1 zwitch: 2.0.4 - hast-util-select@6.0.2: + hast-util-select@6.0.4: dependencies: '@types/hast': 3.0.4 '@types/unist': 3.0.3 bcp-47-match: 2.0.3 comma-separated-tokens: 2.0.3 - css-selector-parser: 3.0.5 + css-selector-parser: 3.1.1 devlop: 1.1.0 direction: 2.0.1 hast-util-has-property: 3.0.0 - hast-util-to-string: 3.0.0 + hast-util-to-string: 3.0.1 hast-util-whitespace: 3.0.0 - not: 0.1.0 nth-check: 2.1.1 - property-information: 6.5.0 + property-information: 7.0.0 space-separated-tokens: 2.0.2 unist-util-visit: 5.0.0 zwitch: 2.0.4 - hast-util-to-estree@3.1.0: + hast-util-to-estree@3.1.3: dependencies: - '@types/estree': 1.0.6 + '@types/estree': 1.0.7 '@types/estree-jsx': 1.0.5 '@types/hast': 3.0.4 comma-separated-tokens: 2.0.3 @@ -6432,11 +6423,11 @@ snapshots: estree-util-is-identifier-name: 3.0.0 hast-util-whitespace: 3.0.0 mdast-util-mdx-expression: 2.0.1 - mdast-util-mdx-jsx: 3.1.3 + mdast-util-mdx-jsx: 3.2.0 mdast-util-mdxjs-esm: 2.0.1 - property-information: 6.5.0 + property-information: 7.0.0 space-separated-tokens: 2.0.2 - style-to-object: 0.4.4 + style-to-js: 1.1.16 unist-util-position: 5.0.0 zwitch: 2.0.4 transitivePeerDependencies: @@ -6456,7 +6447,7 @@ snapshots: stringify-entities: 4.0.4 zwitch: 2.0.4 - hast-util-to-html@9.0.4: + hast-util-to-html@9.0.5: dependencies: '@types/hast': 3.0.4 '@types/unist': 3.0.3 @@ -6465,14 +6456,14 @@ snapshots: hast-util-whitespace: 3.0.0 html-void-elements: 3.0.0 mdast-util-to-hast: 13.2.0 - property-information: 6.5.0 + property-information: 7.0.0 space-separated-tokens: 2.0.2 stringify-entities: 4.0.4 zwitch: 2.0.4 - hast-util-to-jsx-runtime@2.3.0: + hast-util-to-jsx-runtime@2.3.6: dependencies: - '@types/estree': 1.0.6 + '@types/estree': 1.0.7 '@types/hast': 3.0.4 '@types/unist': 3.0.3 comma-separated-tokens: 2.0.3 @@ -6480,11 +6471,11 @@ snapshots: estree-util-is-identifier-name: 3.0.0 hast-util-whitespace: 3.0.0 mdast-util-mdx-expression: 2.0.1 - mdast-util-mdx-jsx: 3.1.3 + mdast-util-mdx-jsx: 3.2.0 mdast-util-mdxjs-esm: 2.0.1 - property-information: 6.5.0 + property-information: 7.0.0 space-separated-tokens: 2.0.2 - style-to-object: 1.0.8 + style-to-js: 1.1.16 unist-util-position: 5.0.0 vfile-message: 4.0.2 transitivePeerDependencies: @@ -6500,7 +6491,7 @@ snapshots: web-namespaces: 2.0.1 zwitch: 2.0.4 - hast-util-to-string@3.0.0: + hast-util-to-string@3.0.1: dependencies: '@types/hast': 3.0.4 @@ -6515,12 +6506,12 @@ snapshots: dependencies: '@types/hast': 3.0.4 - hastscript@9.0.0: + hastscript@9.0.1: dependencies: '@types/hast': 3.0.4 comma-separated-tokens: 2.0.3 hast-util-parse-selector: 4.0.0 - property-information: 6.5.0 + property-information: 7.0.0 space-separated-tokens: 2.0.2 html-encoding-sniffer@4.0.0: @@ -6531,27 +6522,27 @@ snapshots: html-void-elements@3.0.0: {} - html-whitespace-sensitive-tag-names@3.0.0: {} + html-whitespace-sensitive-tag-names@3.0.1: {} http-cache-semantics@4.1.1: {} http-proxy-agent@7.0.2: dependencies: agent-base: 7.1.3 - debug: 4.3.7 + debug: 4.4.0 transitivePeerDependencies: - supports-color https-proxy-agent@7.0.6: dependencies: agent-base: 7.1.3 - debug: 4.3.7 + debug: 4.4.0 transitivePeerDependencies: - supports-color - i18next@23.15.1: + i18next@23.16.8: dependencies: - '@babel/runtime': 7.25.6 + '@babel/runtime': 7.27.0 iconv-lite@0.6.3: dependencies: @@ -6559,7 +6550,7 @@ snapshots: idb@7.1.1: {} - immutable@5.0.3: {} + immutable@5.1.1: {} import-meta-resolve@4.1.0: {} @@ -6570,15 +6561,13 @@ snapshots: inherits@2.0.4: {} - inline-style-parser@0.1.1: {} - inline-style-parser@0.2.4: {} - internal-slot@1.0.7: + internal-slot@1.1.0: dependencies: es-errors: 1.3.0 hasown: 2.0.2 - side-channel: 1.0.6 + side-channel: 1.1.0 is-absolute-url@4.0.1: {} @@ -6589,34 +6578,46 @@ snapshots: is-alphabetical: 2.0.1 is-decimal: 2.0.1 - is-array-buffer@3.0.4: + is-array-buffer@3.0.5: dependencies: - call-bind: 1.0.7 - get-intrinsic: 1.2.4 + call-bind: 1.0.8 + call-bound: 1.0.4 + get-intrinsic: 1.3.0 is-arrayish@0.3.2: {} - is-bigint@1.0.4: + is-async-function@2.1.1: dependencies: - has-bigints: 1.0.2 + async-function: 1.0.0 + call-bound: 1.0.4 + get-proto: 1.0.1 + has-tostringtag: 1.0.2 + safe-regex-test: 1.1.0 + + is-bigint@1.1.0: + dependencies: + has-bigints: 1.1.0 - is-boolean-object@1.1.2: + is-boolean-object@1.2.2: dependencies: - call-bind: 1.0.7 + call-bound: 1.0.4 has-tostringtag: 1.0.2 is-callable@1.2.7: {} - is-core-module@2.14.0: + is-core-module@2.16.1: dependencies: hasown: 2.0.2 - is-data-view@1.0.1: + is-data-view@1.0.2: dependencies: - is-typed-array: 1.1.13 + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + is-typed-array: 1.1.15 - is-date-object@1.0.5: + is-date-object@1.1.0: dependencies: + call-bound: 1.0.4 has-tostringtag: 1.0.2 is-decimal@2.0.1: {} @@ -6627,8 +6628,19 @@ snapshots: is-extglob@2.1.1: {} + is-finalizationregistry@1.1.1: + dependencies: + call-bound: 1.0.4 + is-fullwidth-code-point@3.0.0: {} + is-generator-function@1.1.0: + dependencies: + call-bound: 1.0.4 + get-proto: 1.0.1 + has-tostringtag: 1.0.2 + safe-regex-test: 1.1.0 + is-glob@4.0.3: dependencies: is-extglob: 2.1.1 @@ -6641,12 +6653,13 @@ snapshots: is-interactive@2.0.0: {} - is-module@1.0.0: {} + is-map@2.0.3: {} - is-negative-zero@2.0.3: {} + is-module@1.0.0: {} - is-number-object@1.0.7: + is-number-object@1.1.1: dependencies: + call-bound: 1.0.4 has-tostringtag: 1.0.2 is-number@7.0.0: {} @@ -6657,38 +6670,52 @@ snapshots: is-potential-custom-element-name@1.0.1: {} - is-regex@1.1.4: + is-regex@1.2.1: dependencies: - call-bind: 1.0.7 + call-bound: 1.0.4 + gopd: 1.2.0 has-tostringtag: 1.0.2 + hasown: 2.0.2 is-regexp@1.0.0: {} - is-shared-array-buffer@1.0.3: + is-set@2.0.3: {} + + is-shared-array-buffer@1.0.4: dependencies: - call-bind: 1.0.7 + call-bound: 1.0.4 is-stream@2.0.1: {} - is-string@1.0.7: + is-string@1.1.1: dependencies: + call-bound: 1.0.4 has-tostringtag: 1.0.2 - is-symbol@1.0.4: + is-symbol@1.1.1: dependencies: - has-symbols: 1.0.3 + call-bound: 1.0.4 + has-symbols: 1.1.0 + safe-regex-test: 1.1.0 - is-typed-array@1.1.13: + is-typed-array@1.1.15: dependencies: - which-typed-array: 1.1.15 + which-typed-array: 1.1.19 is-unicode-supported@1.3.0: {} is-unicode-supported@2.1.0: {} - is-weakref@1.0.2: + is-weakmap@2.0.2: {} + + is-weakref@1.1.1: dependencies: - call-bind: 1.0.7 + call-bound: 1.0.4 + + is-weakset@2.0.4: + dependencies: + call-bound: 1.0.4 + get-intrinsic: 1.3.0 is-wsl@3.1.0: dependencies: @@ -6696,20 +6723,20 @@ snapshots: isarray@2.0.5: {} - jake@10.9.1: + jake@10.9.2: dependencies: - async: 3.2.5 + async: 3.2.6 chalk: 4.1.2 filelist: 1.0.4 minimatch: 3.1.2 jest-worker@26.6.2: dependencies: - '@types/node': 22.13.10 + '@types/node': 22.13.13 merge-stream: 2.0.0 supports-color: 7.2.0 - jiti@1.21.6: {} + jiti@1.21.7: {} js-tokens@4.0.0: {} @@ -6724,36 +6751,36 @@ snapshots: jsdom@26.0.0: dependencies: - cssstyle: 4.2.1 + cssstyle: 4.3.0 data-urls: 5.0.0 - decimal.js: 10.4.3 - form-data: 4.0.1 + decimal.js: 10.5.0 + form-data: 4.0.2 html-encoding-sniffer: 4.0.0 http-proxy-agent: 7.0.2 https-proxy-agent: 7.0.6 is-potential-custom-element-name: 1.0.1 - nwsapi: 2.2.16 + nwsapi: 2.2.19 parse5: 7.2.1 rrweb-cssom: 0.8.0 saxes: 6.0.0 symbol-tree: 3.2.4 - tough-cookie: 5.0.0 + tough-cookie: 5.1.2 w3c-xmlserializer: 5.0.0 webidl-conversions: 7.0.0 whatwg-encoding: 3.1.1 whatwg-mimetype: 4.0.0 - whatwg-url: 14.1.0 - ws: 8.18.0 + whatwg-url: 14.2.0 + ws: 8.18.1 xml-name-validator: 5.0.0 transitivePeerDependencies: - bufferutil - supports-color - utf-8-validate - jsesc@0.5.0: {} - jsesc@3.0.2: {} + jsesc@3.1.0: {} + json-schema-traverse@1.0.0: {} json-schema@0.4.0: {} @@ -6799,12 +6826,12 @@ snapshots: log-symbols@6.0.0: dependencies: - chalk: 5.3.0 + chalk: 5.4.1 is-unicode-supported: 1.3.0 longest-streak@3.1.0: {} - lru-cache@11.0.2: {} + lru-cache@10.4.3: {} lru-cache@5.1.1: dependencies: @@ -6816,14 +6843,14 @@ snapshots: dependencies: sourcemap-codec: 1.4.8 - magic-string@0.30.14: + magic-string@0.30.17: dependencies: '@jridgewell/sourcemap-codec': 1.5.0 magicast@0.3.5: dependencies: - '@babel/parser': 7.26.3 - '@babel/types': 7.26.3 + '@babel/parser': 7.27.0 + '@babel/types': 7.27.0 source-map-js: 1.2.1 markdown-extensions@2.0.0: {} @@ -6837,7 +6864,7 @@ snapshots: punycode.js: 2.3.1 uc.micro: 2.1.0 - markdown-table@3.0.3: {} + markdown-table@3.0.4: {} marked-footnote@1.2.4(marked@12.0.2): dependencies: @@ -6847,52 +6874,55 @@ snapshots: dependencies: marked: 12.0.2 - marked-smartypants@1.1.8(marked@12.0.2): + marked-smartypants@1.1.9(marked@12.0.2): dependencies: marked: 12.0.2 smartypants: 0.2.2 marked@12.0.2: {} + math-intrinsics@1.1.0: {} + mdast-util-definitions@6.0.0: dependencies: '@types/mdast': 4.0.4 '@types/unist': 3.0.3 unist-util-visit: 5.0.0 - mdast-util-directive@3.0.0: + mdast-util-directive@3.1.0: dependencies: '@types/mdast': 4.0.4 '@types/unist': 3.0.3 + ccount: 2.0.1 devlop: 1.1.0 - mdast-util-from-markdown: 2.0.1 - mdast-util-to-markdown: 2.1.0 - parse-entities: 4.0.1 + mdast-util-from-markdown: 2.0.2 + mdast-util-to-markdown: 2.1.2 + parse-entities: 4.0.2 stringify-entities: 4.0.4 unist-util-visit-parents: 6.0.1 transitivePeerDependencies: - supports-color - mdast-util-find-and-replace@3.0.1: + mdast-util-find-and-replace@3.0.2: dependencies: '@types/mdast': 4.0.4 escape-string-regexp: 5.0.0 unist-util-is: 6.0.0 unist-util-visit-parents: 6.0.1 - mdast-util-from-markdown@2.0.1: + mdast-util-from-markdown@2.0.2: dependencies: '@types/mdast': 4.0.4 '@types/unist': 3.0.3 - decode-named-character-reference: 1.0.2 + decode-named-character-reference: 1.1.0 devlop: 1.1.0 mdast-util-to-string: 4.0.0 - micromark: 4.0.0 - micromark-util-decode-numeric-character-reference: 2.0.1 - micromark-util-decode-string: 2.0.0 - micromark-util-normalize-identifier: 2.0.0 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 + micromark: 4.0.2 + micromark-util-decode-numeric-character-reference: 2.0.2 + micromark-util-decode-string: 2.0.1 + micromark-util-normalize-identifier: 2.0.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 unist-util-stringify-position: 4.0.0 transitivePeerDependencies: - supports-color @@ -6902,24 +6932,24 @@ snapshots: '@types/mdast': 4.0.4 ccount: 2.0.1 devlop: 1.1.0 - mdast-util-find-and-replace: 3.0.1 - micromark-util-character: 2.1.0 + mdast-util-find-and-replace: 3.0.2 + micromark-util-character: 2.1.1 - mdast-util-gfm-footnote@2.0.0: + mdast-util-gfm-footnote@2.1.0: dependencies: '@types/mdast': 4.0.4 devlop: 1.1.0 - mdast-util-from-markdown: 2.0.1 - mdast-util-to-markdown: 2.1.0 - micromark-util-normalize-identifier: 2.0.0 + mdast-util-from-markdown: 2.0.2 + mdast-util-to-markdown: 2.1.2 + micromark-util-normalize-identifier: 2.0.1 transitivePeerDependencies: - supports-color mdast-util-gfm-strikethrough@2.0.0: dependencies: '@types/mdast': 4.0.4 - mdast-util-from-markdown: 2.0.1 - mdast-util-to-markdown: 2.1.0 + mdast-util-from-markdown: 2.0.2 + mdast-util-to-markdown: 2.1.2 transitivePeerDependencies: - supports-color @@ -6927,9 +6957,9 @@ snapshots: dependencies: '@types/mdast': 4.0.4 devlop: 1.1.0 - markdown-table: 3.0.3 - mdast-util-from-markdown: 2.0.1 - mdast-util-to-markdown: 2.1.0 + markdown-table: 3.0.4 + mdast-util-from-markdown: 2.0.2 + mdast-util-to-markdown: 2.1.2 transitivePeerDependencies: - supports-color @@ -6937,20 +6967,20 @@ snapshots: dependencies: '@types/mdast': 4.0.4 devlop: 1.1.0 - mdast-util-from-markdown: 2.0.1 - mdast-util-to-markdown: 2.1.0 + mdast-util-from-markdown: 2.0.2 + mdast-util-to-markdown: 2.1.2 transitivePeerDependencies: - supports-color - mdast-util-gfm@3.0.0: + mdast-util-gfm@3.1.0: dependencies: - mdast-util-from-markdown: 2.0.1 + mdast-util-from-markdown: 2.0.2 mdast-util-gfm-autolink-literal: 2.0.1 - mdast-util-gfm-footnote: 2.0.0 + mdast-util-gfm-footnote: 2.1.0 mdast-util-gfm-strikethrough: 2.0.0 mdast-util-gfm-table: 2.0.0 mdast-util-gfm-task-list-item: 2.0.0 - mdast-util-to-markdown: 2.1.0 + mdast-util-to-markdown: 2.1.2 transitivePeerDependencies: - supports-color @@ -6960,12 +6990,12 @@ snapshots: '@types/hast': 3.0.4 '@types/mdast': 4.0.4 devlop: 1.1.0 - mdast-util-from-markdown: 2.0.1 - mdast-util-to-markdown: 2.1.0 + mdast-util-from-markdown: 2.0.2 + mdast-util-to-markdown: 2.1.2 transitivePeerDependencies: - supports-color - mdast-util-mdx-jsx@3.1.3: + mdast-util-mdx-jsx@3.2.0: dependencies: '@types/estree-jsx': 1.0.5 '@types/hast': 3.0.4 @@ -6973,9 +7003,9 @@ snapshots: '@types/unist': 3.0.3 ccount: 2.0.1 devlop: 1.1.0 - mdast-util-from-markdown: 2.0.1 - mdast-util-to-markdown: 2.1.0 - parse-entities: 4.0.1 + mdast-util-from-markdown: 2.0.2 + mdast-util-to-markdown: 2.1.2 + parse-entities: 4.0.2 stringify-entities: 4.0.4 unist-util-stringify-position: 4.0.0 vfile-message: 4.0.2 @@ -6984,11 +7014,11 @@ snapshots: mdast-util-mdx@3.0.0: dependencies: - mdast-util-from-markdown: 2.0.1 + mdast-util-from-markdown: 2.0.2 mdast-util-mdx-expression: 2.0.1 - mdast-util-mdx-jsx: 3.1.3 + mdast-util-mdx-jsx: 3.2.0 mdast-util-mdxjs-esm: 2.0.1 - mdast-util-to-markdown: 2.1.0 + mdast-util-to-markdown: 2.1.2 transitivePeerDependencies: - supports-color @@ -6998,8 +7028,8 @@ snapshots: '@types/hast': 3.0.4 '@types/mdast': 4.0.4 devlop: 1.1.0 - mdast-util-from-markdown: 2.0.1 - mdast-util-to-markdown: 2.1.0 + mdast-util-from-markdown: 2.0.2 + mdast-util-to-markdown: 2.1.2 transitivePeerDependencies: - supports-color @@ -7012,22 +7042,23 @@ snapshots: dependencies: '@types/hast': 3.0.4 '@types/mdast': 4.0.4 - '@ungap/structured-clone': 1.2.0 + '@ungap/structured-clone': 1.3.0 devlop: 1.1.0 - micromark-util-sanitize-uri: 2.0.0 + micromark-util-sanitize-uri: 2.0.1 trim-lines: 3.0.1 unist-util-position: 5.0.0 unist-util-visit: 5.0.0 vfile: 6.0.3 - mdast-util-to-markdown@2.1.0: + mdast-util-to-markdown@2.1.2: dependencies: '@types/mdast': 4.0.4 '@types/unist': 3.0.3 longest-streak: 3.1.0 mdast-util-phrasing: 4.1.0 mdast-util-to-string: 4.0.0 - micromark-util-decode-string: 2.0.0 + micromark-util-classify-character: 2.0.1 + micromark-util-decode-string: 2.0.1 unist-util-visit: 5.0.0 zwitch: 2.0.4 @@ -7041,279 +7072,277 @@ snapshots: merge2@1.4.1: {} - micromark-core-commonmark@2.0.1: + micromark-core-commonmark@2.0.3: dependencies: - decode-named-character-reference: 1.0.2 + decode-named-character-reference: 1.1.0 devlop: 1.1.0 - micromark-factory-destination: 2.0.0 - micromark-factory-label: 2.0.0 - micromark-factory-space: 2.0.0 - micromark-factory-title: 2.0.0 - micromark-factory-whitespace: 2.0.0 - micromark-util-character: 2.1.0 - micromark-util-chunked: 2.0.0 - micromark-util-classify-character: 2.0.0 - micromark-util-html-tag-name: 2.0.0 - micromark-util-normalize-identifier: 2.0.0 - micromark-util-resolve-all: 2.0.0 - micromark-util-subtokenize: 2.0.1 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 + micromark-factory-destination: 2.0.1 + micromark-factory-label: 2.0.1 + micromark-factory-space: 2.0.1 + micromark-factory-title: 2.0.1 + micromark-factory-whitespace: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-chunked: 2.0.1 + micromark-util-classify-character: 2.0.1 + micromark-util-html-tag-name: 2.0.1 + micromark-util-normalize-identifier: 2.0.1 + micromark-util-resolve-all: 2.0.1 + micromark-util-subtokenize: 2.1.0 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 micromark-extension-directive@3.0.2: dependencies: devlop: 1.1.0 - micromark-factory-space: 2.0.0 - micromark-factory-whitespace: 2.0.0 - micromark-util-character: 2.1.0 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 - parse-entities: 4.0.1 + micromark-factory-space: 2.0.1 + micromark-factory-whitespace: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + parse-entities: 4.0.2 micromark-extension-gfm-autolink-literal@2.1.0: dependencies: - micromark-util-character: 2.1.0 - micromark-util-sanitize-uri: 2.0.0 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 + micromark-util-character: 2.1.1 + micromark-util-sanitize-uri: 2.0.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 micromark-extension-gfm-footnote@2.1.0: dependencies: devlop: 1.1.0 - micromark-core-commonmark: 2.0.1 - micromark-factory-space: 2.0.0 - micromark-util-character: 2.1.0 - micromark-util-normalize-identifier: 2.0.0 - micromark-util-sanitize-uri: 2.0.0 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 + micromark-core-commonmark: 2.0.3 + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-normalize-identifier: 2.0.1 + micromark-util-sanitize-uri: 2.0.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 micromark-extension-gfm-strikethrough@2.1.0: dependencies: devlop: 1.1.0 - micromark-util-chunked: 2.0.0 - micromark-util-classify-character: 2.0.0 - micromark-util-resolve-all: 2.0.0 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 + micromark-util-chunked: 2.0.1 + micromark-util-classify-character: 2.0.1 + micromark-util-resolve-all: 2.0.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 - micromark-extension-gfm-table@2.1.0: + micromark-extension-gfm-table@2.1.1: dependencies: devlop: 1.1.0 - micromark-factory-space: 2.0.0 - micromark-util-character: 2.1.0 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 micromark-extension-gfm-tagfilter@2.0.0: dependencies: - micromark-util-types: 2.0.0 + micromark-util-types: 2.0.2 micromark-extension-gfm-task-list-item@2.1.0: dependencies: devlop: 1.1.0 - micromark-factory-space: 2.0.0 - micromark-util-character: 2.1.0 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 micromark-extension-gfm@3.0.0: dependencies: micromark-extension-gfm-autolink-literal: 2.1.0 micromark-extension-gfm-footnote: 2.1.0 micromark-extension-gfm-strikethrough: 2.1.0 - micromark-extension-gfm-table: 2.1.0 + micromark-extension-gfm-table: 2.1.1 micromark-extension-gfm-tagfilter: 2.0.0 micromark-extension-gfm-task-list-item: 2.1.0 - micromark-util-combine-extensions: 2.0.0 - micromark-util-types: 2.0.0 + micromark-util-combine-extensions: 2.0.1 + micromark-util-types: 2.0.2 - micromark-extension-mdx-expression@3.0.0: + micromark-extension-mdx-expression@3.0.1: dependencies: - '@types/estree': 1.0.6 + '@types/estree': 1.0.7 devlop: 1.1.0 - micromark-factory-mdx-expression: 2.0.2 - micromark-factory-space: 2.0.0 - micromark-util-character: 2.1.0 - micromark-util-events-to-acorn: 2.0.2 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 + micromark-factory-mdx-expression: 2.0.3 + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-events-to-acorn: 2.0.3 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 - micromark-extension-mdx-jsx@3.0.1: + micromark-extension-mdx-jsx@3.0.2: dependencies: - '@types/acorn': 4.0.6 - '@types/estree': 1.0.6 + '@types/estree': 1.0.7 devlop: 1.1.0 estree-util-is-identifier-name: 3.0.0 - micromark-factory-mdx-expression: 2.0.2 - micromark-factory-space: 2.0.0 - micromark-util-character: 2.1.0 - micromark-util-events-to-acorn: 2.0.2 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 + micromark-factory-mdx-expression: 2.0.3 + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-events-to-acorn: 2.0.3 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 vfile-message: 4.0.2 micromark-extension-mdx-md@2.0.0: dependencies: - micromark-util-types: 2.0.0 + micromark-util-types: 2.0.2 micromark-extension-mdxjs-esm@3.0.0: dependencies: - '@types/estree': 1.0.6 + '@types/estree': 1.0.7 devlop: 1.1.0 - micromark-core-commonmark: 2.0.1 - micromark-util-character: 2.1.0 - micromark-util-events-to-acorn: 2.0.2 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 + micromark-core-commonmark: 2.0.3 + micromark-util-character: 2.1.1 + micromark-util-events-to-acorn: 2.0.3 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 unist-util-position-from-estree: 2.0.0 vfile-message: 4.0.2 micromark-extension-mdxjs@3.0.0: dependencies: - acorn: 8.14.0 - acorn-jsx: 5.3.2(acorn@8.14.0) - micromark-extension-mdx-expression: 3.0.0 - micromark-extension-mdx-jsx: 3.0.1 + acorn: 8.14.1 + acorn-jsx: 5.3.2(acorn@8.14.1) + micromark-extension-mdx-expression: 3.0.1 + micromark-extension-mdx-jsx: 3.0.2 micromark-extension-mdx-md: 2.0.0 micromark-extension-mdxjs-esm: 3.0.0 - micromark-util-combine-extensions: 2.0.0 - micromark-util-types: 2.0.0 + micromark-util-combine-extensions: 2.0.1 + micromark-util-types: 2.0.2 - micromark-factory-destination@2.0.0: + micromark-factory-destination@2.0.1: dependencies: - micromark-util-character: 2.1.0 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 - micromark-factory-label@2.0.0: + micromark-factory-label@2.0.1: dependencies: devlop: 1.1.0 - micromark-util-character: 2.1.0 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 - micromark-factory-mdx-expression@2.0.2: + micromark-factory-mdx-expression@2.0.3: dependencies: - '@types/estree': 1.0.6 + '@types/estree': 1.0.7 devlop: 1.1.0 - micromark-factory-space: 2.0.0 - micromark-util-character: 2.1.0 - micromark-util-events-to-acorn: 2.0.2 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-events-to-acorn: 2.0.3 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 unist-util-position-from-estree: 2.0.0 vfile-message: 4.0.2 - micromark-factory-space@2.0.0: + micromark-factory-space@2.0.1: dependencies: - micromark-util-character: 2.1.0 - micromark-util-types: 2.0.0 + micromark-util-character: 2.1.1 + micromark-util-types: 2.0.2 - micromark-factory-title@2.0.0: + micromark-factory-title@2.0.1: dependencies: - micromark-factory-space: 2.0.0 - micromark-util-character: 2.1.0 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 - micromark-factory-whitespace@2.0.0: + micromark-factory-whitespace@2.0.1: dependencies: - micromark-factory-space: 2.0.0 - micromark-util-character: 2.1.0 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 - micromark-util-character@2.1.0: + micromark-util-character@2.1.1: dependencies: - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 - micromark-util-chunked@2.0.0: + micromark-util-chunked@2.0.1: dependencies: - micromark-util-symbol: 2.0.0 + micromark-util-symbol: 2.0.1 - micromark-util-classify-character@2.0.0: + micromark-util-classify-character@2.0.1: dependencies: - micromark-util-character: 2.1.0 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 - micromark-util-combine-extensions@2.0.0: + micromark-util-combine-extensions@2.0.1: dependencies: - micromark-util-chunked: 2.0.0 - micromark-util-types: 2.0.0 + micromark-util-chunked: 2.0.1 + micromark-util-types: 2.0.2 - micromark-util-decode-numeric-character-reference@2.0.1: + micromark-util-decode-numeric-character-reference@2.0.2: dependencies: - micromark-util-symbol: 2.0.0 + micromark-util-symbol: 2.0.1 - micromark-util-decode-string@2.0.0: + micromark-util-decode-string@2.0.1: dependencies: - decode-named-character-reference: 1.0.2 - micromark-util-character: 2.1.0 - micromark-util-decode-numeric-character-reference: 2.0.1 - micromark-util-symbol: 2.0.0 + decode-named-character-reference: 1.1.0 + micromark-util-character: 2.1.1 + micromark-util-decode-numeric-character-reference: 2.0.2 + micromark-util-symbol: 2.0.1 - micromark-util-encode@2.0.0: {} + micromark-util-encode@2.0.1: {} - micromark-util-events-to-acorn@2.0.2: + micromark-util-events-to-acorn@2.0.3: dependencies: - '@types/acorn': 4.0.6 - '@types/estree': 1.0.6 + '@types/estree': 1.0.7 '@types/unist': 3.0.3 devlop: 1.1.0 estree-util-visit: 2.0.0 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 vfile-message: 4.0.2 - micromark-util-html-tag-name@2.0.0: {} + micromark-util-html-tag-name@2.0.1: {} - micromark-util-normalize-identifier@2.0.0: + micromark-util-normalize-identifier@2.0.1: dependencies: - micromark-util-symbol: 2.0.0 + micromark-util-symbol: 2.0.1 - micromark-util-resolve-all@2.0.0: + micromark-util-resolve-all@2.0.1: dependencies: - micromark-util-types: 2.0.0 + micromark-util-types: 2.0.2 - micromark-util-sanitize-uri@2.0.0: + micromark-util-sanitize-uri@2.0.1: dependencies: - micromark-util-character: 2.1.0 - micromark-util-encode: 2.0.0 - micromark-util-symbol: 2.0.0 + micromark-util-character: 2.1.1 + micromark-util-encode: 2.0.1 + micromark-util-symbol: 2.0.1 - micromark-util-subtokenize@2.0.1: + micromark-util-subtokenize@2.1.0: dependencies: devlop: 1.1.0 - micromark-util-chunked: 2.0.0 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 + micromark-util-chunked: 2.0.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 - micromark-util-symbol@2.0.0: {} + micromark-util-symbol@2.0.1: {} - micromark-util-types@2.0.0: {} + micromark-util-types@2.0.2: {} - micromark@4.0.0: + micromark@4.0.2: dependencies: '@types/debug': 4.1.12 - debug: 4.3.7 - decode-named-character-reference: 1.0.2 + debug: 4.4.0 + decode-named-character-reference: 1.1.0 devlop: 1.1.0 - micromark-core-commonmark: 2.0.1 - micromark-factory-space: 2.0.0 - micromark-util-character: 2.1.0 - micromark-util-chunked: 2.0.0 - micromark-util-combine-extensions: 2.0.0 - micromark-util-decode-numeric-character-reference: 2.0.1 - micromark-util-encode: 2.0.0 - micromark-util-normalize-identifier: 2.0.0 - micromark-util-resolve-all: 2.0.0 - micromark-util-sanitize-uri: 2.0.0 - micromark-util-subtokenize: 2.0.1 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 + micromark-core-commonmark: 2.0.3 + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-chunked: 2.0.1 + micromark-util-combine-extensions: 2.0.1 + micromark-util-decode-numeric-character-reference: 2.0.2 + micromark-util-encode: 2.0.1 + micromark-util-normalize-identifier: 2.0.1 + micromark-util-resolve-all: 2.0.1 + micromark-util-sanitize-uri: 2.0.1 + micromark-util-subtokenize: 2.1.0 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 transitivePeerDependencies: - supports-color @@ -7342,11 +7371,11 @@ snapshots: dependencies: brace-expansion: 2.0.1 - mrmime@2.0.0: {} + mrmime@2.0.1: {} ms@2.1.3: {} - nanoid@3.3.8: {} + nanoid@3.3.11: {} neotraverse@0.6.18: {} @@ -7357,25 +7386,25 @@ snapshots: node-addon-api@7.1.1: optional: true - node-releases@2.0.18: {} - - not@0.1.0: {} + node-releases@2.0.19: {} nth-check@2.1.1: dependencies: boolbase: 1.0.0 - nwsapi@2.2.16: {} + nwsapi@2.2.19: {} - object-inspect@1.13.1: {} + object-inspect@1.13.4: {} object-keys@1.1.1: {} - object.assign@4.1.5: + object.assign@4.1.7: dependencies: - call-bind: 1.0.7 + call-bind: 1.0.8 + call-bound: 1.0.4 define-properties: 1.2.1 - has-symbols: 1.0.3 + es-object-atoms: 1.1.1 + has-symbols: 1.1.0 object-keys: 1.1.1 once@1.4.0: @@ -7386,15 +7415,15 @@ snapshots: dependencies: mimic-function: 5.0.1 - oniguruma-to-es@0.10.0: + oniguruma-to-es@2.3.0: dependencies: emoji-regex-xs: 1.0.0 regex: 5.1.1 regex-recursion: 5.1.1 - ora@8.1.1: + ora@8.2.0: dependencies: - chalk: 5.3.0 + chalk: 5.4.1 cli-cursor: 5.0.0 cli-spinners: 2.9.2 is-interactive: 2.0.0 @@ -7404,42 +7433,47 @@ snapshots: string-width: 7.2.0 strip-ansi: 7.1.0 + own-keys@1.0.1: + dependencies: + get-intrinsic: 1.3.0 + object-keys: 1.1.1 + safe-push-apply: 1.0.0 + p-limit@2.3.0: dependencies: p-try: 2.2.0 - p-limit@6.1.0: + p-limit@6.2.0: dependencies: - yocto-queue: 1.1.1 + yocto-queue: 1.2.1 p-locate@4.1.0: dependencies: p-limit: 2.3.0 - p-queue@8.0.1: + p-queue@8.1.0: dependencies: eventemitter3: 5.0.1 - p-timeout: 6.1.3 + p-timeout: 6.1.4 - p-timeout@6.1.3: {} + p-timeout@6.1.4: {} p-try@2.2.0: {} - pagefind@1.1.1: + pagefind@1.3.0: optionalDependencies: - '@pagefind/darwin-arm64': 1.1.1 - '@pagefind/darwin-x64': 1.1.1 - '@pagefind/linux-arm64': 1.1.1 - '@pagefind/linux-x64': 1.1.1 - '@pagefind/windows-x64': 1.1.1 + '@pagefind/darwin-arm64': 1.3.0 + '@pagefind/darwin-x64': 1.3.0 + '@pagefind/linux-arm64': 1.3.0 + '@pagefind/linux-x64': 1.3.0 + '@pagefind/windows-x64': 1.3.0 - parse-entities@4.0.1: + parse-entities@4.0.2: dependencies: '@types/unist': 2.0.11 - character-entities: 2.0.2 character-entities-legacy: 3.0.0 character-reference-invalid: 2.0.1 - decode-named-character-reference: 1.0.2 + decode-named-character-reference: 1.1.0 is-alphanumerical: 2.0.1 is-decimal: 2.0.1 is-hexadecimal: 2.0.1 @@ -7479,11 +7513,11 @@ snapshots: dependencies: find-up: 4.1.0 - possible-typed-array-names@1.0.0: {} + possible-typed-array-names@1.1.0: {} - postcss-nested@6.2.0(postcss@8.4.49): + postcss-nested@6.2.0(postcss@8.5.3): dependencies: - postcss: 8.4.49 + postcss: 8.5.3 postcss-selector-parser: 6.1.2 postcss-selector-parser@6.1.2: @@ -7491,29 +7525,29 @@ snapshots: cssesc: 3.0.0 util-deprecate: 1.0.2 - postcss@8.4.49: + postcss@8.5.3: dependencies: - nanoid: 3.3.8 + nanoid: 3.3.11 picocolors: 1.1.1 source-map-js: 1.2.1 - preferred-pm@4.0.0: + preferred-pm@4.1.1: dependencies: - find-up-simple: 1.0.0 + find-up-simple: 1.0.1 find-yarn-workspace-root2: 1.2.16 - which-pm: 3.0.0 + which-pm: 3.0.1 prettier-plugin-astro@0.14.1: dependencies: - '@astrojs/compiler': 2.10.3 - prettier: 3.4.2 + '@astrojs/compiler': 2.11.0 + prettier: 3.5.3 sass-formatter: 0.7.9 - prettier@3.4.2: {} + prettier@3.5.3: {} pretty-bytes@5.6.0: {} - prismjs@1.29.0: {} + prismjs@1.30.0: {} prompts@2.4.2: dependencies: @@ -7522,6 +7556,8 @@ snapshots: property-information@6.5.0: {} + property-information@7.0.0: {} + punycode.js@2.3.1: {} punycode@2.3.1: {} @@ -7532,25 +7568,25 @@ snapshots: dependencies: safe-buffer: 5.2.1 - readdirp@4.1.1: {} + readdirp@4.1.2: {} - recast@0.23.9: + recast@0.23.11: dependencies: ast-types: 0.16.1 esprima: 4.0.1 source-map: 0.6.1 tiny-invariant: 1.3.3 - tslib: 2.6.3 + tslib: 2.8.1 recma-build-jsx@1.0.0: dependencies: - '@types/estree': 1.0.6 + '@types/estree': 1.0.7 estree-util-build-jsx: 3.0.1 vfile: 6.0.3 - recma-jsx@1.0.0(acorn@8.14.0): + recma-jsx@1.0.0(acorn@8.14.1): dependencies: - acorn-jsx: 5.3.2(acorn@8.14.0) + acorn-jsx: 5.3.2(acorn@8.14.1) estree-util-to-js: 2.0.0 recma-parse: 1.0.0 recma-stringify: 1.0.0 @@ -7560,19 +7596,30 @@ snapshots: recma-parse@1.0.0: dependencies: - '@types/estree': 1.0.6 + '@types/estree': 1.0.7 esast-util-from-js: 2.0.1 unified: 11.0.5 vfile: 6.0.3 recma-stringify@1.0.0: dependencies: - '@types/estree': 1.0.6 + '@types/estree': 1.0.7 estree-util-to-js: 2.0.0 unified: 11.0.5 vfile: 6.0.3 - regenerate-unicode-properties@10.1.1: + reflect.getprototypeof@1.0.10: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.23.9 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + get-intrinsic: 1.3.0 + get-proto: 1.0.1 + which-builtin-type: 1.2.1 + + regenerate-unicode-properties@10.2.0: dependencies: regenerate: 1.4.2 @@ -7582,7 +7629,7 @@ snapshots: regenerator-transform@0.15.2: dependencies: - '@babel/runtime': 7.25.6 + '@babel/runtime': 7.27.0 regex-recursion@5.1.1: dependencies: @@ -7595,30 +7642,34 @@ snapshots: dependencies: regex-utilities: 2.3.0 - regexp.prototype.flags@1.5.2: + regexp.prototype.flags@1.5.4: dependencies: - call-bind: 1.0.7 + call-bind: 1.0.8 define-properties: 1.2.1 es-errors: 1.3.0 + get-proto: 1.0.1 + gopd: 1.2.0 set-function-name: 2.0.2 - regexpu-core@5.3.2: + regexpu-core@6.2.0: dependencies: - '@babel/regjsgen': 0.8.0 regenerate: 1.4.2 - regenerate-unicode-properties: 10.1.1 - regjsparser: 0.9.1 + regenerate-unicode-properties: 10.2.0 + regjsgen: 0.8.0 + regjsparser: 0.12.0 unicode-match-property-ecmascript: 2.0.0 - unicode-match-property-value-ecmascript: 2.1.0 + unicode-match-property-value-ecmascript: 2.2.0 + + regjsgen@0.8.0: {} - regjsparser@0.9.1: + regjsparser@0.12.0: dependencies: - jsesc: 0.5.0 + jsesc: 3.0.2 rehype-autolink-headings@7.1.0: dependencies: '@types/hast': 3.0.4 - '@ungap/structured-clone': 1.2.0 + '@ungap/structured-clone': 1.3.0 hast-util-heading-rank: 3.0.0 hast-util-is-element: 3.0.0 unified: 11.0.5 @@ -7642,21 +7693,21 @@ snapshots: rehype-raw@7.0.0: dependencies: '@types/hast': 3.0.4 - hast-util-raw: 9.0.4 + hast-util-raw: 9.1.0 vfile: 6.0.3 rehype-recma@1.0.0: dependencies: - '@types/estree': 1.0.6 + '@types/estree': 1.0.7 '@types/hast': 3.0.4 - hast-util-to-estree: 3.1.0 + hast-util-to-estree: 3.1.3 transitivePeerDependencies: - supports-color rehype-stringify@10.0.1: dependencies: '@types/hast': 3.0.4 - hast-util-to-html: 9.0.4 + hast-util-to-html: 9.0.5 unified: 11.0.5 rehype@13.0.2: @@ -7666,19 +7717,19 @@ snapshots: rehype-stringify: 10.0.1 unified: 11.0.5 - remark-directive@3.0.0: + remark-directive@3.0.1: dependencies: '@types/mdast': 4.0.4 - mdast-util-directive: 3.0.0 + mdast-util-directive: 3.1.0 micromark-extension-directive: 3.0.2 unified: 11.0.5 transitivePeerDependencies: - supports-color - remark-gfm@4.0.0: + remark-gfm@4.0.1: dependencies: '@types/mdast': 4.0.4 - mdast-util-gfm: 3.0.0 + mdast-util-gfm: 3.1.0 micromark-extension-gfm: 3.0.0 remark-parse: 11.0.0 remark-stringify: 11.0.0 @@ -7686,7 +7737,7 @@ snapshots: transitivePeerDependencies: - supports-color - remark-mdx@3.0.1: + remark-mdx@3.1.0: dependencies: mdast-util-mdx: 3.0.0 micromark-extension-mdxjs: 3.0.0 @@ -7696,8 +7747,8 @@ snapshots: remark-parse@11.0.0: dependencies: '@types/mdast': 4.0.4 - mdast-util-from-markdown: 2.0.1 - micromark-util-types: 2.0.0 + mdast-util-from-markdown: 2.0.2 + micromark-util-types: 2.0.2 unified: 11.0.5 transitivePeerDependencies: - supports-color @@ -7720,14 +7771,14 @@ snapshots: remark-stringify@11.0.0: dependencies: '@types/mdast': 4.0.4 - mdast-util-to-markdown: 2.1.0 + mdast-util-to-markdown: 2.1.2 unified: 11.0.5 require-from-string@2.0.2: {} - resolve@1.22.8: + resolve@1.22.10: dependencies: - is-core-module: 2.14.0 + is-core-module: 2.16.1 path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 @@ -7761,42 +7812,44 @@ snapshots: retext-stringify: 4.0.0 unified: 11.0.5 - reusify@1.0.4: {} + reusify@1.1.0: {} - rollup-plugin-terser@7.0.2(rollup@2.79.1): + rollup-plugin-terser@7.0.2(rollup@2.79.2): dependencies: '@babel/code-frame': 7.26.2 jest-worker: 26.6.2 - rollup: 2.79.1 + rollup: 2.79.2 serialize-javascript: 4.0.0 - terser: 5.31.0 + terser: 5.39.0 - rollup@2.79.1: + rollup@2.79.2: optionalDependencies: fsevents: 2.3.3 - rollup@4.28.0: + rollup@4.37.0: dependencies: '@types/estree': 1.0.6 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.28.0 - '@rollup/rollup-android-arm64': 4.28.0 - '@rollup/rollup-darwin-arm64': 4.28.0 - '@rollup/rollup-darwin-x64': 4.28.0 - '@rollup/rollup-freebsd-arm64': 4.28.0 - '@rollup/rollup-freebsd-x64': 4.28.0 - '@rollup/rollup-linux-arm-gnueabihf': 4.28.0 - '@rollup/rollup-linux-arm-musleabihf': 4.28.0 - '@rollup/rollup-linux-arm64-gnu': 4.28.0 - '@rollup/rollup-linux-arm64-musl': 4.28.0 - '@rollup/rollup-linux-powerpc64le-gnu': 4.28.0 - '@rollup/rollup-linux-riscv64-gnu': 4.28.0 - '@rollup/rollup-linux-s390x-gnu': 4.28.0 - '@rollup/rollup-linux-x64-gnu': 4.28.0 - '@rollup/rollup-linux-x64-musl': 4.28.0 - '@rollup/rollup-win32-arm64-msvc': 4.28.0 - '@rollup/rollup-win32-ia32-msvc': 4.28.0 - '@rollup/rollup-win32-x64-msvc': 4.28.0 + '@rollup/rollup-android-arm-eabi': 4.37.0 + '@rollup/rollup-android-arm64': 4.37.0 + '@rollup/rollup-darwin-arm64': 4.37.0 + '@rollup/rollup-darwin-x64': 4.37.0 + '@rollup/rollup-freebsd-arm64': 4.37.0 + '@rollup/rollup-freebsd-x64': 4.37.0 + '@rollup/rollup-linux-arm-gnueabihf': 4.37.0 + '@rollup/rollup-linux-arm-musleabihf': 4.37.0 + '@rollup/rollup-linux-arm64-gnu': 4.37.0 + '@rollup/rollup-linux-arm64-musl': 4.37.0 + '@rollup/rollup-linux-loongarch64-gnu': 4.37.0 + '@rollup/rollup-linux-powerpc64le-gnu': 4.37.0 + '@rollup/rollup-linux-riscv64-gnu': 4.37.0 + '@rollup/rollup-linux-riscv64-musl': 4.37.0 + '@rollup/rollup-linux-s390x-gnu': 4.37.0 + '@rollup/rollup-linux-x64-gnu': 4.37.0 + '@rollup/rollup-linux-x64-musl': 4.37.0 + '@rollup/rollup-win32-arm64-msvc': 4.37.0 + '@rollup/rollup-win32-ia32-msvc': 4.37.0 + '@rollup/rollup-win32-x64-msvc': 4.37.0 fsevents: 2.3.3 rrweb-cssom@0.8.0: {} @@ -7807,20 +7860,26 @@ snapshots: s.color@0.0.15: {} - safe-array-concat@1.1.2: + safe-array-concat@1.1.3: dependencies: - call-bind: 1.0.7 - get-intrinsic: 1.2.4 - has-symbols: 1.0.3 + call-bind: 1.0.8 + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + has-symbols: 1.1.0 isarray: 2.0.5 safe-buffer@5.2.1: {} - safe-regex-test@1.0.3: + safe-push-apply@1.0.0: + dependencies: + es-errors: 1.3.0 + isarray: 2.0.5 + + safe-regex-test@1.1.0: dependencies: - call-bind: 1.0.7 + call-bound: 1.0.4 es-errors: 1.3.0 - is-regex: 1.1.4 + is-regex: 1.2.1 safer-buffer@2.1.2: {} @@ -7828,10 +7887,10 @@ snapshots: dependencies: suf-log: 2.5.3 - sass@1.83.4: + sass@1.86.0: dependencies: chokidar: 4.0.3 - immutable: 5.0.3 + immutable: 5.1.1 source-map-js: 1.2.1 optionalDependencies: '@parcel/watcher': 2.5.1 @@ -7851,6 +7910,8 @@ snapshots: semver@7.6.3: {} + semver@7.7.1: {} + serialize-javascript@4.0.0: dependencies: randombytes: 2.1.0 @@ -7860,8 +7921,8 @@ snapshots: define-data-property: 1.1.4 es-errors: 1.3.0 function-bind: 1.1.2 - get-intrinsic: 1.2.4 - gopd: 1.0.1 + get-intrinsic: 1.3.0 + gopd: 1.2.0 has-property-descriptors: 1.0.2 set-function-name@2.0.2: @@ -7871,11 +7932,17 @@ snapshots: functions-have-names: 1.2.3 has-property-descriptors: 1.0.2 + set-proto@1.0.0: + dependencies: + dunder-proto: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + sharp@0.33.5: dependencies: color: 4.2.3 detect-libc: 2.0.3 - semver: 7.6.3 + semver: 7.7.1 optionalDependencies: '@img/sharp-darwin-arm64': 0.33.5 '@img/sharp-darwin-x64': 0.33.5 @@ -7897,23 +7964,44 @@ snapshots: '@img/sharp-win32-ia32': 0.33.5 '@img/sharp-win32-x64': 0.33.5 - shiki@1.26.1: + shiki@1.29.2: dependencies: - '@shikijs/core': 1.26.1 - '@shikijs/engine-javascript': 1.26.1 - '@shikijs/engine-oniguruma': 1.26.1 - '@shikijs/langs': 1.26.1 - '@shikijs/themes': 1.26.1 - '@shikijs/types': 1.26.1 - '@shikijs/vscode-textmate': 10.0.1 + '@shikijs/core': 1.29.2 + '@shikijs/engine-javascript': 1.29.2 + '@shikijs/engine-oniguruma': 1.29.2 + '@shikijs/langs': 1.29.2 + '@shikijs/themes': 1.29.2 + '@shikijs/types': 1.29.2 + '@shikijs/vscode-textmate': 10.0.2 '@types/hast': 3.0.4 - side-channel@1.0.6: + side-channel-list@1.0.0: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + + side-channel-map@1.0.1: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + + side-channel-weakmap@1.0.2: dependencies: - call-bind: 1.0.7 + call-bound: 1.0.4 es-errors: 1.3.0 - get-intrinsic: 1.2.4 - object-inspect: 1.13.1 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + side-channel-map: 1.0.1 + + side-channel@1.1.0: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + side-channel-list: 1.0.0 + side-channel-map: 1.0.1 + side-channel-weakmap: 1.0.2 signal-exit@4.1.0: {} @@ -7921,7 +8009,7 @@ snapshots: dependencies: '@kwsites/file-exists': 1.1.1 '@kwsites/promise-deferred': 1.1.1 - debug: 4.3.7 + debug: 4.4.0 transitivePeerDependencies: - supports-color @@ -7931,7 +8019,7 @@ snapshots: sisteransi@1.0.5: {} - sitemap@7.1.2: + sitemap@8.0.0: dependencies: '@types/node': 17.0.45 '@types/sax': 1.2.7 @@ -7961,11 +8049,11 @@ snapshots: sprintf-js@1.0.3: {} - starlight-blog@0.15.0(@astrojs/starlight@0.29.2(patch_hash=cce5b634885e07791c60f64102f8e7a74def815cdbc19d8aa069b9f4602f2890)(astro@4.16.18(@types/node@22.13.10)(rollup@2.79.1)(sass@1.83.4)(terser@5.31.0)(typescript@5.7.3)))(astro@4.16.18(@types/node@22.13.10)(rollup@2.79.1)(sass@1.83.4)(terser@5.31.0)(typescript@5.7.3)): + starlight-blog@0.15.0(@astrojs/starlight@0.29.2(patch_hash=cce5b634885e07791c60f64102f8e7a74def815cdbc19d8aa069b9f4602f2890)(astro@4.16.18(@types/node@22.13.13)(rollup@2.79.2)(sass@1.86.0)(terser@5.39.0)(typescript@5.7.3)))(astro@4.16.18(@types/node@22.13.13)(rollup@2.79.2)(sass@1.86.0)(terser@5.39.0)(typescript@5.7.3)): dependencies: - '@astrojs/mdx': 3.1.9(astro@4.16.18(@types/node@22.13.10)(rollup@2.79.1)(sass@1.83.4)(terser@5.31.0)(typescript@5.7.3)) + '@astrojs/mdx': 3.1.9(astro@4.16.18(@types/node@22.13.13)(rollup@2.79.2)(sass@1.86.0)(terser@5.39.0)(typescript@5.7.3)) '@astrojs/rss': 4.0.5 - '@astrojs/starlight': 0.29.2(patch_hash=cce5b634885e07791c60f64102f8e7a74def815cdbc19d8aa069b9f4602f2890)(astro@4.16.18(@types/node@22.13.10)(rollup@2.79.1)(sass@1.83.4)(terser@5.31.0)(typescript@5.7.3)) + '@astrojs/starlight': 0.29.2(patch_hash=cce5b634885e07791c60f64102f8e7a74def815cdbc19d8aa069b9f4602f2890)(astro@4.16.18(@types/node@22.13.13)(rollup@2.79.2)(sass@1.86.0)(terser@5.39.0)(typescript@5.7.3)) astro-remote: 0.3.2 github-slugger: 2.0.0 marked: 12.0.2 @@ -7975,11 +8063,11 @@ snapshots: - astro - supports-color - starlight-links-validator@0.13.4(@astrojs/starlight@0.29.2(patch_hash=cce5b634885e07791c60f64102f8e7a74def815cdbc19d8aa069b9f4602f2890)(astro@4.16.18(@types/node@22.13.10)(rollup@2.79.1)(sass@1.83.4)(terser@5.31.0)(typescript@5.7.3)))(astro@4.16.18(@types/node@22.13.10)(rollup@2.79.1)(sass@1.83.4)(terser@5.31.0)(typescript@5.7.3)): + starlight-links-validator@0.13.4(@astrojs/starlight@0.29.2(patch_hash=cce5b634885e07791c60f64102f8e7a74def815cdbc19d8aa069b9f4602f2890)(astro@4.16.18(@types/node@22.13.13)(rollup@2.79.2)(sass@1.86.0)(terser@5.39.0)(typescript@5.7.3)))(astro@4.16.18(@types/node@22.13.13)(rollup@2.79.2)(sass@1.86.0)(terser@5.39.0)(typescript@5.7.3)): dependencies: - '@astrojs/starlight': 0.29.2(patch_hash=cce5b634885e07791c60f64102f8e7a74def815cdbc19d8aa069b9f4602f2890)(astro@4.16.18(@types/node@22.13.10)(rollup@2.79.1)(sass@1.83.4)(terser@5.31.0)(typescript@5.7.3)) + '@astrojs/starlight': 0.29.2(patch_hash=cce5b634885e07791c60f64102f8e7a74def815cdbc19d8aa069b9f4602f2890)(astro@4.16.18(@types/node@22.13.13)(rollup@2.79.2)(sass@1.86.0)(terser@5.39.0)(typescript@5.7.3)) '@types/picomatch': 2.3.3 - astro: 4.16.18(@types/node@22.13.10)(rollup@2.79.1)(sass@1.83.4)(terser@5.31.0)(typescript@5.7.3) + astro: 4.16.18(@types/node@22.13.13)(rollup@2.79.2)(sass@1.86.0)(terser@5.39.0)(typescript@5.7.3) github-slugger: 2.0.0 hast-util-from-html: 2.0.1 hast-util-has-property: 3.0.0 @@ -8005,39 +8093,44 @@ snapshots: get-east-asian-width: 1.3.0 strip-ansi: 7.1.0 - string.prototype.matchall@4.0.11: + string.prototype.matchall@4.0.12: dependencies: - call-bind: 1.0.7 + call-bind: 1.0.8 + call-bound: 1.0.4 define-properties: 1.2.1 - es-abstract: 1.23.3 + es-abstract: 1.23.9 es-errors: 1.3.0 - es-object-atoms: 1.0.0 - get-intrinsic: 1.2.4 - gopd: 1.0.1 - has-symbols: 1.0.3 - internal-slot: 1.0.7 - regexp.prototype.flags: 1.5.2 + es-object-atoms: 1.1.1 + get-intrinsic: 1.3.0 + gopd: 1.2.0 + has-symbols: 1.1.0 + internal-slot: 1.1.0 + regexp.prototype.flags: 1.5.4 set-function-name: 2.0.2 - side-channel: 1.0.6 + side-channel: 1.1.0 - string.prototype.trim@1.2.9: + string.prototype.trim@1.2.10: dependencies: - call-bind: 1.0.7 + call-bind: 1.0.8 + call-bound: 1.0.4 + define-data-property: 1.1.4 define-properties: 1.2.1 - es-abstract: 1.23.3 - es-object-atoms: 1.0.0 + es-abstract: 1.23.9 + es-object-atoms: 1.1.1 + has-property-descriptors: 1.0.2 - string.prototype.trimend@1.0.8: + string.prototype.trimend@1.0.9: dependencies: - call-bind: 1.0.7 + call-bind: 1.0.8 + call-bound: 1.0.4 define-properties: 1.2.1 - es-object-atoms: 1.0.0 + es-object-atoms: 1.1.1 string.prototype.trimstart@1.0.8: dependencies: - call-bind: 1.0.7 + call-bind: 1.0.8 define-properties: 1.2.1 - es-object-atoms: 1.0.0 + es-object-atoms: 1.1.1 stringify-entities@4.0.4: dependencies: @@ -8064,11 +8157,11 @@ snapshots: strip-comments@2.0.1: {} - strnum@1.0.5: {} + strnum@1.1.2: {} - style-to-object@0.4.4: + style-to-js@1.1.16: dependencies: - inline-style-parser: 0.1.1 + style-to-object: 1.0.8 style-to-object@1.0.8: dependencies: @@ -8095,36 +8188,36 @@ snapshots: type-fest: 0.16.0 unique-string: 2.0.0 - terser@5.31.0: + terser@5.39.0: dependencies: '@jridgewell/source-map': 0.3.6 - acorn: 8.14.0 + acorn: 8.14.1 commander: 2.20.3 source-map-support: 0.5.21 tiny-invariant@1.3.3: {} - tinyexec@0.3.1: {} + tinyexec@0.3.2: {} - tldts-core@6.1.47: {} + tldts-core@6.1.85: {} - tldts@6.1.47: + tldts@6.1.85: dependencies: - tldts-core: 6.1.47 + tldts-core: 6.1.85 to-regex-range@5.0.1: dependencies: is-number: 7.0.0 - tough-cookie@5.0.0: + tough-cookie@5.1.2: dependencies: - tldts: 6.1.47 + tldts: 6.1.85 tr46@1.0.1: dependencies: punycode: 2.3.1 - tr46@5.0.0: + tr46@5.1.0: dependencies: punycode: 2.3.1 @@ -8132,11 +8225,11 @@ snapshots: trough@2.2.0: {} - tsconfck@3.1.4(typescript@5.7.3): + tsconfck@3.1.5(typescript@5.7.3): optionalDependencies: typescript: 5.7.3 - tslib@2.6.3: {} + tslib@2.8.1: {} tsm@2.3.0: dependencies: @@ -8144,39 +8237,40 @@ snapshots: type-fest@0.16.0: {} - type-fest@4.30.0: {} + type-fest@4.38.0: {} - typed-array-buffer@1.0.2: + typed-array-buffer@1.0.3: dependencies: - call-bind: 1.0.7 + call-bound: 1.0.4 es-errors: 1.3.0 - is-typed-array: 1.1.13 + is-typed-array: 1.1.15 - typed-array-byte-length@1.0.1: + typed-array-byte-length@1.0.3: dependencies: - call-bind: 1.0.7 - for-each: 0.3.3 - gopd: 1.0.1 - has-proto: 1.0.3 - is-typed-array: 1.1.13 + call-bind: 1.0.8 + for-each: 0.3.5 + gopd: 1.2.0 + has-proto: 1.2.0 + is-typed-array: 1.1.15 - typed-array-byte-offset@1.0.2: + typed-array-byte-offset@1.0.4: dependencies: available-typed-arrays: 1.0.7 - call-bind: 1.0.7 - for-each: 0.3.3 - gopd: 1.0.1 - has-proto: 1.0.3 - is-typed-array: 1.1.13 - - typed-array-length@1.0.6: - dependencies: - call-bind: 1.0.7 - for-each: 0.3.3 - gopd: 1.0.1 - has-proto: 1.0.3 - is-typed-array: 1.1.13 - possible-typed-array-names: 1.0.0 + call-bind: 1.0.8 + for-each: 0.3.5 + gopd: 1.2.0 + has-proto: 1.2.0 + is-typed-array: 1.1.15 + reflect.getprototypeof: 1.0.10 + + typed-array-length@1.0.7: + dependencies: + call-bind: 1.0.8 + for-each: 0.3.5 + gopd: 1.2.0 + is-typed-array: 1.1.15 + possible-typed-array-names: 1.1.0 + reflect.getprototypeof: 1.0.10 typedoc-plugin-markdown@4.2.10(typedoc@0.26.11(typescript@5.7.3)): dependencies: @@ -8191,7 +8285,7 @@ snapshots: lunr: 2.3.9 markdown-it: 14.1.0 minimatch: 9.0.5 - shiki: 1.26.1 + shiki: 1.29.2 typescript: 5.7.3 yaml: 2.6.0 @@ -8203,23 +8297,23 @@ snapshots: ultramatter@0.0.4: {} - unbox-primitive@1.0.2: + unbox-primitive@1.1.0: dependencies: - call-bind: 1.0.7 - has-bigints: 1.0.2 - has-symbols: 1.0.3 - which-boxed-primitive: 1.0.2 + call-bound: 1.0.4 + has-bigints: 1.1.0 + has-symbols: 1.1.0 + which-boxed-primitive: 1.1.1 undici-types@6.20.0: {} - unicode-canonical-property-names-ecmascript@2.0.0: {} + unicode-canonical-property-names-ecmascript@2.0.1: {} unicode-match-property-ecmascript@2.0.0: dependencies: - unicode-canonical-property-names-ecmascript: 2.0.0 + unicode-canonical-property-names-ecmascript: 2.0.1 unicode-property-aliases-ecmascript: 2.1.0 - unicode-match-property-value-ecmascript@2.1.0: {} + unicode-match-property-value-ecmascript@2.2.0: {} unicode-property-aliases-ecmascript@2.1.0: {} @@ -8287,16 +8381,12 @@ snapshots: upath@1.2.0: {} - update-browserslist-db@1.1.1(browserslist@4.24.2): + update-browserslist-db@1.1.3(browserslist@4.24.4): dependencies: - browserslist: 4.24.2 + browserslist: 4.24.4 escalade: 3.2.0 picocolors: 1.1.1 - uri-js@4.4.1: - dependencies: - punycode: 2.3.1 - util-deprecate@1.0.2: {} vfile-location@5.0.3: @@ -8314,20 +8404,20 @@ snapshots: '@types/unist': 3.0.3 vfile-message: 4.0.2 - vite@5.4.11(@types/node@22.13.10)(sass@1.83.4)(terser@5.31.0): + vite@5.4.15(@types/node@22.13.13)(sass@1.86.0)(terser@5.39.0): dependencies: esbuild: 0.21.5 - postcss: 8.4.49 - rollup: 4.28.0 + postcss: 8.5.3 + rollup: 4.37.0 optionalDependencies: - '@types/node': 22.13.10 + '@types/node': 22.13.13 fsevents: 2.3.3 - sass: 1.83.4 - terser: 5.31.0 + sass: 1.86.0 + terser: 5.39.0 - vitefu@1.0.4(vite@5.4.11(@types/node@22.13.10)(sass@1.83.4)(terser@5.31.0)): + vitefu@1.0.6(vite@5.4.15(@types/node@22.13.13)(sass@1.86.0)(terser@5.39.0)): optionalDependencies: - vite: 5.4.11(@types/node@22.13.10)(sass@1.83.4)(terser@5.31.0) + vite: 5.4.15(@types/node@22.13.13)(sass@1.86.0)(terser@5.39.0) w3c-xmlserializer@5.0.0: dependencies: @@ -8345,9 +8435,9 @@ snapshots: whatwg-mimetype@4.0.0: {} - whatwg-url@14.1.0: + whatwg-url@14.2.0: dependencies: - tr46: 5.0.0 + tr46: 5.1.0 webidl-conversions: 7.0.0 whatwg-url@7.1.0: @@ -8356,26 +8446,51 @@ snapshots: tr46: 1.0.1 webidl-conversions: 4.0.2 - which-boxed-primitive@1.0.2: + which-boxed-primitive@1.1.1: + dependencies: + is-bigint: 1.1.0 + is-boolean-object: 1.2.2 + is-number-object: 1.1.1 + is-string: 1.1.1 + is-symbol: 1.1.1 + + which-builtin-type@1.2.1: + dependencies: + call-bound: 1.0.4 + function.prototype.name: 1.1.8 + has-tostringtag: 1.0.2 + is-async-function: 2.1.1 + is-date-object: 1.1.0 + is-finalizationregistry: 1.1.1 + is-generator-function: 1.1.0 + is-regex: 1.2.1 + is-weakref: 1.1.1 + isarray: 2.0.5 + which-boxed-primitive: 1.1.1 + which-collection: 1.0.2 + which-typed-array: 1.1.19 + + which-collection@1.0.2: dependencies: - is-bigint: 1.0.4 - is-boolean-object: 1.1.2 - is-number-object: 1.0.7 - is-string: 1.0.7 - is-symbol: 1.0.4 + is-map: 2.0.3 + is-set: 2.0.3 + is-weakmap: 2.0.2 + is-weakset: 2.0.4 which-pm-runs@1.1.0: {} - which-pm@3.0.0: + which-pm@3.0.1: dependencies: load-yaml-file: 0.2.0 - which-typed-array@1.1.15: + which-typed-array@1.1.19: dependencies: available-typed-arrays: 1.0.7 - call-bind: 1.0.7 - for-each: 0.3.3 - gopd: 1.0.1 + call-bind: 1.0.8 + call-bound: 1.0.4 + for-each: 0.3.5 + get-proto: 1.0.1 + gopd: 1.2.0 has-tostringtag: 1.0.2 widest-line@5.0.0: @@ -8393,23 +8508,23 @@ snapshots: workbox-build@6.6.0(@types/babel__core@7.20.5): dependencies: - '@apideck/better-ajv-errors': 0.3.6(ajv@8.13.0) - '@babel/core': 7.26.0 - '@babel/preset-env': 7.24.5(@babel/core@7.26.0) - '@babel/runtime': 7.25.6 - '@rollup/plugin-babel': 5.3.1(@babel/core@7.26.0)(@types/babel__core@7.20.5)(rollup@2.79.1) - '@rollup/plugin-node-resolve': 11.2.1(rollup@2.79.1) - '@rollup/plugin-replace': 2.4.2(rollup@2.79.1) + '@apideck/better-ajv-errors': 0.3.6(ajv@8.17.1) + '@babel/core': 7.26.10 + '@babel/preset-env': 7.26.9(@babel/core@7.26.10) + '@babel/runtime': 7.27.0 + '@rollup/plugin-babel': 5.3.1(@babel/core@7.26.10)(@types/babel__core@7.20.5)(rollup@2.79.2) + '@rollup/plugin-node-resolve': 11.2.1(rollup@2.79.2) + '@rollup/plugin-replace': 2.4.2(rollup@2.79.2) '@surma/rollup-plugin-off-main-thread': 2.2.3 - ajv: 8.13.0 + ajv: 8.17.1 common-tags: 1.8.2 fast-json-stable-stringify: 2.1.0 fs-extra: 9.1.0 glob: 7.2.3 lodash: 4.17.21 pretty-bytes: 5.6.0 - rollup: 2.79.1 - rollup-plugin-terser: 7.0.2(rollup@2.79.1) + rollup: 2.79.2 + rollup-plugin-terser: 7.0.2(rollup@2.79.2) source-map: 0.8.0-beta.0 stringify-object: 3.3.0 strip-comments: 2.0.1 @@ -8503,7 +8618,7 @@ snapshots: wrappy@1.0.2: {} - ws@8.18.0: {} + ws@8.18.1: {} xml-name-validator@5.0.0: {} @@ -8517,17 +8632,17 @@ snapshots: yargs-parser@21.1.1: {} - yocto-queue@1.1.1: {} + yocto-queue@1.2.1: {} - zod-to-json-schema@3.23.5(zod@3.23.8): + zod-to-json-schema@3.24.5(zod@3.24.2): dependencies: - zod: 3.23.8 + zod: 3.24.2 - zod-to-ts@1.2.0(typescript@5.7.3)(zod@3.23.8): + zod-to-ts@1.2.0(typescript@5.7.3)(zod@3.24.2): dependencies: typescript: 5.7.3 - zod: 3.23.8 + zod: 3.24.2 - zod@3.23.8: {} + zod@3.24.2: {} zwitch@2.0.4: {} diff --git a/public/d2/docs/zh-tw/concept/Inter-Process Communication/index-0.svg b/public/d2/docs/zh-tw/concept/Inter-Process Communication/index-0.svg new file mode 100644 index 0000000000..03c0d94417 --- /dev/null +++ b/public/d2/docs/zh-tw/concept/Inter-Process Communication/index-0.svg @@ -0,0 +1,191 @@ + + + + + + + + +WebviewFrontendCoreBackend Event Event + + + + + + diff --git a/public/d2/docs/zh-tw/concept/Inter-Process Communication/index-1.svg b/public/d2/docs/zh-tw/concept/Inter-Process Communication/index-1.svg new file mode 100644 index 0000000000..5f002bab01 --- /dev/null +++ b/public/d2/docs/zh-tw/concept/Inter-Process Communication/index-1.svg @@ -0,0 +1,194 @@ + + + + + + + + +WebviewFrontendCoreBackendInvokeHandler IPC Request Invoke command Serialize return Response + + + + + + + + + diff --git a/public/d2/docs/zh-tw/concept/architecture-0.svg b/public/d2/docs/zh-tw/concept/architecture-0.svg new file mode 100644 index 0000000000..d93a3e68c4 --- /dev/null +++ b/public/d2/docs/zh-tw/concept/architecture-0.svg @@ -0,0 +1,198 @@ + + + + + + + + +CoreUpstreamtauritauri-buildtauri-codegentauri-runtime-wryWRYTAOtauri-runtimetauri-macrostauri-utils + + + + + + + + + + + + + diff --git a/public/d2/docs/zh-tw/concept/process-model-0.svg b/public/d2/docs/zh-tw/concept/process-model-0.svg new file mode 100644 index 0000000000..20963bf722 --- /dev/null +++ b/public/d2/docs/zh-tw/concept/process-model-0.svg @@ -0,0 +1,197 @@ + + + + + + + + +CoreEvents & Commands 1Events & Commands 2Events & Commands 3WebView1WebView2WebView3WebViewWebViewWebView + + + + + + + + + + + + diff --git a/src/content/docs/zh-tw/about/book.md b/src/content/docs/zh-tw/about/book.md new file mode 100644 index 0000000000..44303f8c8b --- /dev/null +++ b/src/content/docs/zh-tw/about/book.md @@ -0,0 +1,32 @@ +--- +title: Tauri 之書 +i18nReady: true +--- + +:::note[進度更新] + +我們正在積極地創作和撰寫《Tauri 之書》。由於 Tauri 的巨大增長,我們遇到了延遲,但最近重新確定了這個專案的優先事項。雖然我們還沒有發佈時間表的細節,但你可以關注這個頁面的更新。 + +我們很抱歉這篇文章延後了原定的出版日期。如果您透過 GitHub 贊助商或 Open Collective 進行了捐贈,並希望要求退款,您可以透過 Open Collective:[聯絡 Open Collective 上的 Tauri](https://opencollective.com/tauri/contact)。 + +::: + +### 概述 + +Tauri 之書將引導您透過 Tauri 的歷史和我們所做的設計決策。它還將深入討論為什麼隱私、安全和永續性是重要的和基本的討論,你可以應用到任何現代軟體專案。 + +主題包括: + +- Tauri 設計背後的方法和原理 +- 使用 Tauri 建置時的選項 +- 你不必在快速交付和可持續和負責任之間進行選擇 +- 為什麼我們選擇 Rust 語言作為 Tauri 的綁定和應用層 +- 為什麼二元審查很重要 + +### 歷史 + +到 2020 年,原生應用程式的製造已經變得比以往任何時候都更容易和更容易獲得。儘管如此,初學者和經驗豐富的開發人員都面臨著快速變化的安全和隱私環境中的艱難選擇。在使用者設備的半可信環境中尤其如此。 + +Tauri 消除了猜測,因為它從一開始就被設計成採用 Rust 語言的新範式和創造性靈活性,並允許您使用任何前端框架建立應用程式。了解如何為主要的桌面和行動平台設計、建置、審計和部署小型、快速、健全和安全的原生應用程式,所有這些都可以在完全相同的程式碼庫中在記錄的時間內完成,甚至不需要了解 Rust 程式語言。 + +作者和 Tauri 的創始人 Daniel 和 Lucas 將帶領您從理論到實踐的旅程,期間您將了解為什麼要構建 Tauri 以及它在內部是如何工作的。 。本書結合了開源、DevOps、安全和企業架構方面的客座見解,也展示了話語式的哲學討論和開源永續性觀點,你的下一代應用程式將從中受益——你的使用者也將從中受益。 diff --git a/src/content/docs/zh-tw/about/governance.md b/src/content/docs/zh-tw/about/governance.md new file mode 100644 index 0000000000..2233339abb --- /dev/null +++ b/src/content/docs/zh-tw/about/governance.md @@ -0,0 +1,50 @@ +--- +title: Tauri 治理 +i18nReady: true +--- + +Tauri 組織結構的主要目標之一是確保我們始終堅持開源價值觀,並在尊重貢獻者的健康和福祉的同時可持續發展。 [Commons Conservancy 中的 Tauri 計劃](https://dracc.commonsconservancy.org/0035/)旨在致力於這些價值觀,並促進 Tauri 及其輔助材料未來發展過程中的開放、透明和高效治理。 + +## Tauri 工作小組 + +Tauri 工作小組是為實現此治理過程而建立的集體框架。它由以下幾個部分組成: + +- 工作小組成員 +- Tauri 董事和董事會 +- 領域和領域負責人 +- 團隊 + +![Tauri governance diagram](@assets/about/governance/diagram.svg) + +### 工作小組成員 + +所有組成 Tauri 工作小組的人。 + +### Tauri 理事和理事會 + +Tauri 董事會是 Tauri 方案的中央決策機構,負責 Tauri 方案的全面健康與穩定。執行局就方案內的重大決定和工作小組所提出的問題進行表決。 + +個別董事可能是技術貢獻者,是 Tauri 未來的利益相關者,分享行業經驗,或對開放原始碼中的監管和法律方面充滿熱情。 + +### 領域與領域負責人 + +領域是在 Tauri 中表示感興趣領域的組織單位。 + +領域負責人是 Tauri 社群中具有該領域專業知識並受信任的貢獻者。他們負責設定方向,監督和支援該領域內的活動。 + +目前的領域和領域負責人詳見 [GitHub 上的治理與指導儲存庫](https://github.com/tauri-apps/governance-and-guidance)。 + +### 團隊 + +團隊是支持或維護 Tauri 程式特定領域的小貢獻者團體。它們是 Tauri 執行其長期任務和目標的一種手段,特別是當特別的貢獻無法達到相同的結果時。 + +## 參與 + +如果你有興趣成為 Tauri 董事會董事或領域領導,這些職位的選舉全年都在進行。對於域名領導者來說,這些活動在春季和秋季舉行,對於董事會成員來說,這些活動在夏季舉行。如何申請的說明張貼在 [Tauri 部落格](https://tauri.app/blog),在各自的選舉之前。 + +## 附加資源 + +- [治理與指導儲存庫](https://github.com/tauri-apps/governance-and-guidance):有關 Tauri 治理和當前領域和領域領導的更詳細資訊 +- [社會契約](https://github.com/tauri-apps/governance-and-guidance/blob/main/SOCIAL_CONTRACT.md):社會契約告知我們的決策與組織 +- [行為準則](https://github.com/tauri-apps/governance-and-guidance/blob/main/CODE_OF_CONDUCT.md) +- [Tauri 計劃章程](https://dracc.commonsconservancy.org/0035/) diff --git a/src/content/docs/zh-tw/about/index.mdx b/src/content/docs/zh-tw/about/index.mdx new file mode 100644 index 0000000000..72d8330c38 --- /dev/null +++ b/src/content/docs/zh-tw/about/index.mdx @@ -0,0 +1,30 @@ +--- +title: 關於 Tauri +i18nReady: true +--- + +:::tip + +如果你想要快速了解技術概述並開始建立一個應用程式,那麼請訪問[什麼是 Tauri 頁面](/zh-tw/start/)。 +如果你想更了解該專案的理念,請持續閱讀。 +::: + +import { LinkCard, CardGrid } from '@astrojs/starlight/components'; + + + + + + diff --git a/src/content/docs/zh-tw/about/philosophy.md b/src/content/docs/zh-tw/about/philosophy.md new file mode 100644 index 0000000000..f9426e7721 --- /dev/null +++ b/src/content/docs/zh-tw/about/philosophy.md @@ -0,0 +1,47 @@ +--- +title: Tauri 哲學 +i18nReady: true +--- + +Tauri 是一個工具包,可以幫助開發人員為主要的桌面平台製作應用程式——幾乎可以使用任何現有的前端框架。核心是用 Rust 建構的,CLI 利用 Node.js 使 Tauri 成為一個真正的多語言方法來建立和維護偉大的應用程式。 + + + +## 安全優先 + +在當今世界,每個真實的威脅模型都假設使用者的裝置已經被入侵。這讓應用程式開發人員陷入了一個複雜的境地,因為如果設備已經處於危險之中,如何能讓軟體可信呢? + +我們採取的是縱深防禦。我們希望你能採取一切可能的預防措施來減少你面對攻擊者的表面積。 Tauri 允許你選擇要發佈的 API 端點,無論你是否希望在應用程式中內建本機主機伺服器,它甚至可以在執行時間隨機化功能句柄。這些技術和其他技術構成了增強您和您的使用者能力的安全基線。 + +透過使靜態攻擊變得極其困難並將系統彼此隔離來減慢攻擊者的速度是遊戲的名稱。如果您來自電子生態系統,請放心,預設情況下 Tauri 只提供二進制文件,而不是 ASAR 文件。 + +透過選擇以安全作為指導力量來建立 Tauri,我們為您提供了採取主動安全姿態的每一個機會。 + +## Polyglots, not Silos + +大多數當代框架使用單一語言範式,因此被困在知識和慣用法的泡沫中。這可以很好地適用於某些利基應用程式,但它也培養了一種部落主義。 + +這可以從 React、Angular 和 Vue 開發社群擠在一起的方式中看出,最終很少產生交叉影響。 + +同樣的情況可以在 Rust、Node 和 c++ 的戰場上看到,強硬派立場鮮明,拒絕跨社群合作。 + +今天,Tauri 使用 Rust 作為後端,但在不久的將來,其他後端,如 Go、Nim、Python、Csharp 等將成為可能。這是因為我們正在維護官方的 Rust 綁定到 [webview](https://github.com/webview) 組織,並計劃讓你根據自己的需求切換後端。由於我們的 API 可以使用 C interop 以任何語言實現,因此完全符合規範只需要一個 PR。 + +## 真正的開源 + +如果沒有社區,這一切都沒有意義。今天的軟體社群是一個神奇的地方,人們在這裡互相幫助並做出很棒的東西——開源是其中非常重要的一部分。 + +開源對不同的人來說意味著不同的東西,但大多數人都會同意它是為了支持自由。當軟體不尊重你的權利時,它看起來是不公平的,並可能透過不道德的方式損害你的自由。 + +這就是為什麼我們為 FLOSS 倡導者可以使用 Tauri 建立「可認證的」開源應用程式而感到自豪,這些應用程式可以包含在 FSF 認可的 GNU/Linux 發行版中。 + +## 未來 + +Tauri 的未來取決於你的參與和貢獻。嘗試它,文件問題,加入一個工作組或捐款-每一個貢獻都是重要的。無論如何,請務必保持聯繫! ! diff --git a/src/content/docs/zh-tw/about/trademark.md b/src/content/docs/zh-tw/about/trademark.md new file mode 100644 index 0000000000..e6bf427ebf --- /dev/null +++ b/src/content/docs/zh-tw/about/trademark.md @@ -0,0 +1,119 @@ +--- +title: 商標指南 +i18nReady: true +--- + +本商標政策旨在協助您了解如何在共享資源保護協會內使用 Tauri 專案擁有的金牛座商標、服務標誌和標誌。 + +雖然我們的軟體是在免費和開源軟體許可下提供的,但版權許可並不包括使用我們商標的許可,此政策旨在解釋如何使用我們的商標符合背景法律和社群期望。 + +**本保單涵蓋:** + +- 我們的文字商標和服務商標:TAURI、TAO、WRY +- 我們的標誌:TAURI、TAO、WRY 標誌 (以及所有視覺衍生品) + +本政策包括所有商標和服務商標,無論是否註冊。 + +## 一般指南 + +無論何時你使用我們的標誌,你必須總是以一種不誤導任何人的方式這樣做,他們從誰那裡得到什麼。例如,當你發布一個修改版本(又稱 Fork)時,你不能說你在發布 TAURI 軟體,因為收件人可能不理解你的修改版本和我們自己的版本之間的差異。 + +您也不能在您的網站上使用我們的標誌,以表明您的網站是官方網站或我們認可您的網站。 + +但是,您可以說您喜歡 TAURI 軟體,您參與了 TAURI 社區,您正在提供 TAURI 軟體的未修改版本。 + +貴方不得使用或註冊我方標誌或其變體作為貴方自己的商標、服務標誌、網域名稱、公司名稱、商號、產品名稱或服務名稱的一部分。 + +商標法不允許您使用與我們過於相似的名稱或商標。因此,貴方不得對類似或相容的產品或服務使用我們的任何標記的明顯變體或任何語音等價物、外語等價物、起飛或縮寫。我們認為下面的程式碼與我們的某個標記過於相似: + +- TAURIMAGE +- Tauri 錢包應用 + +## 可接受的用途 + +### 應用程式 + +TAURI 是一個為計算設備開發應用程式的框架。您可以聲稱您的應用程式使用了 TAURI,但應注意避免給人留下這樣的印象,即您的應用程式是由 Commons Conservancy 的 Tauri 計劃批准的,或者是一個正式的應用程式。一定要小心,不要在發布應用程式時使用預設圖示。 + +### 外掛程式和模板 + +您可以使用適當的命名約定發佈外掛程式和範本的程式碼,但請注意這些工作沒有得到官方批准。只有由 GitHub 組織 `tauri-apps` 內的組織管理的程式碼庫才被認為是官方的。 + +## 核心修改(fork) + +如果你發布我們的軟體的修改版本(TAURI 核心),你必須刪除我們所有的標誌和命名從它。您必須保留我們的 SPDX 格式的原始許可證。您可以使用我們的文字標記,但不能使用我們的標誌,以如實描述您所提供的軟體的來源。例如,如果您發布的程式碼是對我們軟體的修改,您可能會說,“此軟體是從金牛座軟體的源代碼派生的。” + +### 關於相容性的聲明 + +您可以使用我們的文字標識,但不能使用我們的商標圖案,以真實地描述您的軟體與我們之間的關係。任何其他用途可能會暗示我們已經認證或批准了您的軟體。如果您希望使用我們的商標圖案,請聯絡我們討論授權條款。 + +### 命名相容的產品 + +如果您希望以 TAURI 軟體為參考來描述您的產品,以下是您可以這樣做的條件。只有在以下情況下,您才能將您的軟體稱為 XYZ(其中 XYZ 是您的產品名稱): + +- 我們提供的所有 TAURI 軟體版本,都是由我們提供的精確二進制檔案或核心軟體和工具製造的。 +- 您的產品與 TAURI 軟體的 api 完全相容。 +- 您在行銷資料或產品描述中使用以下說明:“金牛座是 Tauri 專案的商標,隸屬於共享資源保護協會。 https://tauri.app ” + +### 使用者群組 + +只要符合以下條件,您可以將文字識別作為您的使用者群組名稱的一部分使用: + +- 我們小組的主要焦點是我們的軟體 +- 該集團沒有獲利 +- 出席會議的任何費用僅用於支付場地、食物和飲料的費用 + +您無權使用我們的標誌進行會議。 + +### 不包含域名 + +您不得註冊任何域名,包括我們的字詞標記或任何變體或組合。 + +### TAURI 標誌的其他獲利用途 + +如果您正在製作視頻,教程系列,書籍或其他教育材料,並且您通過訂閱,銷售,廣告或類似方式獲得付款,那麼您必須獲得公共資源保護協會內 Tauri 計劃的明確許可。 + +## 如何顯示我們的標誌 + +當您有權使用我們的標誌時,這裡是如何顯示它。 + +### 商標標記與圖例 + +在網頁、文件或文件中,第一次或最突出地提及標誌時,應附有一個符號,表明該標誌是註冊商標(「®」)還是未註冊商標(「™」)。如果您不知道哪一種適用,請與我們聯絡。 (TAURI 本身就是一個註冊商標。) + +在你使用標記的頁面底部放置以下通知:TAURI 是 [Tauri 程式在共享資源保護協會]的商標。 」 + +### 使用文字商標 + +使用正確的商標,無論是縮寫,連字符,或與任何其他詞或詞的組合。 + +- 不可接受的:TAUREE +- 可接受:TAURI + +不要將商標複數化。 + +- 不可接受:我的電腦上運行著 17 個 TAURI。 +- 可接受:我的電腦上運行了 17 個 TAURI 應用程式,並且有空閒的 ram 空間。 + +使用商標作為修飾名詞的形容詞。 + +- 不可接受:這是 TAURI。 +- 可接受:這是一個 TAURI 軟體應用程式。 + +### 商標的使用 + +除了縮放,你不能改變任何 logo。這意味著你不能加入裝飾元素,改變顏色,改變比例,扭曲它,新增元素,或將它與其他 logo 結合。 + +我們有一個高對比的 logo 版本,你可以在下面的資源部分下載。 + +## 資產 + +- 你可以在這裡下載整個[品牌指南](/assets/brand_guidelines.pdf) - (PDF,74.3 MB) +- 您可以在 [Logopack](/assets/logopack.zip) 下載 LOGO 和 Wordmark 的 SVG 和 PNG 格式檔案 - (ZIP,203 KB) + +--- + +共享資源保護協會內的 Tauri 專案保留在任何時候修改這些商標指南的所有權利。 +如有疑問,請發送電子郵件至 `trademark@tauri.app`。 + +這些準則基於《模板商標指南》,可在 http://www.modeltrademarkguidelines.org 上獲取,採用創作共用署名 3.0 國際授權使用:https://creativecommons.org/licenses/by/3.0/deed.en_EU。版本 1.0 日期為 2022 年 8 月 20 日。 diff --git a/src/content/docs/zh-tw/concept/Inter-Process Communication/brownfield.md b/src/content/docs/zh-tw/concept/Inter-Process Communication/brownfield.md new file mode 100644 index 0000000000..364350fd0d --- /dev/null +++ b/src/content/docs/zh-tw/concept/Inter-Process Communication/brownfield.md @@ -0,0 +1,28 @@ +--- +title: Brownfield 模式 +--- + +_**這是預設模式。 **_ + +這是使用 Tauri 的最簡單和最直接的模式,因為本模式會盡可能嘗試與現有的前端專案相容。簡而言之,它盡量不要求額外的配置,跟著現有的 web 前端應用在瀏覽器中使用的方式保持一致。但並不是 _**所有**_ 在現有瀏覽器應用程式中有效的功能都能開箱即用。 + +如果你不熟悉 Brownfield 軟體開發模式,你可以閱讀 [Brownfield 維基百科]。 +對 Tauri 而言,現有軟體特別指現代瀏覽器支援的特性與行為規範,而非傳統遺留系統。 + +## 配置 + +因為 Brownfield 模式是預設模式,所以無需設定任何配置選項。如果要明確設定它,你可以在 `tauri.conf.json` 設定檔中使用 `tauri > pattern` 物件。 + +```json +{ + "tauri": { + "pattern": { + "use": "brownfield" + } + } +} +``` + +_**Brownfield 模式沒有額外的配置選項。 **_ + +[Brownfield 維基百科]: https://en.wikipedia.org/wiki/Brownfield_(software_development) diff --git a/src/content/docs/zh-tw/concept/Inter-Process Communication/index.mdx b/src/content/docs/zh-tw/concept/Inter-Process Communication/index.mdx new file mode 100644 index 0000000000..167fc6b314 --- /dev/null +++ b/src/content/docs/zh-tw/concept/Inter-Process Communication/index.mdx @@ -0,0 +1,94 @@ +--- +title: 行程間通信 +sidebar: + label: 概述 + order: 1 + i18nReady: true +--- + +import { CardGrid, LinkCard } from '@astrojs/starlight/components'; + +行程間通訊(IPC)允許隔離的行程安全地進行通信,是建構更複雜應用程式的關鍵。 + +在以下指南中了解特定的 IPC 模式: + + + + + + +Tauri 使用特定風格的行程間通信,稱為[非同步資訊傳遞],其中流程透過一些簡單的資料表示交換*請求*和*回應*。對於任何有 Web 開發經驗的人來說,資訊傳遞應該聽起來很熟悉,因為這種範式用於互聯網的客戶端-伺服器通訊。 + +資訊傳遞是一種比共享記憶體或直接函數存取更安全的技術,因為接收方可以自由地拒絕或丟棄請求。例如,如果Tauri核心程序確定某個請求是惡意的,它將簡單地丟棄該請求,並且不會執行相應的函數。 + +接下來,我們將更詳細地解釋 Tauri 的兩個 IPC 原語——`事件`和`命令`。 + +## 事件 + +事件是一次性、單向的 IPC 資訊,最適合用於通訊生命週期事件和狀態變化。與[命令](#命令)不同,事件可以由前端*和* Tauri 核心發出。 + +
+ +```d2 sketch pad=50 +shape: sequence_diagram + +Frontend: { + shape: rectangle + label: "Webview\nFrontend" +} +Core: { + shape: rectangle + label: "Core\nBackend" +} + +Frontend -> Core: "Event"{style.animated: true} +Core -> Frontend: "Event"{style.animated: true} +``` + +
在核心和 Webview 之間發送的事件。
+
+ +## 指令 + +Tauri 也提供了一種類似[外部函數介面]的抽象,建立在IPC資訊之上[^1]。 +主要 API `invoke` 類似於瀏覽器的`fetch` API,允許前端呼叫 Rust 函數、傳遞參數並接收資料。 + +由於該機制在底層使用類似 [JSON-RPC] 的協定來序列化請求和回應,因此所有參數和返回資料必須能夠序列化為 JSON。 + +
+ +```d2 sketch pad=50 +shape: sequence_diagram + + +Frontend: { + label: "Webview\nFrontend" +} + +Core: { + label: "Core\nBackend" +} +InvokeHandler: { + label: "Invoke\nHandler" +} + +Frontend -> Core: "IPC Request"{style.animated: true} +Core -> InvokeHandler: "Invoke command"{style.animated: true} +InvokeHandler -> Core: "Serialize return"{style.animated: true} +Core -> Frontend: "Response"{style.animated: true} +``` + +
指令呼叫中涉及的 IPC 資訊。
+
+ +[^1]: 由於命令在底層仍然使用資訊傳遞,因此它們沒有真實 FFI 介面所面臨的安全隱患。 + +[非同步資訊傳遞]: https://en.wikipedia.org/wiki/Message_passing#Asynchronous_message_passing +[json-rpc]: https://www.jsonrpc.org +[外部函式介面]: https://en.wikipedia.org/wiki/Foreign_function_interface diff --git a/src/content/docs/zh-tw/concept/architecture.mdx b/src/content/docs/zh-tw/concept/architecture.mdx new file mode 100644 index 0000000000..ed8c1d9bab --- /dev/null +++ b/src/content/docs/zh-tw/concept/architecture.mdx @@ -0,0 +1,192 @@ +--- +title: Tauri 結構 +sidebar: + order: 0 + i18nReady: true +--- + +## 介紹 + +Tauri 是一個多語言和通用工具包,非常可組合,允許開發人員建立各種應用程式。它用於使用 Rust 工具和在Webview 中呈現的 HTML 建立桌面電腦應用程式。使用 Tauri 建立的應用程式可以與任意數量的可選 JS API 和Rust API一起發布,以便 Webview 可以透過資訊傳遞控制系統。 + +開發人員可以輕鬆擴展預設 API,以實現自己的功能,並在 Webview 和基於 Rust 的後端之間建立橋接。 + +Tauri 應用程式可以有[托盤類型介面](/zh-tw/learn/system-tray/)。它們可以被[更新](/zh-tw/plugin/updater/),並且如預期地由使用者的作業系統進行管理。 + +由於使用了作業系統的 Webview,它們非常小。它們不附帶運行時,因為最終的二進制檔案是從 Rust 編譯而來的。這使得[逆向工程 Tauri 應用程式不是一項簡單的任務](/zh-tw/security/)。 + +### Tauri 不是 + +Tauri 不是一個輕量級核心包裝器。相反,它直接使用 [WRY](#wry) 和 [TAO](#tao) 來進行系統呼叫的重負載。 + +Tauri 不是虛擬機器或虛擬化環境。相反,它是一個應用程式工具包,允許製作 Webview OS 應用程式。 + +## 核心生態系統 + +
+ +```d2 sketch pad=50 +direction: up + +Core: { + shape: rectangle + "tauri": { + "tauri-runtime" + "tauri-macros" + "tauri-utils" + } + + "tauri-build" + "tauri-codegen" + "tauri-runtime-wry" +} + +Upstream: { + shape: rectangle + direction: right + WRY + TAO +} + +Core."tauri"."tauri-runtime" -> Core."tauri-runtime-wry"{style.animated: true} + +Upstream.WRY -> Upstream.TAO{style.animated: true} +Core."tauri-runtime-wry" -> Upstream.Wry {style.animated: true} +``` + +
簡化的 Tauri 架構圖
+
+ +### tauri + +[在 GitHub 上查看](https://github.com/tauri-apps/tauri/tree/dev/crates/tauri) + +這是一個主要的 crate,將所有內容結合在一起。它將運行時、巨集、工具和 API 整合成一個最終產品。 +它在編譯時會讀取[`tauri.conf.json`](/zh-tw/reference/config/)文件,以引入功能並進行應用程式的實際配置(甚至是專案資料夾中的 `Cargo.toml` 文件)。它在運行時處理腳本注入(用於 polyfills / 原型修訂),託管與系統互動的 API,甚至管理更新過程。 + +### tauri-runtime + +[在 GitHub 上查看](https://github.com/tauri-apps/tauri/tree/dev/crates/tauri-runtime) + +Tauri 本身與底層 Webview 庫之間的黏合層。 + +### tauri-macros + +[在 GitHub 上查看](https://github.com/tauri-apps/tauri/tree/dev/crates/tauri-macros) + +透過利用 [`tauri-codegen`](https://github.com/tauri-apps/tauri/tree/dev/crates/tauri-codegen) crate 為上下文、處理程序和命令建立巨集。 + +### tauri-utils + +[在 GitHub 上查看](https://github.com/tauri-apps/tauri/tree/dev/crates/tauri-utils) + +在許多地方重複使用的通用程式碼,提供有用的工具,如解析設定檔、檢測平台三元組、注入 CSP 和管理資產。 + +### tauri-build + +[在 GitHub 上查看](https://github.com/tauri-apps/tauri/tree/dev/crates/tauri-build) + +在建置時套用宏,以設定 `cargo` 所需的一些特殊功能。 + +### tauri-codegen + +[在 GitHub 上查看](https://github.com/tauri-apps/tauri/tree/dev/crates/tauri-codegen) + +嵌入、哈希和壓縮資產,包括應用程式的圖示以及系統托盤。在編譯時解析[`tauri.conf.json`](/zh-tw/reference/config/)並產生 Config 結構。 + +### tauri-runtime-wry + +[在 GitHub 上查看](https://github.com/tauri-apps/tauri/tree/dev/crates/tauri-runtime-wry) + +這個 crate 為 WRY 開啟了直接的系統層級交互,例如列印、監視器偵測和其他與視窗相關的任務。 + +## Tauri 工具 + +### API (JavaScript / TypeScript) + +[在 GitHub 上查看](https://github.com/tauri-apps/tauri/tree/dev/packages/api) + +一個 TypeScript 函式庫,為您建立 `cjs` 和 `esm` JavaScript 端點,以便您匯入到前端框架中,以便 Webview 可以呼叫和監聽後端活動。也以純 TypeScript 的形式發布,因為對於某些框架來說,這更為最佳化。它利用 Webview 的資訊傳遞與其主機進行通訊。 + +### Bundler (Rust / Shell) + +[在 GitHub 上查看](https://github.com/tauri-apps/tauri/tree/dev/crates/tauri-bundler) + +一個庫,為其檢測或被告知的平台建立 Tauri 應用程式。目前支援 macOS、Windows 和 Linux—但在不久的將來也將支援行動平台。可以在 Tauri 專案之外使用。 + +### cli.rs (Rust) + +[在 GitHub 上查看](https://github.com/tauri-apps/tauri/tree/dev/crates/tauri-cli) + +這個 Rust 可執行檔提供了 CLI 所需的所有活動的完整介面。它在 macOS、Windows 和 Linux 上運行。 + +### cli.js (JavaScript) + +[在 GitHub 上查看](https://github.com/tauri-apps/tauri/tree/dev/packages/cli) + +圍繞 [`cli.rs`](https://github.com/tauri-apps/tauri/blob/dev/crates/tauri-cli)的包裝,使用 [`napi-rs`](https://github.com/napi-rs/napi-rs) 為每個平台產生 npm 套件。 + +### create-tauri-app (JavaScript) + +[在 GitHub 上查看](https://github.com/tauri-apps/create-tauri-app) + +一個工具包,使工程團隊能夠快速建立新的 `tauri-apps` 專案,使用他們選擇的前端框架(只要它已被配置)。 + +## 上游 Crates + +Tauri-Apps 組織維護兩個來自 Tauri 的「上游」 crate,即 TAO 用於建立和管理應用程式窗口,WRY 用於與窗口內的 Webview 進行介面。 + +### TAO + +[在 GitHub 上查看](https://github.com/tauri-apps/tao) + +一個跨平台的應用程式視窗建立庫,支援所有主要平台,如 Windows、macOS、Linux、iOS 和 Android。用 Rust 編寫,它是 [winit](https://github.com/rust-windowing/winit) 的一個分支,我們根據自己的需求進行了擴展—例如選單列和系統托盤。 + +### WRY + +[在 GitHub 上查看](https://github.com/tauri-apps/wry) + +WRY 是一個跨平台的 WebView 渲染庫,以 Rust 編寫,支援所有主要桌面平台,如 Windows、macOS 和 Linux。 Tauri 使用 WRY 作為抽象層,負責決定使用哪個 Webview(以及如何進行互動)。 + +## 其他工具 + +### tauri-action + +[在 GitHub 上查看](https://github.com/tauri-apps/tauri-action) + +一個 GitHub 工作流程,為所有平台建立 Tauri 二進制。甚至允許建立一個(非常基本的)Tauri 應用程式,即使沒有設定 Tauri。 + +### tauri-vscode + +[在 GitHub 上查看](https://github.com/tauri-apps/tauri-vscode) + +這個專案增強了 Visual Studio Code 介面,提供了一些非常實用的功能。 + +### vue-cli-plugin-tauri + +[在 GitHub 上查看](https://github.com/tauri-apps/vue-cli-plugin-tauri) + +允許您在 vue-cli 專案中非常快速地安裝 Tauri。 + +## 外掛 + +[Tauri 外掛指南](/zh-tw/develop/plugins/) + +一般來說,外掛由第三方編寫(儘管可能有官方支援的外掛)。 + +一個外掛通常完成三件事: + 1. 使 Rust 程式碼能夠「做某事」。 + 2. 提供介面間的串接黏合,使其易於整合到應用程式中。 + 3. 提供 JavaScript API,以便與 Rust 程式碼進行介面。 + +以下是一些 Tauri 外掛的範例: + +- [tauri-plugin-fs](https://github.com/tauri-apps/tauri-plugin-fs) +- [tauri-plugin-sql](https://github.com/tauri-apps/tauri-plugin-sql) +- [tauri-plugin-stronghold](https://github.com/tauri-apps/tauri-plugin-stronghold) + +## 許可證 + +Tauri 本身根據 MIT 或 Apache-2.0 許可證授權。如果您重新打包並修改任何原始程式碼,您有責任確保遵守所有上游許可證。 Tauri 以「原樣」提供,沒有明確的適用性聲明。 + +在這裡,您可以瀏覽我們的[軟體資料清單](https://app.fossa.com/projects/git%2Bgithub.com%2Ftauri-apps%2Ftauri)。 \ No newline at end of file diff --git a/src/content/docs/zh-tw/concept/index.mdx b/src/content/docs/zh-tw/concept/index.mdx new file mode 100644 index 0000000000..d940efdd73 --- /dev/null +++ b/src/content/docs/zh-tw/concept/index.mdx @@ -0,0 +1,40 @@ +--- +title: 核心概念 +sidebar: + order: 0 + i18nReady: true + label: 概述 +--- + +import { CardGrid, LinkCard } from '@astrojs/starlight/components'; + +Tauri 有多種主題被視為核心概念,任何開發者在開發應用程式時都應該了解的事情。 +如果你想充分利用這個框架,這裡有一些你應該要更加熟悉的主題。 + + + + + + + + \ No newline at end of file diff --git a/src/content/docs/zh-tw/concept/process-model.md b/src/content/docs/zh-tw/concept/process-model.md new file mode 100644 index 0000000000..6782e26aec --- /dev/null +++ b/src/content/docs/zh-tw/concept/process-model.md @@ -0,0 +1,86 @@ +--- +title: 行程模型 +sidebar: + order: 0 + i18nReady: true +--- + +Tauri 採用了類似於 Electron 或許多現代網頁瀏覽器的多行程架構。 + +本指南探討了這種設計選擇背後的原因以及為什麼它對編寫安全應用程式至關重要。 + +## 為什麼要使用多個行程? + +在圖形使用者介面(GUI)應用程式的早期階段,通常使用單一行程來執行計算、繪製介面和回應使用者輸入。 + +正如你可能猜到的,這意味著長時間運行的昂貴計算會使使用者介面無響應,或者更糟的是,應用程式的一個元件發生故障會導致整個應用程式崩潰。 + +顯然,需要一種更具彈性的架構,應用程式開始在不同的行程中運行不同的元件。這更好地利用了現代多核心 CPU,並創造了更安全的應用程式。一個組件的崩潰不會再影響整個系統,因為組件在不同的行程中隔離開來。如果一個行程進入無效狀態,我們可以輕鬆重新啟動它。 + +我們也可以透過僅向每個行程分配最低限度的權限來限制潛在漏洞的影響範圍,給予它們完成工作的足夠權限。這種模式被稱為[最小權限原則],在現實世界中你經常會看到。如果你邀請一個園丁修剪你的樹籬,你會給他們你的花園的鑰匙。你不會給他們你房子的鑰匙;他們為什麼需要訪問那個呢?同樣的概念適用於電腦程式。我們給他們的存取權越少,如果被攻破,他們造成的傷害就越小。 + +## 核心行程 + +每個 Tauri 應用程式都有一個核心行程,作為應用程式的入口點,並且是唯一一個擁有完全作業系統存取權限的元件。 + +核心的主要責任是利用該權限來建立和協調應用程式視窗、系統匣選單或通知。 + +Tauri 實現了必要的跨平台抽象,使這一過程變得簡單。它還透過核心行程路由所有[行程間通訊],允許你在一個中心位置攔截、過濾和操作 IPC 資訊。 + +核心行程也應負責管理全域狀態,例如設定或資料庫連線。這使你能夠輕鬆同步視窗之間的狀態,並保護你的商業敏感資料免受前端窺探。 + +我們選擇 Rust 來實現 Tauri,因為它的[所有權]概念在保證記憶體安全的同時保持了優異的效能。 + +
+ +```d2 sketch pad=50 +direction: right + +Core: { + shape: diamond +} + +"事件與命令 1": { + WebView1: WebView +} + +"事件與命令 2": { + WebView2: WebView +} + +"事件與命令 3": { + WebView3: WebView +} + +Core -> "事件與指令 1"{style.animated: true} +Core -> "事件與指令 2"{style.animated: true} +Core -> "事件與指令 3"{style.animated: true} + +"事件與指令 1" -> WebView1{style.animated: true} +"事件與指令 2" -> WebView2{style.animated: true} +"事件與指令 3" -> WebView3{style.animated: true} +``` + +
Tauri 行程模型的簡化表示。一個核心行程管理一個或多個 WebView 行程。
+
+ +## WebView 行程 + +核心行程並不會直接渲染實際的使用者介面(UI);它啟動 WebView 行程,這些行程利用作業系統提供的 WebView 程式庫。 WebView 是一個類似瀏覽器的環境,可以執行你的 HTML、CSS 和 JavaScript。 + +這意味著你在傳統網頁開發中使用的大多數技術和工具都可以用來創建 Tauri 應用程式。例如,許多 Tauri 範例是使用 [Svelte] 前端框架和 [Vite] 打包工具編寫的。 + +安全最佳實踐同樣適用;例如,你必須始終清理使用者輸入,絕不會在前端處理機密資訊,並且理想情況下將盡可能多的業務邏輯推遲到核心行程,以保持你的攻擊面較小。 + +與其他類似解決方案不同,WebView 庫**不**包含在你的最終可執行檔中,而是在運行時動態連結[^1]。這使你的應用程式*顯著*更小,但也意味著你需要考慮平台差異,就像傳統網頁開發一樣。 + +[^1]: 目前,Tauri 在 Windows 上使用 [Microsoft Edge WebView2],在 macOS 上使用 [WKWebView],在 Linux 上使用 [webkitgtk]。 + +[最小權限原則]: https://zh.wikipedia.org/wiki/%E6%9C%80%E5%B0%8F%E6%9D%83%E9%99%90%E5%8E%9F%E5%88%99 +[行程間通訊]: /zh-tw/concept/inter-process-communication/ +[所有權]: https://doc.rust-lang.org/book/ch04-01-what-is-ownership.html +[Microsoft Edge WebView2]: https://docs.microsoft.com/en-us/microsoft-edge/webview2/ +[WKWebView]: https://developer.apple.com/documentation/webkit/wkwebview +[webkitgtk]: https://webkitgtk.org +[Svelte]: https://svelte.dev/ +[Vite]: https://vitejs.dev/ \ No newline at end of file diff --git a/src/content/docs/zh-tw/concept/size.mdx b/src/content/docs/zh-tw/concept/size.mdx new file mode 100644 index 0000000000..b6344c5b00 --- /dev/null +++ b/src/content/docs/zh-tw/concept/size.mdx @@ -0,0 +1,72 @@ +--- +title: 應用程式大小 +sidebar: + order: 0 + i18nReady: true +--- + +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +雖然 Tauri 預設提供非常小的二進制文件,但稍微推一下極限也無妨,因此這裡有一些技巧和建議,以達到最佳效果。 + +## Cargo 配置 + +您可以對專案進行的最簡單的前端無關的大小優化之一是為其新增一個 Cargo 配置檔案。 + +根據您使用的是 stable 或 nightly 的 Rust 工具鏈,您可以使用的選項會有所不同。 +除非您是進階用戶,建議您堅持使用穩定版工具鏈。 + + + +```toml +# src-tauri/Cargo.toml +[profile.dev] +incremental = true # 以較小的步驟編譯您的二進制。 + +[profile.release] +codegen-units = 1 # 允許 LLVM 執行更好的最佳化。 +lto = true # 啟用連結時最佳化。 +opt-level = "s" # 優先考慮小型的二進制檔案大小。如果您想要加快速度,請使用 `3`。 +panic = "abort" # 透過停用 panic 處理程序來提升效能。 +strip = true # 確認移除除錯符號。 + +```` + + + +```toml +# src-tauri/Cargo.toml +[profile.dev] +incremental = true # 以較小的步驟編譯您的二進制檔案。 +rustflags = ["-Zthreads=8"] # 提高編譯效能。 + +[profile.release] +codegen-units = 1 # 允許 LLVM 執行更好的最佳化。 +lto = true # 啟用連結時最佳化。 +opt-level = "s" # 優先考慮小的二進制檔案大小。如果您想要加快速度,請使用 `3`。 +panic = "abort" # 透過停用 panic 處理程序來提升效能。 +strip = true # 確認移除除錯符號。 +trim-paths = "all" # 從您的二進制檔案中移除潛在的特權資訊。 +rustflags = ["-Cdebuginfo=0", "-Zthreads=8"] # 提升編譯效能。 +```` + + + + +### 參考資料 + +:::note +這並不是所有可用選項的完整參考,只是我們想要特別強調的幾個選項。 +::: + +- [incremental:](https://doc.rust-lang.org/cargo/reference/profiles.html#incremental) 以較小的步驟編譯您的二進制。 +- [codegen-units:](https://doc.rust-lang.org/cargo/reference/profiles.html#codegen-units) 以犧牲編譯時間最佳化為代價,加快編譯時間。 +- [lto:](https://doc.rust-lang.org/cargo/reference/profiles.html#lto) 啟用連結時最佳化。 +- [opt-level:](https://doc.rust-lang.org/cargo/reference/profiles.html#opt-level) 決定編譯器的重點。使用 `3` 來最佳化效能,使用 `z` 來優化大小,使用 `s` 以達到兩者之間的平衡。 +- [panic:](https://doc.rust-lang.org/cargo/reference/profiles.html#panic) 透過移除 panic unwind 來減少大小。 +- [strip:](https://doc.rust-lang.org/cargo/reference/profiles.html#strip) 從二進制檔案剝離符號或除錯資訊。 +- [rpath:](https://doc.rust-lang.org/cargo/reference/profiles.html#rpath) 透過將資訊硬編碼到二進制檔案中,幫助找到二進制檔案所需的動態函式庫。 +- [trim-paths:](https://rust-lang.github.io/rfcs/3127-trim-paths.html) 從二進制檔案移除潛在的特權資訊。 +- [rustflags:](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#profile-rustflags-option) 在每個設定檔的基礎上設定 Rust 編譯器標誌。 + - `-Cdebuginfo=0`: 是否應在建置中包含除錯資訊符號。 + - `-Zthreads=8`: 增加編譯時使用的執行緒數。 \ No newline at end of file diff --git a/src/content/docs/zh-tw/develop/Debug/add-cargo-config-dark.png b/src/content/docs/zh-tw/develop/Debug/add-cargo-config-dark.png new file mode 100644 index 0000000000..d893e81f60 Binary files /dev/null and b/src/content/docs/zh-tw/develop/Debug/add-cargo-config-dark.png differ diff --git a/src/content/docs/zh-tw/develop/Debug/add-cargo-config-light.png b/src/content/docs/zh-tw/develop/Debug/add-cargo-config-light.png new file mode 100644 index 0000000000..afd0e6e031 Binary files /dev/null and b/src/content/docs/zh-tw/develop/Debug/add-cargo-config-light.png differ diff --git a/src/content/docs/zh-tw/develop/Debug/application.mdx b/src/content/docs/zh-tw/develop/Debug/application.mdx new file mode 100644 index 0000000000..320eb3e8f0 --- /dev/null +++ b/src/content/docs/zh-tw/develop/Debug/application.mdx @@ -0,0 +1,113 @@ +--- +title: 应用调试 +--- + +{/* TODO: REVISE COPY TO V2 */} +{/* TODO: Update links and internal navigation */} +{/* TODO: Revise this change: Application Debugging > Application Debug */} + +import CommandTabs from '@components/CommandTabs.astro'; + +在 Tauri 中的所有动态部分,您可能会遇到需要调试的问题。有很多位置会打印错误详细資訊,Tauri 还包含一些工具来简化调试过程。 + +## Rust 控制台 + +查找错误的第一个地方是 Rust 控制台。它位于您运行 `tauri dev` 等命令的终端中。您可以使用以下代码从 Rust 文件内部向该控制台打印内容: + +```rust +println!("来自 Rust 的資訊: {}", msg); +``` + +有时,您的 Rust 代码中可能存在错误,Rust 编译器可以为您提供大量資訊。例如,如果 `tauri dev` 崩溃,您可以在 Linux 和 macOS 上像这样重新运行它: + +```shell +RUST_BACKTRACE=1 tauri dev +``` + +或在 Windows 上像这样重新运行它: + +```shell +set RUST_BACKTRACE=1 +tauri dev +``` + +此命令为您提供了详细的堆栈跟踪。一般来说,Rust 编译器会通过为您提供有关该问题的大量資訊来帮助您,例如: + +```bash +error[E0425]: cannot find value `sun` in this scope + --> src/main.rs:11:5 + | +11 | sun += i.to_string().parse::().unwrap(); + | ^^^ help: a local variable with a similar name exists: `sum` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. +``` + +## WebView 控制台 + +在 WebView 中右键单击, 然后选择 `Inspect Element`. 这将打开一个类似于您熟悉的 Chrome 或 Firefox 开发工具的 Web 检查器。 +您还可以使用 Linux 和 Windows 上的 `Ctrl + Shift + i` 快捷键,以及macOS 上的 `Command + Option + i` 快捷键打开检查器. + +检查器是平台特定的,在 Linux 上使用 webkit2gtk 的 WebInspector,在 macOS 上使用 Safari 的检查器,在 Windows 上使用 Microsoft Edge DevTools。 + +### 通过程序打开 Devtools + +您可以使用 [`WebviewWindow::open_devtools`] 和 [`WebviewWindow::close_devtools`] 函数来控制检查器窗口的可见性: + +```rust +tauri::Builder::default() + .setup(|app| { + #[cfg(debug_assertions)] // 仅在调试构建时包含此代码 + { + let window = app.get_webview_window("main").unwrap(); + window.open_devtools(); + window.close_devtools(); + } + Ok(()) + }); +``` + +### 在生产中使用检查器 + +默认情况下,检查器只在开发和调试版本中启用,除非使用 Cargo 功能将其启用。 + +#### 创建调试构建 + +要创建调试构建,请运行 `tauri build --debug` 命令. + + + +与正常的构建和开发过程一样,首次运行此命令需要一些时间,但在后续运行中速度显著提高。 +最终打包的应用程序启用了开发控制台,并放置在 `src-tauri/target/debug/bundle` 中。 + +你还可以从终端运行已构建的应用程序,查看 Rust 编译器注释(在出错的情况下)或你的 `println` 資訊。浏览到 `src-tauri/target/(release|debug)/[应用程序名称]`文件,然后直接在控制台中运行,或双击文件系统中的可执行文件(注意:使用此方法时,控制台会在出错时关闭)。 + +##### 启用 Devtools 功能 + +:::danger + +在 macOS 上,开发工具 API 是私有的。在 macOS 上使用私有 API 会导致您的应用程序无法被 App Store 接受。 + +::: + +要在生产构建中启用 devtools,必须在 `src-tauri/Cargo.toml` 文件中启用 `devtools` Cargo 功能: + +```toml +[dependencies] +tauri = { version = "...", features = ["...", "devtools"] } +``` + +## 调试核心进程 + +核心进程由 Rust 支持,因此您可以使用 GDB 或 LLDB 进行调试。您可以按照[在 VS Code 中调试]指南学习如何使用 LLDB VS 代码扩展来调试 Tauri 应用程序的核心进程。 + +[在 VS Code 中调试]: /develop/debug/vscode/ +[`WebviewWindow::open_devtools`]: https://docs.rs/tauri/2.0.0/tauri/webview/struct.WebviewWindow.html#method.open_devtools +[`WebviewWindow::close_devtools`]: https://docs.rs/tauri/2.0.0/tauri/webview/struct.WebviewWindow.html#method.close_devtools diff --git a/src/content/docs/zh-tw/develop/Debug/debug-session-dark.png b/src/content/docs/zh-tw/develop/Debug/debug-session-dark.png new file mode 100644 index 0000000000..6435b3b491 Binary files /dev/null and b/src/content/docs/zh-tw/develop/Debug/debug-session-dark.png differ diff --git a/src/content/docs/zh-tw/develop/Debug/debug-session-light.png b/src/content/docs/zh-tw/develop/Debug/debug-session-light.png new file mode 100644 index 0000000000..a18032db29 Binary files /dev/null and b/src/content/docs/zh-tw/develop/Debug/debug-session-light.png differ diff --git a/src/content/docs/zh-tw/develop/Debug/index.mdx b/src/content/docs/zh-tw/develop/Debug/index.mdx new file mode 100644 index 0000000000..d30df91032 --- /dev/null +++ b/src/content/docs/zh-tw/develop/Debug/index.mdx @@ -0,0 +1,148 @@ +--- +title: 调试 +sidebar: + label: 概述 + order: 10 +i18nReady: true +--- + +import CommandTabs from '@components/CommandTabs.astro'; + +由于 Tauri 中的所有移动部分,您可能会遇到需要调试的问题。打印错误详细資訊的位置很多,Tauri 包含一些工具,使调试过程更加简单。 + +## 仅开发模式的代码 + +工具包中最有用的调试工具之一是能够在代码中新增调试语句。但是,您通常不希望这些程序最终进入生产环境,这就是检查您是否在开发模式下运行的功能派上用场的地方。 + +### 在 Rust 中 + +```rs frame=none +fn main() { + // 当前实例是否以 `tauri dev` 启动。 + #[cfg(dev)] + { + // 仅限 `tauri dev` 的代码 + } + if cfg!(dev) { + // 仅限 `tauri dev` 的代码 + } else { + // 仅限 `tauri build` 的代码 + } + let is_dev: bool = tauri::is_dev(); + + // 是否启用调试断言。对于 `tauri dev` 和 `tauri build --debug` 来说也是如此。 + #[cfg(debug_assertions)] + { + // 仅为调试代码 + } + if cfg!(debug_assertions) { + // 仅为调试代码 + } else { + // 仅为生产代码 + } +} + +``` + +{/* TODO: js version */} + +## Rust 控制台 + +查找错误的第一个位置是在 Rust 控制台中。这是在您运行的终端中,例如 `tauri dev`。您可以使用以下代码从 Rust 文件中将某些内容打印到该控制台: + +```rust frame=none +println!("Message from Rust: {}", msg); +``` + +有时你的 Rust 代码中可能有错误,而 Rust 编译器可以给你很多資訊。例如,如果 `tauri dev` 崩溃,您可以在 Linux 和 macOS 上像这样重新运行它: + +```shell frame=none +RUST_BACKTRACE=1 tauri dev +``` + +或在 Windows (PowerShell) 上如下所示: + +```powershell frame=none +$env:RUST_BACKTRACE=1 +tauri dev +``` + +此命令为您提供精细的堆栈跟踪。一般来说,Rust 编译器会为您提供有关问题的详细資訊,例如: + +```bash frame=none +error[E0425]: cannot find value `sun` in this scope + --> src/main.rs:11:5 + | +11 | sun += i.to_string().parse::().unwrap(); + | ^^^ help: a local variable with a similar name exists: `sum` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. +``` + +## WebView 控制台 + +右键单击 WebView,然后选择 `Inspect Element (检查元素)`。这将打开一个 web-inspector,类似于您习惯的 Chrome 或 Firefox 开发工具。 +您还可以在 Linux 和 Windows 上使用 `Ctrl + Shift + i` 快捷键,在 macOS 上使用 `Command + Option + i` 打开检查器。 + +该检查器是特定于平台的,在 Linux 上呈现 webkit2gtk WebInspector,在 macOS 上呈现 Safari 的检查器,在 Windows 上呈现 Microsoft Edge DevTools。 + +### 以编程方式打开 Devtools + +您可以使用 WebviewWindow:[`WebviewWindow::open_devtools`] 和 [`WebviewWindow::close_devtools`] 函数控制检查器窗口的可见性: + +```rust +tauri::Builder::default() + .setup(|app| { + #[cfg(debug_assertions)] // 仅在调试(debug)版本中包含此代码 + { + let window = app.get_webview_window("main").unwrap(); + window.open_devtools(); + window.close_devtools(); + } + Ok(()) + }); +``` + +### 在生产环境中使用 Inspector + +默认情况下,除非您使用 Cargo 功能启用它,否则 Inspector 仅在开发和调试版本中启用。 + +#### 创建调试产物 + +要创建调试版本产物,请运行 `tauri build --debug` 命令。 + + + +与正常的构建和开发过程一样,首次运行此命令时,构建需要一些时间,但在后续运行时要快得多。最终打包的应用程序启用了开发控制台,并放置在 `src-tauri/target/debug/bundle` 中。 + +您还可以从终端运行构建的应用程序,为您提供 Rust 编译器注释(以防出现错误)或 `println` 打印消息。浏览到该文件 `src-tauri/target/(release|debug)/[app name]` 并直接在控制台中运行它,或者双击文件系统中的可执行文件本身(注意:使用此方法时,控制台会关闭)。 + +##### 启用 Devtools 功能 + +:::danger + +devtools API 在 macOS 上是私有的。在 macOS 上使用私有 API 会阻止您的应用程序被 App Store 接受。 + +::: + +要在 **生产版本** 中启用 devtools,必须在 `src-tauri/Cargo.toml` 文件中启用 `devtools` Cargo 功能: + +```toml +[dependencies] +tauri = { version = "...", features = ["...", "devtools"] } +``` + +## 调试核心进程 + +Core 进程由 Rust 提供支持,因此您可以使用 GDB 或 LLDB 对其进行调试。您可以按照 [在 VS Code 调试] 指南了解如何使用 LLDB VS Code 扩展来调试 Tauri 应用程序的核心进程。 + +[在 VS Code 调试]: /zh-tw/develop/debug/vscode/ +[`WebviewWindow::open_devtools`]: https://docs.rs/tauri/2.0.0/tauri/webview/struct.WebviewWindow.html#method.open_devtools +[`WebviewWindow::close_devtools`]: https://docs.rs/tauri/2.0.0/tauri/webview/struct.WebviewWindow.html#method.close_devtools diff --git a/src/content/docs/zh-tw/develop/Debug/npm-configuration-dark.png b/src/content/docs/zh-tw/develop/Debug/npm-configuration-dark.png new file mode 100644 index 0000000000..00694aef6c Binary files /dev/null and b/src/content/docs/zh-tw/develop/Debug/npm-configuration-dark.png differ diff --git a/src/content/docs/zh-tw/develop/Debug/npm-configuration-light.png b/src/content/docs/zh-tw/develop/Debug/npm-configuration-light.png new file mode 100644 index 0000000000..45ce6f48c5 Binary files /dev/null and b/src/content/docs/zh-tw/develop/Debug/npm-configuration-light.png differ diff --git a/src/content/docs/zh-tw/develop/Debug/rename-configuration-dark.png b/src/content/docs/zh-tw/develop/Debug/rename-configuration-dark.png new file mode 100644 index 0000000000..aefb8e5ab3 Binary files /dev/null and b/src/content/docs/zh-tw/develop/Debug/rename-configuration-dark.png differ diff --git a/src/content/docs/zh-tw/develop/Debug/rename-configuration-light.png b/src/content/docs/zh-tw/develop/Debug/rename-configuration-light.png new file mode 100644 index 0000000000..f6fa58f839 Binary files /dev/null and b/src/content/docs/zh-tw/develop/Debug/rename-configuration-light.png differ diff --git a/src/content/docs/zh-tw/develop/Debug/rustrover.mdx b/src/content/docs/zh-tw/develop/Debug/rustrover.mdx new file mode 100644 index 0000000000..2cf982416c --- /dev/null +++ b/src/content/docs/zh-tw/develop/Debug/rustrover.mdx @@ -0,0 +1,82 @@ +--- +title: 在 JetBrains 的 IDE 中调试 +--- + +{/* TODO: Add support to light/dark mode images */} + +在本指南中,我们将通过设置 JetBrains RustRover 来调试[你的 Tauri 应用的核心进程](/zh-tw/concept/process-model/#核心进程)。这也基本适用于 IntelliJ 和 CLion 。 + +## 配置 Cargo 项目 + +根据项目所使用的前端技术栈,项目目录可能是也可能不是一个 Cargo 项目。默认情况下,Tauri 会将 Rust 项目放在名为 `src-tauri` 的子目录中。仅当 Rust 也用于前端开发时,它才会在根目录下创建一个 Cargo 项目。 + +如果顶层没有 `Cargo.toml` 文件,你需要手动将它新增到项目中。打开 Cargo 工具窗口(在主菜单中,转到**视图 | 工具窗口 | Cargo**),点击工具栏上的 **+** (**附加 Cargo 项目**),并选择 `src-tauri/Cargo.toml` 文件。 + +或者,你可以通过将以下文件新增到项目根目录下来手动创建一个顶层 Cargo 工作区: + +```toml title=Cargo.toml +[workspace] +members = ["src-tauri"] +``` + +在继续之前,确保你的项目已加载完成。如果 Cargo 工具窗口显示了工作区的所有模块和目标,那么就可以开始了。 + +## 设置运行配置 + +你需要设置两个单独的运行/调试配置: + +- 一个用于在调试模式下启动 Tauri 应用, +- 另一个用于运行你选择的前端开发服务器。 + +### Tauri 应用 + +1. 在主菜单中,转到**运行 | 编辑配置**。 +2. 在**运行/调试配置**对话框中: + +- 要创建一个新配置,点击工具栏上的 **+** 并选择 **Cargo**。 + +![新增运行/调试配置](./add-cargo-config-light.png) +{/* ![新增运行/调试配置](./add-cargo-config-dark.png#gh-dark-mode-only) */} + +在创建完成后,我们需要配置 RustRover ,所以它会在没有任何默认特性的情况下指示 Cargo 来构建我们的应用。这会告诉 Tauri 使用你的开发服务器而不是从磁盘上读取到的资产。通常,这个标志是通过 Tauri CLI 来传递的,但由于我们这里完全避开了它,我们需要手动传递这个标志。 + +![新增 `--no-default-features` 标志](./set-no-default-features-light.png) +{/* ![新增 `--no-default-features` 标志](./set-no-default-features-dark.png#gh-dark-mode-only) */} + +现在,我们可以选择性地将运行或调试的配置重命名为某个更容易记住的名称,在这个例子中,我们将其命名为 "Run Tauri App",但你也可以任意命名。 + +![重命名配置](./rename-configuration-light.png) +{/* ![重命名配置](./rename-configuration-dark.png#gh-dark-mode-only) */} + +### 开发服务器 + +以上配置会使用 Cargo 来直接构建 Rust 应用,并将调试器附加到上面。这意味着我们完全避开了 Tauri CLI ,所以像 `beforeDevCommand` 和 `beforeBuildCommand` 这类的特性都**不会**被执行。我们需要手动运行开发服务器来解决。 + +要创建相应的运行配置,你需要检查实际使用的开发服务器。找到 `src-tauri/tauri.conf.json` 文件,并查找以下行: + +```json + "beforeDevCommand": "pnpm dev" +``` + +对于 `npm`、`pnpm` 或是 `yarn` ,你可以使用 **npm** 运行配置,例如: + +![NPM 配置](./npm-configuration-light.png) +{/* ![NPM 配置](./npm-configuration-dark.png#gh-dark-mode-only) */} + +确保你的**命令**、**脚本**和**软件包管理器**中字段的值都是正确的。 + +如果你的开发服务器是基于 Rust 的 WebAssembly 前端框架的 `trunk`,你可以使用通用的 **Shell Script** 运行配置: + +![Trunk 服务配置](./trunk-configuration-light.png) +{/* ![Trunk 服务配置](./trunk-configuration-dark.png#gh-dark-mode-only) */} + +## 启动调试会话 + +要启动调试会话,首先需要运行你的开发服务器,然后通过点击位于运行配置切换器旁边的**调试**按钮来启动 Tauri 应用调试。RustRover 会自动识别出项目中任何 Rust 文件中的断点,并在第一个命中的断点处停下。 + +![调试会话](./debug-session-light.png) +{/* ![调试会话](./debug-session-dark.png#gh-dark-mode-only) */} + +从这里开始,你可以浏览变量的值,进一步地步入到代码中,并详细检查运行时的情况。 + +[你的 tauri 应用的核心进程]: ../../../../concept/process-model#the-core-process diff --git a/src/content/docs/zh-tw/develop/Debug/set-no-default-features-dark.png b/src/content/docs/zh-tw/develop/Debug/set-no-default-features-dark.png new file mode 100644 index 0000000000..d83067cb58 Binary files /dev/null and b/src/content/docs/zh-tw/develop/Debug/set-no-default-features-dark.png differ diff --git a/src/content/docs/zh-tw/develop/Debug/set-no-default-features-light.png b/src/content/docs/zh-tw/develop/Debug/set-no-default-features-light.png new file mode 100644 index 0000000000..c8f90aacea Binary files /dev/null and b/src/content/docs/zh-tw/develop/Debug/set-no-default-features-light.png differ diff --git a/src/content/docs/zh-tw/develop/Debug/trunk-configuration-dark.png b/src/content/docs/zh-tw/develop/Debug/trunk-configuration-dark.png new file mode 100644 index 0000000000..b6d15ba30d Binary files /dev/null and b/src/content/docs/zh-tw/develop/Debug/trunk-configuration-dark.png differ diff --git a/src/content/docs/zh-tw/develop/Debug/trunk-configuration-light.png b/src/content/docs/zh-tw/develop/Debug/trunk-configuration-light.png new file mode 100644 index 0000000000..986fc45af7 Binary files /dev/null and b/src/content/docs/zh-tw/develop/Debug/trunk-configuration-light.png differ diff --git a/src/content/docs/zh-tw/develop/Debug/vscode.mdx b/src/content/docs/zh-tw/develop/Debug/vscode.mdx new file mode 100644 index 0000000000..b3d4e4d5d0 --- /dev/null +++ b/src/content/docs/zh-tw/develop/Debug/vscode.mdx @@ -0,0 +1,154 @@ +--- +title: 在 VS Code 中调试 +--- + +本指南将指导您设置 VS 代码,以调试 [Tauri 应用的核心流程](https://tauri.app/v1/reference/architecture/process-model#the-core-process)。 + +## 所有具有 vscode-lldb 扩展的平台 + +### 先决条件 + +安装 [`vscode-lldb`] 扩展。 + +[`vscode-lldb`]: https://marketplace.visualstudio.com/items?itemName=vadimcn.vscode-lldb + +### 配置 launch.json + +创建一个 `.vscode/launch.json` 文件,并将下面的 JSON 内容粘贴到其中: + +```json title=".vscode/launch.json" +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "lldb", + "request": "launch", + "name": "Tauri Development Debug", + "cargo": { + "args": [ + "build", + "--manifest-path=./src-tauri/Cargo.toml", + "--no-default-features" + ] + }, + // task for the `beforeDevCommand` if used, must be configured in `.vscode/tasks.json` + "preLaunchTask": "ui:dev" + }, + { + "type": "lldb", + "request": "launch", + "name": "Tauri Production Debug", + "cargo": { + "args": ["build", "--release", "--manifest-path=./src-tauri/Cargo.toml"] + }, + // task for the `beforeBuildCommand` if used, must be configured in `.vscode/tasks.json` + "preLaunchTask": "ui:build" + } + ] +} +``` + +它直接使用 `cargo` 来构建 Rust 应用程序,并在开发和生产模式下加载它。 + +请注意,它不使用 Tauri CLI,因此不会执行独有的 CLI 功能。`beforeDevCommand` 和 `beforeBuildCommand` 脚本必须事先执行,或在 `preLaunchTask` 字段中配置为任务。下面是一个 `.vscode/tasks.json` 文件示例,其中有两个任务,一个是生成开发服务器的 `beforeDevCommand` 任务,另一个是 `beforeBuildCommand` 任务: + +```json title=".vscode/tasks.json" +{ + // See https://go.microsoft.com/fwlink/?LinkId=733558 + // for the documentation about the tasks.json format + "version": "2.0.0", + "tasks": [ + { + "label": "ui:dev", + "type": "shell", + // `dev` keeps running in the background + // ideally you should also configure a `problemMatcher` + // see https://code.visualstudio.com/docs/editor/tasks#_can-a-background-task-be-used-as-a-prelaunchtask-in-launchjson + "isBackground": true, + // change this to your `beforeDevCommand`: + "command": "yarn", + "args": ["dev"] + }, + { + "label": "ui:build", + "type": "shell", + // change this to your `beforeBuildCommand`: + "command": "yarn", + "args": ["build"] + } + ] +} +``` + +现在,你可以在 `src-tauri/src/main.rs` 或任何其他 Rust 文件中设置断点,并按下 `F5` 开始调试。 + +## 在 Windows 上使用 Visual Studio Windows 调试器 + +Visual Studio Windows Debugger 是一个仅适用于 Windows 的调试器,通常比 [`vscode-lldb`] 更快,并且对一些 Rust 特性(如枚举)提供更好的支持。 + +### 先决条件 + +安装 [C/C++](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools) 扩展,并按照 https://code.visualstudio.com/docs/cpp/config-msvc#_prerequisites 中的步骤安装 Visual Studio Windows 调试器。 + +### 配置 launch.json 和 tasks.json + +```json title=".vscode/launch.json" +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Launch App Debug", + "type": "cppvsdbg", + "request": "launch", + // change the exe name to your actual exe name + // (to debug release builds, change `target/debug` to `release/debug`) + "program": "${workspaceRoot}/src-tauri/target/debug/your-app-name-here.exe", + "cwd": "${workspaceRoot}", + "preLaunchTask": "ui:dev" + } + ] +} +``` + +请注意,它不使用 Tauri CLI,因此独占的 CLI 功能不会被执行。`tasks.json` 与 `lldb` 相同,只是如果您希望在启动之前始终进行编译,则需要新增一个配置组,并将其 `launch.json` 中的 `preLaunchTask` 指向它。 + +这是一个运行开发服务器(相当于 `beforeDevCommand`)和编译(`cargo build`)作为一组的示例,要使用它,请将 `launch.json` 中的 `preLaunchTask` 配置更改为 `dev`(或任何你命名的组)。 + +```json title=".vscode/tasks.json" +{ + // See https://go.microsoft.com/fwlink/?LinkId=733558 + // for the documentation about the tasks.json format + "version": "2.0.0", + "tasks": [ + { + "label": "build:debug", + "type": "cargo", + "command": "build" + }, + { + "label": "ui:dev", + "type": "shell", + // `dev` keeps running in the background + // ideally you should also configure a `problemMatcher` + // see https://code.visualstudio.com/docs/editor/tasks#_can-a-background-task-be-used-as-a-prelaunchtask-in-launchjson + "isBackground": true, + // change this to your `beforeDevCommand`: + "command": "yarn", + "args": ["dev"] + }, + { + "label": "dev", + "dependsOn": ["build:debug", "ui:dev"], + "group": { + "kind": "build" + } + } + ] +} +``` diff --git a/src/content/docs/zh-tw/develop/Plugins/develop-mobile.mdx b/src/content/docs/zh-tw/develop/Plugins/develop-mobile.mdx new file mode 100644 index 0000000000..23c46be801 --- /dev/null +++ b/src/content/docs/zh-tw/develop/Plugins/develop-mobile.mdx @@ -0,0 +1,381 @@ +--- +title: 移动端外掛开发 +i18nReady: true +--- + +:::tip[外掛开发] + +确保你已经熟悉[外掛开发](/zh-tw/develop/plugins/)中的概念,因为本指南大量使用基于那篇文章的概念。 + +::: + +外掛可以运行用 Kotlin(或 Java)和 Swift 编写的本地代码。 +默认外掛模板包括一个使用 Kotlin 的安卓库项目和一个 Swift 包,其中包括一个示例指令,展示如何从 Rust 代码调用外部外掛。 + +## 初始化外掛项目 + +按照[外掛开发](/zh-tw/develop/plugins/#初始化外掛项目)中的步骤初始化新的外掛项目。 + +如果你有一个现有的外掛,并且想新增安卓或 iOS 的功能,你可以使用 `plugin android init` 和 `plugin ios init`来新增构建移动端外掛项目,并指导你完成所需的更改。 + +默认的外掛模板将外掛的实现分为两个独立的模块:`desktop.rs` 和 `mobile.rs`。 + +桌面实现使用 Rust 代码来实现功能,而移动端实现会向本地移动端代码库发送消息以执行功能并返回结果。如果两个实现存在共享逻辑,可以在 `lib.rs` 中定义: + +```rust +// lib.rs +use tauri::Runtime; + +impl { + pub fn do_something(&self) { + // 一些桌面和移动设备之间共享的实现 + } +} +``` + +这一实现简化了共享 API 的过程,该 API 可被指令和 Rust 代码使用。 + +### 开发一个安卓外掛 + +一个安卓 Tauri 外掛的定义为一个扩展了 `app.tauri.plugin.Plugin` 并具有 `app.tauri.annotation.TauriPlugin` 注解的 Kotlin 类。每个有 `app.tauri.annotation.Command` 注解的方法都可以被 Rust 或 JavaScript 调用。 + +Tauri 使用 Kotlin 作为默认的安卓外掛实现,但是你也可以使用 Java 作为替代。在创建一个外掛后,在 Android Studio 中右键 Kotlin 外掛类并点击菜单中的 ”将 Kotlin 文件转换为 Java 文件“ 按钮。Anroid Studio 会指导你完成到 Java 项目的迁移。 + +### 开发一个 iOS 外掛 + +一个 iOS Tauri 外掛由一个扩展了 `Tauri` 包的 `Plugin` 类定义。每个具有 `@objc` 属性和 `(_ invode: Invoke)` 参数的函数(例如 `@objc private func download(_ invoke: Invoke) { }`)都可以被 Rust 或 JavaScript 调用。 + +外掛被定义为一个 [Swift 包](https://www.swift.org/package-manager/),因此你可以使用它的包管理器以管理依赖 + +## 外掛配置 + +前往外掛开发指南的[外掛配置](/zh-tw/develop/plugins/#外掛配置)章节以获取更多关于外掛开发的配置資訊。 + +移动设备上的外掛实例具有用于外掛配置的获取器: + + + + +```kotlin +@TauriPlugin +class ExamplePlugin(private val activity: Activity): Plugin(activity) { + override fun load(webView: WebView) { + val timeout = this.config.getInt("timeout", 30) + } +} +``` + + + + +```swift +class ExamplePlugin: Plugin { + @objc public override func load(webview: WKWebView) { + let timeout = self.config["timeout"] as? Int ?? 30 + } +} +``` + + + + +## 生命周期事件 + +外掛可以连接到几个生命周期事件中: + +- [`load`](#load):当外掛被加载到 webview 中时触发 +- [`onNewIntent`](#onnewintent):(仅安卓)当活动被重启时触发 + +在外掛开发指南中还有一些其他[外掛生命周期事件](/zh-tw/develop/plugins/#生命周期事件)的介绍。 + +### `load` + +- **当**:外掛被加载到 webview 中 +- **为了**:加载外掛初始化代码 + + + + +```kotlin +@TauriPlugin +class ExamplePlugin(private val activity: Activity): Plugin(activity) { + override fun load(webView: WebView) { + // 在这里启动外掛 + } +} +``` + + + + +```swift +class ExamplePlugin: Plugin { + @objc public override func load(webview: WKWebView) { + let timeout = self.config["timeout"] as? Int ?? 30 + } +} +``` + + + + +### `onNewIntent` + +**备注**:这只在安卓系统上有效。 + +- **当**:活动项目重启。查阅 [Activity#`onNewIntent`]() 以获取更多資訊。 +- **为了**:处理活动重启,例如通知被点击或者深链接被使用。 + +```kotlin +// import android.content.Intent + +@TauriPlugin +class ExamplePlugin(private val activity: Activity): Plugin(activity) { + override fun onNewIntent(intent: Intent) { + // 处理重启事件 + } +} +``` + +## 新增移动端命令 + +在相应的移动端项目中有一个外掛类,可以在其中定义能够通过 Rust 代码调用的命令: + +import { Tabs, TabItem } from '@astrojs/starlight/components'; + + + + +```kotlin +@TauriPlugin +class ExamplePlugin(private val activity: Activity): Plugin(activity) { + @Command + fun openCamera(invoke: Invoke) { + val allowEdit = invoke.getBoolean("allowEdit", false) + val quality = invoke.getInt("quality", 100) + + val ret = JSObject() + ret.put("path", "/path/to/photo.jpg") + invoke.resolve(ret) + } +} +``` + + + + +```swift +class ExamplePlugin: Plugin { + @objc public func openCamera(_ invoke: Invoke) { + let allowEdit = invoke.getBool("allowEdit", false) + let quality = invoke.getInt("quality", 100) + + invoke.resolve(["path": "/path/to/photo.jpg"]) + } +} +``` + + + + +使用 [`tauri::plugin::PluginHandle`](https://docs.rs/tauri/2.0.0/tauri/plugin/struct.PluginHandle.html) 以在 Rust 中创建一个移动端命令: + +```rust +use std::path::PathBuf; +use serde::{Deserialize, Serialize}; +use tauri::Runtime; + +#[derive(Serialize)] +#[serde(rename_all = "camelCase")] +pub struct CameraRequest { + quality: usize, + allow_edit: bool, +} + +#[derive(Deserialize)] +pub struct Photo { + path: PathBuf, +} + + +impl { + pub fn open_camera(&self, payload: CameraRequest) -> crate::Result { + self + .0 + .run_mobile_plugin("openCamera", payload) + .map_err(Into::into) + } +} +``` + +## 权限许可 + +如果外掛需要最终用户的权限,Tauri 简化了检查和请求权限的过程。 + + + + +首先定义所需权限的列表和别名,以在代码中标识每个权限组。这是在 `TauriPlugin` 注解中完成的: + +```kotlin +@TauriPlugin( + permissions = [ + Permission(strings = [Manifest.permission.POST_NOTIFICATIONS], alias = "postNotification") + ] +) +class ExamplePlugin(private val activity: Activity): Plugin(activity) { } +``` + + + + +首先重写 `checkPermissions` 和 `requestPermissions` 方法: + +```swift +class ExamplePlugin: Plugin { + @objc open func checkPermissions(_ invoke: Invoke) { + invoke.resolve(["postNotification": "prompt"]) + } + + @objc public override func requestPermissions(_ invoke: Invoke) { + // 在这里配置权限许可 + // 然后解决请求 + invoke.resolve(["postNotification": "granted"]) + } +} +``` + + + + +Tauri 自动为外掛实现了两个命令:`checkPermissions` 和 `requestPermissions`。这些命令可以从 JavaScript 或 Rust 中直接调用。 + + + + +```javascript +import { invoke, PermissionState } from '@tauri-apps/api/core' + +interface Permissions { + postNotification: PermissionState +} + +// 查询权限许可状态 +const permission = await invoke('plugin:|checkPermissions') + +if (permission.postNotification === 'prompt-with-rationale') { + // 告诉用户为什么需要权限 +} + +// 请求权限 +if (permission.postNotification.startsWith('prompt')) { + const state = await invoke('plugin:|requestPermissions', { permissions: ['postNotification'] }) +} +``` + + + + +```rust +use serde::{Serialize, Deserialize}; +use tauri::{plugin::PermissionState, Runtime}; + +#[derive(Deserialize)] +#[serde(rename_all = "camelCase")] +struct PermissionResponse { + pub post_notification: PermissionState, +} + +#[derive(Serialize)] +#[serde(rename_all = "camelCase")] +struct RequestPermission { + post_notification: bool, +} + +impl Notification { + pub fn request_post_notification_permission(&self) -> crate::Result { + self.0 + .run_mobile_plugin::("requestPermissions", RequestPermission { post_notification: true }) + .map(|r| r.post_notification) + .map_err(Into::into) + } + + pub fn check_permissions(&self) -> crate::Result { + self.0 + .run_mobile_plugin::("checkPermissions", ()) + .map_err(Into::into) + } +} +``` + + + + +## 外掛事件 + +{/* TODO: Is this section a duplicate of Lifecycle Events above? */} + +外掛可以使用 `trigger` 函数在任何时候触发事件: + + + + +```kotlin +@TauriPlugin +class ExamplePlugin(private val activity: Activity): Plugin(activity) { + override fun load(webView: WebView) { + trigger("load", JSObject()) + } + + override fun onNewIntent(intent: Intent) { + // 处理新意图 + if (intent.action == Intent.ACTION_VIEW) { + val data = intent.data.toString() + val event = JSObject() + event.put("data", data) + trigger("newIntent", event) + } + } + + @Command + fun openCamera(invoke: Invoke) { + val payload = JSObject() + payload.put("open", true) + trigger("camera", payload) + } +} +``` + + + + +```swift +class ExamplePlugin: Plugin { + @objc public override func load(webview: WKWebView) { + trigger("load", data: [:]) + } + + @objc public func openCamera(_ invoke: Invoke) { + trigger("camera", data: ["open": true]) + } +} +``` + + + + +辅助函数可以通过使用 [`addPluginListener`](/zh-tw/reference/javascript/api/namespacecore/#addpluginlistener) 函数在 NPM 包中找到并使用。 + +```javascript +import { addPluginListener, PluginListener } from '@tauri-apps/api/tauri'; + +export async function onRequest( + handler: (url: string) => void +): Promise { + return await addPluginListener( + '', + 'event-name', + handler + ); +} +``` diff --git a/src/content/docs/zh-tw/develop/Plugins/index.mdx b/src/content/docs/zh-tw/develop/Plugins/index.mdx new file mode 100644 index 0000000000..07471e5cc4 --- /dev/null +++ b/src/content/docs/zh-tw/develop/Plugins/index.mdx @@ -0,0 +1,469 @@ +--- +title: 外掛开发 +i18nReady: true +sidebar: + label: Overview + order: 10 +--- + +{/* TODO: Add a CLI section */} + +import CommandTabs from '@components/CommandTabs.astro'; + +{/* TODO: Link to windowing system, commands for sending messages, and event system */} + +:::tip[外掛开发] + +这个指南是用于指导开发 Tauri 外掛。如果你想要寻找关于当前可用的外掛的列表及其使用说明,请前往[功能及秘诀列表](/zh-tw/plugin/)。 + +::: + +外掛可以挂载到 Tauri 的生命周期中,暴露需求 webview API 的 Rust 代码,使用 Rust、Kotlin 或 Swift 代码处理命令并能处理更多需求。 + +Tauri 提供了一个基于 webview 功能的视窗系统,一个在 Rust 进程和 webview 之间发送資訊的方式,一个事件系统,以及一些增强开发体验的工具。 +设计上 Tauri Core 只包含所有人都需要的功能。相对地,它提供了一种将外部功能新增到 Tauri 应用程序中的机制,被称为外掛。 + +一个 Tauri 外掛由一个 Cargo 包和一个可选的 NPM 包(用于提供命令和事件 API 绑定)构成。 +同时,一个外掛项目可以包含一个 Android 库项目和/或一个用于 iOS 的 Swift 包。 +你可以查阅[移动端外掛开发指南](/zh-tw/develop/plugins/develop-mobile/)以获取更多关于开发安卓或 iOS 外掛的資訊。 + +{/* TODO: https://github.com/tauri-apps/tauri/issues/7749 */} + +## 命名规范 + +{/* TODO: Add link to allowlist */} + +Tauri 外掛具有一个前缀(Rust 包使用 `tauri-plugin-` 前缀,NPM 包使用 `@tauri-apps/plugin-` 前缀),随后是外掛名称。 +外掛名称由外掛配置中的 [`tauri.conf.json > plugin`](/zh-tw/reference/config/#pluginconfig) 和许可列表中的配置确定。 + +默认情况下,Tauri 会在你的外掛 crate 前面加上 `tauri-plugin-`。这有助于你的外掛被 Tauri 社区发现,但不是必须的。初始化新外掛项目时,必须提供其名称。生成包名称将为 `tauri-plugin-{plugin-name}`,JavaScript NPM 包名称为 `tauri-plugin-{plugin-name}-api`(尽管我们建议使用 [NPM 范围](https://docs.npmjs.com/about-scopes)如果可能的话)。NPM 包的 Tauri 命名约定是 `@scope-name/plugin-{plugin-name}`。 + +## 初始化外掛项目 + +使用引导创建一个新的外掛项目,请运行 `plugin new`。如果不需要相应的 NPM 程序包,请使用 `--no-api` 命令行标志。如果你想要初始化一个支持 Android 和/或 iOS 的外掛,请使用 `--android` 和/或 `--ios` 命令行标志。 + +完成安装后,你可以运行下列指令来创建一个外掛: + + + +这会在 `tauri-plugin-[name]` 目录下初始化外掛,取决于初始化外掛时所选择的命令行标志,项目将具有以下结构: + +``` +. tauri-plugin-[name]/ +├── src/ - Rust 代码 +│ ├── commands.rs - 定义 webview 可用的命令 +| ├── desktop.rs - 桌面实现 +| ├── error.rs - 用于返回 results 的默认的错误类型 +│ ├── lib.rs - 重新导出适当的实现、设置状态…… +│ ├── mobile.rs - 移动端实现 +│ └── models.rs - 公共的结构体 +├── permissions/ - 这将托管(生成的)命令的权限文件 +├── android - 安卓库 +├── ios - Swift 包 +├── guest-js - JavaScript API 绑定的源代码 +├── dist-js - 从 guest-js 转译的资源 +├── Cargo.toml - Cargo 包元数据 +└── package.json - NPM 包元数据 +``` + +如果你有一个现有的外掛,并且想新增 Android 或 iOS 功能,你可以使用 `plugin android add` 和 `plugin ios add` 来引导移动端库项目,并指导你完成所需的更改。 + +## 移动端外掛开发 + +外掛可以运行用 Kotlin(或 Java)和 Swift 编写的本地移动代码。默认的外掛模板包括一个使用 Kotlin 的 Android 库项目和一个 Swift 包。它包括一个示例移动端命令,展示了如何从 Rust 代码触发其执行。 + +在[移动端外掛开发指南](/zh-tw/develop/plugins/develop-mobile/)中阅读更多关于开发移动端外掛的資訊。 + +## 外掛配置 + +在使用外掛的 Tauri 应用中,外掛配置由 `tauri.conf.json` 中的 `plugin-name` 项配置(其中 `plugin-name` 表示你的外掛的名称): + +```json +{ + "build": { ... }, + "tauri": { ... }, + "plugins": { + "plugin-name": { + "timeout": 30 + } + } +} +``` + +外掛的配置是在 `Builder` 上设置的,并在运行时进行解析。以下是用于指定外掛配置的 `Config` 结构体的示例: + +```rust title="src/lib.rs" +use tauri::plugin::{Builder, Runtime, TauriPlugin}; +use serde::Deserialize; + +// 定义外掛配置 +#[derive(Deserialize)] +struct Config { + timeout: usize, +} + +pub fn init() -> TauriPlugin { + // 如果想要使外掛可选,请使用 `Builder::>` 替换 + Builder::::new("") + .setup(|app, api| { + let timeout = api.config.timeout; + Ok(()) + }) + .build() +} +``` + +## 生命周期事件 + +外掛可以挂载到如下生命周期事件中: + +- [`setup`](#setup): 外掛初始化 +- [`on_navigation`](#on_navigation): Webview 将要触发导航时 +- [`on_webview_ready`](#on_webview_ready): 新窗口创建时 +- [`on_event`](#on_event): 事件循环 +- [`on_drop`](#on_drop): 外掛被析构时 + +还有一些特定的[移动端外掛生命周期事件](/zh-tw/develop/plugins/develop-mobile/#生命周期事件)。 + +### `setup` + +- **当**:外掛被初始化时 +- **为了**:注册移动端外掛、管理状态、运行背景任务 + +```rust title="src/lib.rs" +use tauri::{Manager, plugin::Builder}; +use std::{collections::HashMap, sync::Mutex, time::Duration}; + +struct DummyStore(Mutex>); + +Builder::new("") + .setup(|app, api| { + app.manage(DummyStore(Default::default())); + + let app_ = app.clone(); + std::thread::spawn(move || { + loop { + app_.emit("tick", ()); + std::thread::sleep(Duration::from_secs(1)); + } + }); + + Ok(()) + }) +``` + +### `on_navigation` + +- **当**:Webview 尝试导航时 +- **为了**:验证导航或跟随 URL 变化 + +返回 `false` 将会取消导航。 + +```rust title="src/lib.rs" +use tauri::plugin::Builder; + +Builder::new("") + .on_navigation(|window, url| { + println!("window {} is navigating to {}", window.label(), url); + // 如果被禁止,取消导航 + url.scheme() != "forbidden" + }) +``` + +### `on_webview_ready` + +- **当**:新窗口被创建时 +- **为了**:对每个窗口运行初始化命令 + +```rust title="src/lib.rs" +use tauri::plugin::Builder; + +Builder::new("") + .on_webview_ready(|window| { + window.listen("content-loaded", |event| { + println!("webview content has been loaded"); + }); + }) +``` + +### `on_event` + +- **当**:触发事件循环事件 +- **为了**:管理核心事件,例如窗口事件、菜单事件和应用退出请求 + +在这个生命周期钩子中,你会被任何[事件循环事件](https://docs.rs/tauri/2.0.0/tauri/enum.RunEvent.html)通知。 + +```rust title="src/lib.rs" +use std::{collections::HashMap, fs::write, sync::Mutex}; +use tauri::{plugin::Builder, Manager, RunEvent}; + +struct DummyStore(Mutex>); + +Builder::new("") + .setup(|app, _api| { + app.manage(DummyStore(Default::default())); + Ok(()) + }) + .on_event(|app, event| { + match event { + RunEvent::ExitRequested { api, .. } => { + // 用户请求关闭一个窗口,但没有剩余的窗口 + + // 我们可以阻止应用程序退出 + api.prevent_exit(); + } + RunEvent::Exit => { + // 应用程序将退出,你可以在此处进行清理 + + let store = app.state::(); + write( + app.path().app_local_data_dir().unwrap().join("store.json"), + serde_json::to_string(&*store.0.lock().unwrap()).unwrap(), + ) + .unwrap(); + } + _ => {} + } + }) +``` + +### `on_drop` + +- **当**:外掛将被析构时 +- **为了**:在外掛被消除时运行代码 + +查看 [`rust-std Drop`](https://doc.rust-lang.org/std/ops/trait.Drop.html) 以获取更多資訊。 + +```rust title="src/lib.rs" +use tauri::plugin::Builder; + +Builder::new("") + .on_drop(|app| { + // 外掛将要被销毁 + }) +``` + +## 暴露 Rust API + +在项目的 `desktop.rs` 和 `mobile.rs` 中定义的外掛 API 将作为与外掛同名的结构体导出给用户(使用 Pascal 命名法)。 +设置外掛时,会创建此结构体的实例并将其作为一种状态进行管理,以便用户可以通过外掛中定义的扩展特性,在任何时间点使用 `Manager` 实例(如 `AppHandle`、`App` 或 `Window`)检索它。 + +例如,[`global-shortcut` 外掛](/zh-tw/plugin/global-shortcut/) 定义了一个 `GlobalShortcut` 结构体,可以被 `GlobalShortcutExt` trait 的 `global_shortcut` 方法使用: + +```rust title="src-tauri/src/lib.rs" +use tauri_plugin_global_shortcut::GlobalShortcutExt; + +tauri::Builder::default() + .plugin(tauri_plugin_global_shortcut::init()) + .setup(|app| { + app.global_shortcut().register(...); + Ok(()) + }) +``` + +## 新增命令 + +命令在 `command.rs` 文件中定义。它们是常规的 Tauri 应用程序命令。它们可以直接访问 `AppHandle` 和 `Window` 实例,获取状态,并以与应用命令同样的方式获取输入。 +阅读[命令指南](/zh-tw/develop/calling-rust/)以获取更多关于 Tauri 命令的資訊。 + +这个命令展示了如何使用依赖注入访问 `AppHandle` 和 `Window` 实例,并接受两个输入参数(`on_progress` 和 `url`): + +```rust title="src/commands.rs" +use tauri::{command, ipc::Channel, AppHandle, Runtime, Window}; + +#[command] +async fn upload(app: AppHandle, window: Window, on_progress: Channel, url: String) { + // 在这里实现命令逻辑 + on_progress.send(100).unwrap(); +} +``` + +为了将命令暴露给 webview,你需要在 `lib.rs` 中将命令挂载到 `invoke_handler()` 中: + +```rust title="src/lib.rs" +Builder::new("") + .invoke_handler(tauri::generate_handler![commands::upload]) +``` + +在 `webview-src/index.ts` 中定义一个绑定函数,然后外掛用户就可以轻松地在 JavaScript 中调用这个命令: + +```js name="webview-src/index.ts" +import { invoke, Channel } from '@tauri-apps/api/tauri' + +export async function upload(url: string, onProgressHandler: (progress: number) => void): Promise { + const onProgress = new Channel() + onProgress.onmessage = onProgressHandler + await invoke('plugin:|upload', { url, onProgress }) +} +``` + +确保在测试 TypeScript 代码之前先构建它。 + +### 命令权限 + +默认情况下,前端无法访问您的命令。如果您尝试执行其中之一,您将收到拒绝错误拒绝。 +要实际暴露命令,您还需要定义允许每个命令的权限。 + +#### 权限文件 + +权限被定义在 `permissions` 目录下的 JSON 或 TOML 文件种。每个文件都可以定义一系列的权限、权限集和外掛的默认权限。 + +##### 权限 + +权限描述了您的外掛命令的权限。它可以允许或拒绝命令列表并将特定命令和全局范围关联起来。 + +```toml title="permissions/start-server.toml" +"$schema" = "schemas/schema.json" + +[[permission]] +identifier = "allow-start-server" +description = "Enables the start_server command." +commands.allow = ["start_server"] + +[[permission]] +identifier = "deny-start-server" +description = "Denies the start_server command." +commands.deny = ["start_server"] +``` + +##### 范围 + +范围允许您的外掛对各个命令定义更深层次的限制。 +每个权限文件都可以定义一些范围对象的列表,这些对象定义特定的命令或全局外掛所允许或拒绝的内容。 + +让我们定义一个示例结构,它将保存允许 `shell` 外掛生成的二进制文件列表的范围数据: + +```rust title="src/scope.rs" +#[derive(Debug, schemars::JsonSchema)] +pub struct Entry { + pub binary: String, +} +``` + +###### 命令范围 + +您的外掛使用者可以在其功能文件中定义特定命令的范围(请参阅[文档](/zh-tw/reference/acl/scope/))。 +您可以使用 [`tauri::ipc::CommandScope`](https://docs.rs/tauri/2.0.0-beta/tauri/ipc/struct.CommandScope.html) 结构体读取特定命令的范围: + +```rust title="src/commands.rs" +use tauri::ipc::CommandScope; +use crate::scope::Entry; + +async fn spawn(app: tauri::AppHandle, command_scope: CommandScope<'_, Entry>) -> Result<()> { + let allowed = command_scope.allows(); + let denied = command_scope.denies(); + todo!() +} +``` + +###### 全局范围 + +当权限文件没有定义任何允许或拒绝权限的命令时,它被视为范围权限,并且它将为您的外掛定义全局范围: + +```toml title="permissions/spawn-node.toml" +[[permission]] +identifier = "allow-spawn-node" +description = "This scope permits spawning the `node` binary." + +[[permission.scope.allow]] +binary = "node" +``` + +你可以使用 [`tauri::ipc::GlobalScope`](https://docs.rs/tauri/2.0.0-beta/tauri/ipc/struct.GlobalScope.html) 结构体来获取全局范围的命令: + +```rust title="src/commands.rs" +use tauri::ipc::GlobalScope; +use crate::scope::Entry; + +async fn spawn(app: tauri::AppHandle, scope: GlobalScope<'_, Entry>) -> Result<()> { + let allowed = scope.allows(); + let denied = scope.denies(); + todo!() +} +``` + +:::note +我们建议检查全局和命令范围以获得灵活性 +::: + +###### Schema + +范围条目需要 `schemars` 依赖项来生成 JSON 模式,以便外掛使用者知道范围的格式并在其 IDE 中自动完成。 + +要定义模式,首先将依赖项新增到 Cargo.toml 文件中: + +```toml +# 我们需要将模式新增到依赖项和构建依赖项中, +# 因为 scope.rs 模块在应用程序代码和构建脚本之间共享 +[dependencies] +schemars = "0.8" + +[build-dependencies] +schemars = "0.8" +``` + +在您的构建脚本中,新增如下代码: + +```rust title="build.rs" +#[path = "src/scope.rs"] +mod scope; + +const COMMANDS: &[&str] = &[]; + +fn main() { + tauri_plugin::Builder::new(COMMANDS) + .global_scope_schema(schemars::schema_for!(scope::Entry)) + .build(); +} +``` + +##### 权限集 + +权限集是单独权限的组,可以帮助用户以更高的抽象级别管理您的外掛。 +例如,如果单个 API 使用多个命令,或者命令集合之间存在逻辑连接,则您应该定义一个包含它们的集合: + +```toml title="permissions/websocket.toml" +"$schema" = "schemas/schema.json" +[[set]] +identifier = "allow-websocket" +description = "Allows connecting and sending messages through a WebSocket" +permissions = ["allow-connect", "allow-send"] +``` + +##### 默认权限 + +默认权限是一个带有 `default` 标识符的特殊权限集。这是您的命令默认所需的权限。 +例如,如果没有允许 `request` 命令,`http` 外掛将毫无用处: + +```toml title="permissions/default.toml" +"$schema" = "schemas/schema.json" +[default] +description = "Allows making HTTP requests" +permissions = ["allow-request"] +``` + +#### 自动生成权限 + +为每个命令定义权限的最简单方法是使用 `build.rs` 文件中定义的外掛构建脚本中定义的自动生成选项。 +在 `COMMANDS` 常量中,使用蛇形命名法定义命令列表(应与命令函数名称匹配),Tauri将自动生成 `allow-$commandname` 和 `deny-$commandname` 权限。 + +下面的例子生成了 `allow-upload` 和 `deny-upload` 权限: + +```rust title="src/commands.rs" +const COMMANDS: &[&str] = &["upload"]; + +fn main() { + tauri_plugin::Builder::new(COMMANDS).build(); +} +``` + +有关更多資訊,请参阅[权限概述文档](/zh-tw/security/permissions/) 。 + +## 管理状态 + +外掛可以像 Tauri 应用程序一样管理状态。阅读[状态管理指南](/zh-tw/develop/state-management/)以获取更多資訊。 diff --git a/src/content/docs/zh-tw/develop/Tests/WebDriver/Example/selenium.mdx b/src/content/docs/zh-tw/develop/Tests/WebDriver/Example/selenium.mdx new file mode 100644 index 0000000000..a7c269bfe0 --- /dev/null +++ b/src/content/docs/zh-tw/develop/Tests/WebDriver/Example/selenium.mdx @@ -0,0 +1,194 @@ +--- +title: Selenium +sidebar: + order: 2 +--- + +{/* TODO: REVISE COPY TO V2 */} + +import CommandTabs from '@components/CommandTabs.astro'; + +:::note[示例应用程序] + +本 [Selenium][] 指南期望您已经完成了 [示例应用程序设置][] 以便一步一步跟进 。 一般性资料可能仍然会有帮助。 + +::: + +此 WebDrive 测试示例将使用 [Selenium][] 和一个流行的 Node.js 测试套装。 您应该已经安装 node.js , 并且一起安装了 `npm` 或 `yarn` , [已完成的示例项目][] 使用了 `yarn`. + +## 创建测试目录 + +让我们创建一个空目录用做测试项目。 在此示例项目中我们将使用嵌套目录,因为稍后还将使用其他框架,但通常您只需要使用一个框架。创建接下来我们需要使用的目录。 创建我们将要使用的目录 `mkdir -p webdriver/selenium` 。 指南接下来的部分我们假定您也在目录 `webdriver/selenium` 中完成。 + +## 初始化 Selenium 项目 + +我们将使用预设的 `package.j son` 来引导此测试套件,因为我们已经选择了特定的要使用的依赖项,并希望展示一个简单的工作解决方案。 此部分的底部有一个折叠起来的内容,其中有关如何从头开始设置的指南。 + +`package.json`: + +```json +{ + "name": "selenium", + "version": "1.0.0", + "private": true, + "scripts": { + "test": "mocha" + }, + "dependencies": { + "chai": "^4.3.4", + "mocha": "^9.0.3", + "selenium-webdriver": "^4.0.0-beta.4" + } +} +``` + +我们有一个脚本将 [Mocha][] 作为测试框架运行,暴露在 `test` 命令中。 我们还有将用于运行测试的各种依赖项。 [Mocha][] 作为测试框架, [Chai][] 作为断言库, 和 [`selenium-webdriver`][] (Node.js 中的 [Selenium][] 软件包)。 + +
+如果你想看到如何从头开始设置一个项目,请点击我 + +如果你想从头安装依赖关系,只需运行以下命令。 + + + +我建议将 `"test": "mocha"` 命令新增到 `package.json` 的 `"scripts"` 中,这样运行 Mocha 只需要执行 + + + +
+ +## 测试 + +与 [WebdriverIO 测试套件](/zh-tw/develop/tests/webdriver/example/webdriverio/#config)不同,Selenium不是开箱即用的测试套件,需要开发人员来构建这些内容。 我们选择 [Mocha][], 它是相当中性的,与 WebDrivers 没有关系。 因此我们的脚本需要做一些工作才能以正确的顺序为我们设置所有内容。 [Mocha][] expects a testing file at `test/test.js` by default, so let's create that file now. + +`test/test.js`: + +```javascript +const os = require('os'); +const path = require('path'); +const { expect } = require('chai'); +const { spawn, spawnSync } = require('child_process'); +const { Builder, By, Capabilities } = require('selenium-webdriver'); + +// create the path to the expected application binary +const application = path.resolve( + __dirname, + '..', + '..', + '..', + 'target', + 'release', + 'hello-tauri-webdriver' +); + +// keep track of the webdriver instance we create +let driver; + +// keep track of the tauri-driver process we start +let tauriDriver; + +before(async function () { + // set timeout to 2 minutes to allow the program to build if it needs to + this.timeout(120000); + + // ensure the program has been built + spawnSync('cargo', ['build', '--release']); + + // start tauri-driver + tauriDriver = spawn( + path.resolve(os.homedir(), '.cargo', 'bin', 'tauri-driver'), + [], + { stdio: [null, process.stdout, process.stderr] } + ); + + const capabilities = new Capabilities(); + capabilities.set('tauri:options', { application }); + capabilities.setBrowserName('wry'); + + // start the webdriver client + driver = await new Builder() + .withCapabilities(capabilities) + .usingServer('http://127.0.0.1:4444/') + .build(); +}); + +after(async function () { + // stop the webdriver session + await driver.quit(); + + // kill the tauri-driver process + tauriDriver.kill(); +}); + +describe('Hello Tauri', () => { + it('should be cordial', async () => { + const text = await driver.findElement(By.css('body > h1')).getText(); + expect(text).to.match(/^[hH]ello/); + }); + + it('should be excited', async () => { + const text = await driver.findElement(By.css('body > h1')).getText(); + expect(text).to.match(/!$/); + }); + + it('should be easy on the eyes', async () => { + // selenium returns color css values as rgb(r, g, b) + const text = await driver + .findElement(By.css('body')) + .getCssValue('background-color'); + + const rgb = text.match(/^rgb\((?\d+), (?\d+), (?\d+)\)$/).groups; + expect(rgb).to.have.all.keys('r', 'g', 'b'); + + const luma = 0.2126 * rgb.r + 0.7152 * rgb.g + 0.0722 * rgb.b; + expect(luma).to.be.lessThan(100); + }); +}); +``` + +If you are familiar with JS testing frameworks, `describe`, `it`, and `expect` should look familiar. We also have +semi-complex `before()` and `after()` callbacks to set up and teardown mocha. Lines that are not the tests themselves +have comments explaining the setup and teardown code. If you were familiar with the Spec file from the +[WebdriverIO example](/zh-tw/develop/tests/webdriver/example/webdriverio/#spec), you notice a lot more code that isn't tests, as we have to set up a few +more WebDriver related items. + +## Running the Test Suite + +Now that we are all set up with our dependencies and our test script, let's run it! + + + +We should see output the following output: + +```text +➜ selenium git:(main) ✗ yarn test +yarn run v1.22.11 +$ Mocha + + + Hello Tauri + ✔ should be cordial (120ms) + ✔ should be excited + ✔ should be easy on the eyes + + + 3 passing (588ms) + +Done in 0.93s. +``` + +We can see that our `Hello Tauri` test suite we created with `describe` had all 3 items we created with `it` pass their +tests! + +With [Selenium] and some hooking up to a test suite, we just enabled e2e testing without modifying our Tauri +application at all! + +[示例应用程序设置]: /develop/tests/webdriver/example/ +[Selenium]: https://selenium.dev/ +[已完成的示例项目]: https://github.com/chippers/hello_tauri +[Mocha]: https://mochajs.org/ +[Chai]: https://www.chaijs.com/ +[`selenium-webdriver`]: https://www.npmjs.com/package/selenium-webdriver diff --git a/src/content/docs/zh-tw/develop/Tests/WebDriver/ci.md b/src/content/docs/zh-tw/develop/Tests/WebDriver/ci.md new file mode 100644 index 0000000000..b564cb112b --- /dev/null +++ b/src/content/docs/zh-tw/develop/Tests/WebDriver/ci.md @@ -0,0 +1,97 @@ +--- +title: 持续集成 +description: WebDriver Testing +--- + +利用 Linux 和一些程序来创建模拟显示,可以在 CI 上使用 [`tauri-driver`][] 运行 [WebDriver][] 测试。 下面的示例使用 [我们之前一起构建][]的 [WebdriverIO][] 示例和 GitHub Actions。 + +遵循以下假设: + +1. Tauri 应用程序位于存储库根目录中,在运行 `cargo build --release` 时构建二进制文件。 +2. 当运行 yarn test 时保证 [WebDriverIO][] 程序位于目录 `webdriver/webdriverio` 中。 + +以下是 Github 工作流文件中的注释,文件位于 `.github/workflows/webdriver.yml`。 + +```yaml +# run this action when the repository is pushed to +on: [push] + +# the name of our workflow +name: WebDriver + +jobs: + # a single job named test + test: + # the display name of the test job + name: WebDriverIO Test Runner + + # we want to run on the latest linux environment + runs-on: ubuntu-latest + + # the steps our job runs **in order** + steps: + # checkout the code on the workflow runner + - uses: actions/checkout@v2 + + # install system dependencies that Tauri needs to compile on Linux. + # note the extra dependencies for `tauri-driver` to run which are: `webkit2gtk-driver` and `xvfb` + - name: Tauri dependencies + run: >- + sudo apt-get update && + sudo apt-get install -y + libgtk-3-dev + libayatana-appindicator3-dev + libwebkit2gtk-4.0-dev + webkit2gtk-driver + xvfb + + # install the latest Rust stable + - name: Rust stable + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + + # we run our rust tests before the webdriver tests to avoid testing a broken application + - name: Cargo test + uses: actions-rs/cargo@v1 + with: + command: test + + # build a release build of our application to be used during our WebdriverIO tests + - name: Cargo build + uses: actions-rs/cargo@v1 + with: + command: build + args: --release + + # install the latest stable node version at the time of writing + - name: Node v16 + uses: actions/setup-node@v2 + with: + node-version: 16.x + + # install our Node.js dependencies with Yarn + - name: Yarn install + run: yarn install + working-directory: webdriver/webdriverio + + # install the latest version of `tauri-driver`. + # note: the tauri-driver version is independent of any other Tauri versions + - name: Install tauri-driver + uses: actions-rs/cargo@v1 + with: + command: install + args: tauri-driver + + # run the WebdriverIO test suite. + # we run it through `xvfb-run` (the dependency we installed earlier) to have a fake + # display server which allows our application to run headless without any changes to the code + - name: WebdriverIO + run: xvfb-run yarn test + working-directory: webdriver/webdriverio +``` + +[previously built together]: /zh-tw/test/webdriver/example/webdriverio +[webdriver]: https://www.w3.org/TR/webdriver/ +[`tauri-driver`]: https://crates.io/crates/tauri-driver +[webdriverio]: https://webdriver.io/ diff --git a/src/content/docs/zh-tw/develop/Tests/WebDriver/index.mdx b/src/content/docs/zh-tw/develop/Tests/WebDriver/index.mdx new file mode 100644 index 0000000000..ac79f6e94b --- /dev/null +++ b/src/content/docs/zh-tw/develop/Tests/WebDriver/index.mdx @@ -0,0 +1,63 @@ +--- +title: WebDriver +description: WebDriver Testing +--- + +:::caution[目前处于预测试阶段] + +Webdriver 对 Tauri 的支持仍处于 pre-alpha 阶段。 专用于它的工具,例如 [tauri-driver][],仍在积极开发中,可能会随着时间的推移而根据需要进行更改。 此外,目前仅支持 Windows 和 Linux。 + +::: + +[WebDrive][] 是一个标准化接口,用于与主要用于自动化测试的 Web 文档进行交互。 Tauri 通过跨平台包装器 [`tauri-driver`][] 来调用原生平台的 [WebDriver][] 服务器以支持 [WebDriver][] 接口。 + +## 系统依赖 + +安装最新的 [`tauri-driver`][] 或通过运行以下命令更新现有安装: + +```shell +cargo install tauri-driver --locked +``` + +由于我们目前使用平台的本机 [WebDriver][] 服务器, 因此在支持的平台上运行 [`tauri-driver`][] 有一些要求。 平台支持目前仅限于 Linux 和 Windows。 + +### Linux + +我们在 Linux 平台上使用 `WebKitWebDriver` 的时候。 需要检查这个二进制文件是否已经存在(命令 `which WebKitWebDriver`), 因为某些发行版将其与常规的WebKit软件包捆绑在一起。 其他平台可能有一个单独的软件包,例如在基于 Debian 的发行版上有 `webkit2gtk-driver` 。 + +### Windows + +Make sure to grab the version of [Microsoft Edge Driver][] that matches your Windows Edge version that the application is being built and tested on. 这几乎总是最新 Windows 安装上的最新稳定版本。 如果两个版本不匹配,则在尝试连接时可能会遇到 WebDriver 测试套件挂起的情况。 + +下载内容包含一个名为 `msedgedriver.exe` 的二进制文件。 [`tauri-driver`][] 在 `$PATH` 中寻找该二进制文件,因此请确保它在路径上可用或使用[`tauri-driver`][] 的 `--native-driver` 选项。 你可能希望在 CI 设置过程中自动下载此内容,以确保 Edge 和 Edge 驱动程序版本在 Windows CI 计算机上保持同步。 后续可能会新增有关如何执行此操作的指南。 + +## 应用示例 + +本指南的 [下一部分](/zh-tw/develop/tests/webdriver/example/) 将逐步介绍如何创建包含 WebDriver 测试的最小示例应用程序。 + +如果您想要查看根据指南操作后完成的最小代码库,则可以 查看这里。 该示例还附带了一个 CI 脚本,用于使用 GitHub 操作进行测试,但您可能仍然对 [WebDriver CI](/zh-tw/develop/tests/webdriver/ci/) 指南感兴趣,因为它对概念进行了更多解释 。 + +import { LinkCard, CardGrid } from '@astrojs/starlight/components'; + + + + + + + +## 持续集成 (CI) + +The above examples also comes with a CI script to test with GitHub actions, but you may still be interested in the below WebDriver CI guide as it explains the concept a bit more. + + + +[webdriver]: https://www.w3.org/TR/webdriver/ +[`tauri-driver`]: https://crates.io/crates/tauri-driver +[tauri-driver]: https://crates.io/crates/tauri-driver +[microsoft edge driver]: https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/ diff --git a/src/content/docs/zh-tw/develop/Tests/index.mdx b/src/content/docs/zh-tw/develop/Tests/index.mdx new file mode 100644 index 0000000000..10aafeedf8 --- /dev/null +++ b/src/content/docs/zh-tw/develop/Tests/index.mdx @@ -0,0 +1,13 @@ +--- +title: 测试 +description: Tauri 运行时内外测试技术 +--- + +Tauri 运行时内外测试技术 + +import { LinkCard, CardGrid } from '@astrojs/starlight/components'; + + + + + diff --git a/src/content/docs/zh-tw/develop/Tests/mocking.md b/src/content/docs/zh-tw/develop/Tests/mocking.md new file mode 100644 index 0000000000..d2a834f725 --- /dev/null +++ b/src/content/docs/zh-tw/develop/Tests/mocking.md @@ -0,0 +1,168 @@ +--- +title: Mock Tauri APIs +sidebar: + order: 1 +--- + +在编写前端测试时,您有一个“模拟” Tauri 环境来处理窗口或拦截IPC通话是常见的,即所谓的 _mocking_。 [`@tauri-apps/api/mocks`][] 模块提供一些有用的工具,让您更轻松地完成此操作: + +:::caution + +请记住在每次测试运行后清除模拟,以撤消运行之间的模拟状态更改! 有关更多資訊,请参阅 [`clearMocks()`][] 文档。 + +::: + +## IPC 请求 + +最常见的是,您希望拦截 IPC 请求; 这在各种情况下都很有用: + +- 确保进行正确的后端调用 +- 模拟后端函数的不同结果 + +Tauri 提供 mockIPC 函数来拦截 IPC 请求。 您可以 [在此处][mockipc()]详细了解特定的 API。 + +:::note + +以下示例使用 [Vitest][],但您可以使用任何其他前端测试库,例如 jest。 + +::: + +```javascript +import { beforeAll, expect, test } from "vitest"; +import { randomFillSync } from "crypto"; + +import { mockIPC } from "@tauri-apps/api/mocks"; +import { invoke } from "@tauri-apps/api/tauri"; + +// jsdom doesn't come with a WebCrypto implementation +beforeAll(() => { + Object.defineProperty(window, 'crypto', { + value: { + // @ts-ignore + getRandomValues: (buffer) => { + return randomFillSync(buffer); + }, + }, + }); +}); + + +test("invoke simple", async () => { + mockIPC((cmd, args) => { + // simulated rust command called "add" that just adds two numbers + if(cmd === "add") { + return (args.a as number) + (args.b as number); + } + }); +}); +``` + +有时您想跟踪有关 IPC 呼叫的更多資訊; 调用了多少次命令? 它被调用了吗? 您可以将 [`mockIPC()`][] 与其他侦测和 mocking 工具来测试这一点: + +```javascript +import { beforeAll, expect, test, vi } from "vitest"; +import { randomFillSync } from "crypto"; + +import { mockIPC } from "@tauri-apps/api/mocks"; +import { invoke } from "@tauri-apps/api/tauri"; + +// jsdom doesn't come with a WebCrypto implementation +beforeAll(() => { + Object.defineProperty(window, 'crypto', { + value: { + // @ts-ignore + getRandomValues: (buffer) => { + return randomFillSync(buffer); + }, + }, + }); +}); + + +test("invoke", async () => { + mockIPC((cmd, args) => { + // simulated rust command called "add" that just adds two numbers + if(cmd === "add") { + return (args.a as number) + (args.b as number); + } + }); + + // we can use the spying tools provided by vitest to track the mocked function + const spy = vi.spyOn(window, "__TAURI_IPC__"); + + expect(invoke("add", { a: 12, b: 15 })).resolves.toBe(27); + expect(spy).toHaveBeenCalled(); +}); +``` + +要模拟对 sidecar 或 shell 命令的 IPC 请求,当事件 `spawn()` 或 `execute()` 被调用时获取处理程序的 ID,并使用此 ID 返回给后端: + +```javascript +mockIPC(async (cmd, args) => { + if (args.message.cmd === 'execute') { + const eventCallbackId = `_${args.message.onEventFn}`; + const eventEmitter = window[eventCallbackId]; + + // 'Stdout' event can be called multiple times + eventEmitter({ + event: 'Stdout', + payload: 'some data sent from the process', + }); + + // 'Terminated' event must be called at the end to resolve the promise + eventEmitter({ + event: 'Terminated', + payload: { + code: 0, + signal: 'kill', + }, + }); + } +}); +``` + +## Windows + +有时您有特定于窗口的代码(例如初始屏幕窗口),因此您需要模拟不同的窗口。 您可以使用 [`mockWindows()`][] 方法来创建假窗口标签。 第一个字符串标识“当前”窗口(即 JavaScript 认为自己所在的窗口),所有其他字符串被视为附加窗口。 + +:::note + +[`mockWindows()`][] 只模拟实现窗口,但没有窗口属性。 要模拟窗口属性,您需要使用 [`mockIPC()`][] 拦截正确的调用。 + +::: + +```javascript +import { beforeAll, expect, test } from 'vitest'; +import { randomFillSync } from 'crypto'; + +import { mockWindows } from '@tauri-apps/api/mocks'; + +// jsdom doesn't come with a WebCrypto implementation +beforeAll(() => { + Object.defineProperty(window, 'crypto', { + value: { + // @ts-ignore + getRandomValues: (buffer) => { + return randomFillSync(buffer); + }, + }, + }); +}); + +test('invoke', async () => { + mockWindows('main', 'second', 'third'); + + const { getCurrent, getAll } = await import('@tauri-apps/api/window'); + + expect(getCurrent()).toHaveProperty('label', 'main'); + expect(getAll().map((w) => w.label)).toEqual(['main', 'second', 'third']); +}); +``` + + + +[`@tauri-apps/api/mocks`]: https://tauri.app/v1/api/js/mocks/ +[`mockipc()`]: https://tauri.app/v1/api/js/mocks#mockipc +[`mockwindows()`]: https://tauri.app/v1/api/js/mocks#mockwindows +[`clearmocks()`]: https://tauri.app/v1/api/js/mocks#clearmocks +[vitest]: https://vitest.dev diff --git a/src/content/docs/zh-tw/develop/resources.mdx b/src/content/docs/zh-tw/develop/resources.mdx new file mode 100644 index 0000000000..cd1cd98779 --- /dev/null +++ b/src/content/docs/zh-tw/develop/resources.mdx @@ -0,0 +1,142 @@ +--- +title: 嵌入附加文件 +sidebar: + order: 1 +--- + +你可能需要将一些不直接属于前端(你的 `frontendDist`)的额外的文件包含在你的应用程序包中,又或是这些文件太大无法内联到二进制文件中。我们称这些文件为 `资源(resources)`。 + +要打包你需要的文件,你可以在 `tauri.conf.json` 文件中的 `bundle` 对象中新增 `resources` 属性。 + +在[此处][tauri.bundle]查看更多关于 `tauri.conf.json` 配置。 + +`resources` 期望获得一个字符串列表,其中包含了指向附加文件的绝对或相对路径的。如果需要从目录中包含多个文件,它支持使用 glob 模式。 + +这里是一个示例,用于说明如何进行配置。这不是一个完整的 `tauri.conf.json` 文件: + +```json title=tauri.conf.json +{ + "bundle": { + "resources": [ + "/absolute/path/to/textfile.txt", + "relative/path/to/jsonfile.json", + "resources/*" + ] + } +} +``` + +或者,如果你想要更改文件复制的目标位置,`resources` 配置也接受一个 map 对象。以下是一个示例,展示了如何将来自不同来源的文件包含到同一个 `resources` 文件夹中: + +```json title=tauri.conf.json +{ + "bundle": { + "resources": { + "/absolute/path/to/textfile.txt": "resources/textfile.txt", + "relative/path/to/jsonfile.json": "resources/jsonfile.json", + "resources/*": "resources/" + } + } +} +``` + +:::note + +绝对路径和包含父级组件(`../`)的路径只能通过 `"$RESOURCE/**"` 的方式声明。相对路径如 `"path/to/file.txt"` 可以通过 `"$RESOURCE/path/to/file.txt"` 明确地允许。 + +::: + +## 在 Rust 中访问文件 + +在这个例子中,我们希望打包额外的 i18n json 文件,它们看起来像这样: + +```json title=de.json +{ + "hello": "Guten Tag!", + "bye": "Auf Wiedersehen!" +} +``` + +在这种情况下,我们将这些文件存储在与 `tauri.conf.json` 相邻的 `lang` 目录中。 +为此,我们像上面展示的那样,在 `resources` 中新增 `"lang/*"`。 + +在 Rust 侧,你需要一个 [`PathResolver`] 实例,这让你可以从 [`App`] 和 [`AppHandle`] 中获取它: + +```rust +tauri::Builder::default() + .setup(|app| { + // 指定的路径必须遵循与定义在 + // `tauri.conf.json > bundle > resources` + let resource_path = app.path().resolve("lang/de.json", BaseDirectory::Resource)?; + + let file = std::fs::File::open(&resource_path).unwrap(); + let lang_de: serde_json::Value = serde_json::from_reader(file).unwrap(); + + // 这里将在终端输出 'Guten Tag!' + println!("{}", lang_de.get("hello").unwrap()); + + Ok(()) + }) +``` + +```rust +#[tauri::command] +fn hello(handle: tauri::AppHandle) -> String { + let resource_path = handle.path().resolve("lang/de.json", BaseDirectory::Resource)?; + + let file = std::fs::File::open(&resource_path).unwrap(); + let lang_de: serde_json::Value = serde_json::from_reader(file).unwrap(); + + lang_de.get("hello").unwrap() +} +``` + +## 在 JavaScript 中访问文件 + +这个例子基于上面的示例。 + +请注意,你必须配置访问控制列表,以启用你需要的 [`plugin-fs`] API,同时还需要权限访问 `$RESOURCE` 文件夹: + +```json title=src-tauri/capabilities/default.json ins={14-15} +{ + "$schema": "../gen/schemas/desktop-schema.json", + "identifier": "main-capability", + "description": "Capability for the main window", + "windows": ["main"], + "permissions": [ + "path:default", + "event:default", + "window:default", + "app:default", + "resources:default", + "menu:default", + "tray:default", + "fs:allow-read-text-file", + "fs:allow-resource-read-recursive" + ] +} +``` + +:::note + +在这里,我们使用 `fs:allow-resource-read-recursive` 来允许完全递归读取访问 `$RESOURCE` 文件夹中的所有文件和子目录。 +欲了解更多資訊,请阅读 [Scope Permissions] 查看其他选项,或查阅 [Scopes] 以获取更精细的控制。 + +::: + +```javascript +import { resolveResource } from '@tauri-apps/api/path'; +import { readTextFile } from '@tauri-apps/plugin-fs'; + +const resourcePath = await resolveResource('lang/de.json'); +const langDe = JSON.parse(await readTextFile(resourcePath)); +console.log(langDe.hello); // 这里将在 devtools 的控制台中输出 'Guten Tag!' +``` + +[tauri.bundle]: /reference/config/#bundleconfig +[`pathresolver`]: https://docs.rs/tauri/latest/tauri/struct.PathResolver.html +[`app`]: https://docs.rs/tauri/latest/tauri/struct.App.html +[`apphandle`]: https://docs.rs/tauri/latest/tauri/struct.AppHandle.html +[`plugin-fs`]: /reference/javascript/fs/ +[Scope Permissions]: /plugin/file-system/#scopes +[scopes]: /plugin/file-system/#scopes diff --git a/src/content/docs/zh-tw/develop/sidecar.mdx b/src/content/docs/zh-tw/develop/sidecar.mdx new file mode 100644 index 0000000000..7a140c2548 --- /dev/null +++ b/src/content/docs/zh-tw/develop/sidecar.mdx @@ -0,0 +1,199 @@ +--- +title: 嵌入外部二进制文件 +sidebar: + order: 1 +i18nReady: true +--- + +您可能需要嵌入外部二进制文件来为应用程序新增额外的功能,或者防止用户安装其他依赖项(例如 Node.js 或 Python)。我们将这个二进制文件称为 `sidecar`。 + +二进制文件是用任何编程语言编写的可执行文件。常见的用例是使用 `pyinstaller` 捆绑的 Python CLI 应用程序或 API 服务器。 + +要捆绑您选择的二进制文件,您可以在 `tauri.conf.json` 中的 `tauri > bundle` 对象中新增 `externalBin` 属性。 +`externalBin` 期望一个字符串列表,用于定位具有绝对或相对路径的二进制文件。 + +下面是一个示例来说明配置。这不是一个完整的 `tauri.conf.json` 文件。 + +```json title="src-tauri/tauri.conf.json" +{ + "bundle": { + "externalBin": [ + "/absolute/path/to/sidecar", + "relative/path/to/binary", + "binaries/my-sidecar" + ] + } +} +``` + +:::note +相对路径是相对于 `tauri.conf.json` 文件的,该文件位于 `src-tauri` 目录中。因此,`binaries/my-sidecar` 表示的是 `<项目根目录>/src-tauri/binaries/my-sidecar`。 +::: + +为了使外部二进制文件在每个支持的架构上工作,指定路径上必须存在一个具有相同名称和 `-$TARGET_TRIPLE` 后缀的二进制文件。例如,`"externalBin": ["binaries/my-sidecar"]` 需要在Linux上有一个名为 `src-tauri/binaries/my-sidecar-x86_64-unknown-linux-gnu` 的可执行文件,或者在 Mac OS with Apple Silicon 上有一个名为 `src-tauri/binaries/my-sidecar-aarch64-apple-darwin` 的可执行文件。 + +你可以通过查看 `rustc -Vv` 命令报告的 `host:` 属性来找到当前平台的 `-$TARGET_TRIPLE` 后缀。 + +如果大多数 Unix 系统都有 `grep` 和 `cut` 命令,则可以使用以下命令直接提取 `$TARGET_TRIPLE`。 + +```shell +rustc -Vv | grep host | cut -f2 -d' ' +``` + +在 Windows 上,你可以使用 PowerShell 代替。 + +```powershell +rustc -Vv | Select-String "host:" | ForEach-Object {$_.Line.split(" ")[1]} +``` + +下面是一个将 `$TARGET_TRIPLE` 追加到二进制文件的 Node.js 脚本: + +```javascript +const execa = require('execa'); +const fs = require('fs'); + +let extension = ''; +if (process.platform === 'win32') { + extension = '.exe'; +} + +async function main() { + const rustInfo = (await execa('rustc', ['-vV'])).stdout; + const targetTriple = /host: (\S+)/g.exec(rustInfo)[1]; + if (!targetTriple) { + console.error('Failed to determine platform target triple'); + } + fs.renameSync( + `src-tauri/binaries/sidecar${extension}`, + `src-tauri/binaries/sidecar-${targetTriple}${extension}` + ); +} + +main().catch((e) => { + throw e; +}); +``` + +注意,如果编译的体系结构与运行的体系结构不同,这个脚本将无法工作。 + +## 从 Rust 运行 + +在 Rust 端, 导入 `tauri_plugin_shell::ShellExt` 特征,并在 `AppHandle` 上调用 `shell().sidecar()` 函数。 + +```rust +use tauri_plugin_shell::ShellExt; +use tauri_plugin_shell::process::CommandEvent; + +// `sidecar()` 只需要文件名, 不像 JavaScript 中的整个路径 +let sidecar_command = app.shell().sidecar("my-sidecar").unwrap(); +let (mut rx, mut _child) = sidecar_command + .spawn() + .expect("Failed to spawn sidecar"); + +tauri::async_runtime::spawn(async move { + // 读取诸如 stdout 之类的事件 + while let Some(event) = rx.recv().await { + if let CommandEvent::Stdout(line) = event { + window + .emit("message", Some(format!("'{}'", line))) + .expect("failed to emit event"); + // 写入 stdin + child.write("message from Rust\n".as_bytes()).unwrap(); + } + } +}); +``` + +您可以将此代码放在 Tauri 命令中,以便轻松传递 AppHandle,或者您可以在构建脚本中存储对 AppHandle 的引用,以便在应用程序的其他位置访问它。 + +## 从 JavaScript 运行 + +在 JavaScript 代码中,从 `@tauri-apps/plugin-shell` 模块中导入 `Command` 类,并使用其静态方法 `sidecar`。 + +```javascript +import { Command } from '@tauri-apps/plugin-shell'; +// `binaries/my-sidecar` 是在 `tauri.conf.json > tauri > bundle > externalBin` 指定的确切值。 +const sidecar_command = Command.sidecar('binaries/my-sidecar'); +const output = await sidecar_command.execute(); +``` + +## 传递参数 + +你可以像运行普通的 `Command` 一样向 Sidecar 命令传递参数。 + +参数可以是**静态的**(例如 `-o` 或 `serve`)或者**动态的**(例如 `` 或者 `localhost:`)。 +你按照调用它们的确切顺序来定义这些参数。静态参数保持不变,而动态参数可以使用正则表达式来定义。 + +首先,在 `src-tauri/capabilities/default.json` 中定义需要传递给 sidecar 命令的参数。 + +```json title="src-tauri/capabilities/default.json" ins={14-31} +{ + "$schema": "../gen/schemas/desktop-schema.json", + "identifier": "default", + "description": "Capability for the main window", + "windows": ["main"], + "permissions": [ + "core:path:default", + "core:event:default", + "core:window:default", + "core:app:default", + "core:resources:default", + "core:menu:default", + "core:tray:default", + { + "identifier": "shell:allow-execute", + "allow": [ + { + "args": [ + "arg1", + "-a", + "--arg2", + { + "validator": "\\S+" + } + ], + "cmd": "", + "name": "binaries/my-sidecar", + "sidecar": true + } + ] + }, + "shell:allow-open" + ] +} +``` + +:::note +如果你正在从 Tauri v1 迁移,Tauri v2 CLI 中的 `migrate` 命令应该会为你处理这个问题。阅读[自动迁移](/zh-tw/start/migrate/from-tauri-1/#自动迁移)了解更多資訊。 +::: + +然后,要调用 sidecar 命令,只需将**所有**参数作为数组传入即可。 + +在 Rust 中: + +```rust +use tauri_plugin_shell::ShellExt; +#[tauri::command] +async fn call_my_sidecar(app: tauri::AppHandle) { + let sidecar_command = app.shell() + .sidecar("my-sidecar") + .unwrap() + .args(["arg1", "-a", "--arg2", "any-string-that-matches-the-validator"]); + let (mut _rx, mut _child) = sidecar_command.spawn().unwrap(); +} +``` + +在 JavaScript 中: + +```javascript +import { Command } from '@tauri-apps/plugin-shell'; +// `binaries/my-sidecar` 是在 `tauri.conf.json > tauri > bundle > externalBin` 指定的确切值。 +// 请注意 args 数组需要与 `tauri.conf.json` 中指定的需完全匹配 +const command = Command.sidecar('binaries/my-sidecar', [ + 'arg1', + '-a', + '--arg2', + 'any-string-that-matches-the-validator', +]); +const output = await command.execute(); +``` diff --git a/src/content/docs/zh-tw/develop/updating-dependencies.mdx b/src/content/docs/zh-tw/develop/updating-dependencies.mdx new file mode 100644 index 0000000000..a1b76b6016 --- /dev/null +++ b/src/content/docs/zh-tw/develop/updating-dependencies.mdx @@ -0,0 +1,61 @@ +--- +title: 更新依赖关系 +--- + +import CommandTabs from '@components/CommandTabs.astro'; + +## 更新 npm 包 + +如果您正在使用 `tauri` 包: + + + +您还可以通过以下方式检测最新版本的 Tauri 在命令行上: + + + +或者,如果您正在使用 `vue-cli-plugin-tauri` 方法: + + + +## 更新 Cargo 包 + +您可以用 [`Cargo outdated`][] 或在 crates.io 页面上检查过期的包: [tauri][] / [tauri-build][] + +打开 `src-tauri/Cargo.toml` 并更改 `tauri` 和 `tauri-build` + +```toml +[build-dependencies] +tauri-build = "%version%" + +[dependencies] +tauri = { version = "%version%" } +``` + +其中 `%version%` 是上面相应的版本号 + +然后执行以下操作: + +```shell +cd src-tauri +cargo update +``` + +或者,您可以运行 `cargo upgrade` 命令,由 [ cargo-edit][] 提供,这将自动完成所有这一切。 + +[`cargo outdated`]: https://github.com/kbknapp/cargo-outdated +[tauri]: https://crates.io/crates/tauri/versions +[tauri-build]: https://crates.io/crates/tauri-build/versions +[cargo-edit]: https://github.com/killercup/cargo-edit diff --git a/src/content/docs/zh-tw/distribute/Pipelines/crabnebula-cloud.mdx b/src/content/docs/zh-tw/distribute/Pipelines/crabnebula-cloud.mdx new file mode 100644 index 0000000000..ceb2547bc9 --- /dev/null +++ b/src/content/docs/zh-tw/distribute/Pipelines/crabnebula-cloud.mdx @@ -0,0 +1,20 @@ +--- +title: CrabNebula Cloud +--- + +## 使用 CrabNebula Cloud 进行分发 + +[CrabNebula](https://crabnebula.dev) 是 Tauri 官方合作伙伴,为 Tauri 应用提供服务和工具。 +[CrabNebula Cloud](https://crabnebula.dev/cloud/)是一个与 Tauri 更新程序无缝集成的应用分发平台。 + +该服务提供了一个内容传递网络(CDN),能够以成本效益的方式全球运送您的应用程序安装程序和更新,并公开下载指标。 + +通过 CrabNebula Cloud 服务,实现多个发布渠道、应用网站的下载按钮等非常简单。 + +将您的 Tauri 应用程序设置为使用云非常简单:您只需使用 GitHub 帐户登录 [Cloud 网站],创建组织和应用程序,并安装其 CLI 以创建发布并上传 Tauri 捆绑包。此外,还提供了一个 [GitHub Action] 来简化在 GitHub 工作流程中使用 CLI 的过程。 + +更多資訊,请参阅 [CrabNebula Cloud 文档]。 + +[GitHub Action]: https://github.com/crabnebula-dev/cloud-release/ +[Cloud 网站]: https://web.crabnebula.cloud/ +[CrabNebula Cloud 文档]: https://docs.crabnebula.dev/cloud/ diff --git a/src/content/docs/zh-tw/distribute/Sign/android.mdx b/src/content/docs/zh-tw/distribute/Sign/android.mdx new file mode 100644 index 0000000000..0fbed8dcd3 --- /dev/null +++ b/src/content/docs/zh-tw/distribute/Sign/android.mdx @@ -0,0 +1,115 @@ +--- +title: 安卓代码签名 +sidebar: + label: 安卓 + order: 5 +--- + +import { Steps } from '@astrojs/starlight/components'; + +要在 Play 商店上发布,您需要使用数字证书对应用程序进行签名。 + +安卓使用两个签名密钥:上传和应用签名。 + +开发者将使用上传密钥签名的 `.aab` 或 `.apk` 文件上传到Play商店。 +最终用户下载使用应用签名密钥签名的 `.apk` 文件。 +要创建您的应用签名密钥,请按照[官方 Play 商店文档](https://support.google.com/googleplay/android-developer/answer/9842756?hl=en&visit_id=638549803861403647-3347771264&rd=1)中描述的步骤来进行。 + +请按照以下说明对您的应用进行签名。 + + +1. 创建一个 `upload` 密钥库 + + 如果您已经有一个密钥库,请跳到下一步。如果没有,请使用以下方法之一创建一个。 + + 1. 按照 [Android Studio 密钥生成步骤](https://developer.android.com/studio/publish/app-signing#sign-apk) + 2. 在命令行中运行如下命令: + 在 Mac/Linux 中,执行如下命令: + + ``` + keytool -genkey -v -keystore ~/upload-keystore.jks -keyalg RSA -keysize 2048 -validity 10000 -alias upload + ``` + + 在 Windows 上,执行如下命令: + + ``` + keytool -genkey -v -keystore $env:USERPROFILE\upload-keystore.jks -storetype JKS -keyalg RSA -keysize 2048 -validity 10000 -alias upload + ``` + + 这个命令将 `upload-keystore.jks` 文件存储在你的家目录中。如果你想把它存储在其他地方,可以改变传递给 `-keystore` 参数的参数值。然而,请保持 `keystore` 文件的私密性,不要将其提交到公共源代码控制! + + :::note + + - `keytool` 命令可能不在您的环境变量中 - 它是 Java 的一部分,作为 Android Studio 的一部分安装。例如,您可能会发现它安装在 Android Studio 附带的 JDK 中。 + + - Linux: `/opt/android-studio/jbr/bin/keytool` + - macOS: `/Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/keytool` + - Windows: `C:\\Program Files\\Android\\Android Studio\\jbr\\bin\\keytool.exe` + + 然后使用完整的路径。如果您的路径包含以空格分隔的名称,例如 Program Files,请使用适合平台的符号表示这些名称。例如,在 Mac/Linux 上使用 `Program\ Files`,在Windows上使用 `"Program Files"`。 + + - `-storetype JKS` 标签仅适用于 Java 9 或更新版本。从 Java 9 版本开始,默认的密钥库类型为 PKS12。 + ::: + +3. 从应用程序中引用密钥库 + + 创建一个名为 `[project]/src-tauri/gen/android/keystore.properties` 的文件,其中包含对你的密钥库的引用。 + + ``` + storePassword= + keyPassword= + keyAlias=upload + storeFile=<密钥存储文件的位置,例如 /Users//upload-keystore.jks 或 C:\\Users\\\\upload-keystore.jks> + ``` + + :::caution + 请保持 `keystore.properties` 文件的私密性,不要将其提交到公共源代码控制中。 + ::: + +4. 在 Gradle 中配置签名 + + 通过编辑 `[project]/src-tauri/gen/android/app/build.gradle.kts` 文件,配置 gradle 在发布模式下构建应用时使用您的上传密钥。 + + 1. 在文件开头新增所需的导入。 + + ```kotlin + import java.util.Properties + import java.io.FileInputStream + ``` + + 2. 在 `buildTypes` 代码块之前新增 `release` 签名配置。 + + ```kotlin {3-12} + signingConfigs { + create("release") { + val keystorePropertiesFile = rootProject.file("keystore.properties") + val keystoreProperties = Properties() + if (keystorePropertiesFile.exists()) { + keystoreProperties.load(FileInputStream(keystorePropertiesFile)) + } + + keyAlias = keystoreProperties["keyAlias"] as String + keyPassword = keystoreProperties["keyPassword"] as String + storeFile = file(keystoreProperties["storeFile"] as String) + storePassword = keystoreProperties["storePassword"] as String + } + } + + buildTypes { + ... + } + ``` + + 3. 在 `buildTypes` 块中的 `release` 配置中使用新的 `release` 签名配置。 + + ```kotlin {3} + buildTypes { + getByName("release") { + signingConfig = signingConfigs.getByName("release") + } + } + ``` + + + +你应用的发布版本现在会自动签名。 diff --git a/src/content/docs/zh-tw/distribute/Sign/ios.mdx b/src/content/docs/zh-tw/distribute/Sign/ios.mdx new file mode 100644 index 0000000000..32c0ef8002 --- /dev/null +++ b/src/content/docs/zh-tw/distribute/Sign/ios.mdx @@ -0,0 +1,92 @@ +--- +title: iOS 代码签名 +sidebar: + label: iOS + order: 4 +--- + +在 iOS 上进行代码签名是必需的,以便通过官方[苹果应用商店]或可能的欧盟替代市场分发您的应用程序,并且一般来说可以安装和执行在最终用户设备上。 + +## 前置条件 + +在 iOS 上进行代码签名需要加入[苹果开发者]计划,截至撰写本文时每年费用为 99 美元。 +您还需要一台苹果设备来执行代码签名。这是由于签名过程和苹果的条款和条件所要求的。 + +要分发 iOS 应用程序,您必须在 App Store Connect 中注册您的包标识符,拥有适当的 iOS 代码签名证书以及将它们链接在一起并启用您的应用程序使用的 iOS 功能的移动配置文件。这些要求可以由 Xcode 自动管理,也可以手动提供。 + +## 自动签名 + +让 Xcode 管理应用的签名和配置是将 iOS 应用导出以进行分发的最方便的方式。 +它会自动注册您的包标识符,处理 iOS 功能变化,并根据您选择的导出方法配置适当的证书。 + +默认情况下启用了自动签名,并且在本地机器上使用时会使用 Xcode 中配置的账户进行身份验证。\ +要注册您的帐户,请打开 Xcode 应用程序,然后在 `Xcode > Settings` 菜单中打开设置页面,切换到账户选项卡,并点击 `+` 图标。 + +要使用 CI/CD 平台上的自动签名功能,您必须创建一个 App Store Connect API 密钥,并定义 `APPLE_API_ISSUER`、`APPLE_API_KEY` 和 `APPLE_API_KEY_PATH` 环境变量。 +打开 [App Store Connect 用户和访问页面],选择 Integrations 选项卡,单击 Add 按钮并选择名称和管理员访问权限。 +`APPLE_API_ISSUER`(颁发者 ID)显示在 keys 表的上方,而 `APPLE_API_KEY` 是该表的 Key ID 列的值。 +你还需要下载私钥,它只能下载一次,并且只有在页面重新加载后才可见(该按钮显示在新创建密钥的表格行上)。 +私钥文件路径必须通过 `APPLE_API_KEY_PATH` 环境变量设置。 + +## 手动签名 + +要手动为你的 iOS 应用签名,你可以通过环境变量提供证书和移动配置文件: + +- **IOS_CERTIFICATE**:从 Keychain 导出的证书的 base64 表示形式。 +- **IOS_CERTIFICATE_PASSWORD**:从 Keychain 导出时设置的证书密码。 +- **IOS_MOBILE_PROVISION**:授权描述文件的 Base64 表示。 + +下面几节解释如何获取这些值。 + +### 签名证书 + +注册后,导航到[证书]页面创建一个新的 Apple 分发证书。下载新的证书并将其安装到 macOS 钥匙串中。 + +要导出证书密钥,请打开 "Keychain Access" 应用程序,展开证书条目, +右键点击密钥项目,并选择 "Export \" 选项。选择导出的 .p12 文件的路径,并记住其密码。 + +运行以下 `base64` 命令将证书转换为 base64 格式并复制到剪贴板: + +``` +base64 -i | pbcopy +``` + +剪贴板中的值现在是签名证书的 base64 表示。 +保存并作为 `IOS_CERTIFICATE` 环境变量的值使用。 + +需要设置 `IOS_CERTIFICATE_PASSWORD` 变量的值必须为证书密码。 + +:::tip[选择证书类型] +每个导出方法都必须使用适当的证书类型。 + +- **debugging**:苹果开发或 iOS 应用开发 +- **app-store-connect**:苹果发行版或 iOS 发行版 (App Store Connect 和 Ad Hoc) +- **ad-hoc**:苹果发行版或 iOS 发行版 (App Store Connect 和 Ad Hoc) + +::: + +### 配置文件 + +此外,你必须为你的应用提供配置描述文件。 +在 [Identifiers](https://developer.apple.com/account/resources/identifiers/list) 页面中, +创建一个新的应用程序 ID,并确保其 "Bundle ID" 值与 [`identifier`] 配置中设置的标识符匹配。 + +导航到 [Profiles](https://developer.apple.com/account/resources/profiles/list) 页面以创建新的预配配置文件。 +对于 App Store 分发,必须选择 "App Store Connect" 配置文件。选择合适的 App ID 并链接你之前创建的证书。 + +创建配置文件后,下载它并运行以下 `base64` 命令来转换该配置文件并将其复制到剪贴板: + +``` +base64 -i | pbcopy +``` + +剪贴板中的值现在是配置描述文件的 base64 表示。 +保存它并将其用作 `IOS_MOBILE_PROVISION` 环境变量值。 + +现在你可以构建你的 iOS 应用程序并在 App Store 上发布了! + +[证书]: https://developer.apple.com/account/resources/certificates/list +[苹果开发者]: https://developer.apple.com +[苹果应用商店]: https://www.apple.com/app-store/ +[App Store Connect 用户和访问页面]: https://appstoreconnect.apple.com/access/users +[`identifier`]: /reference/config/#identifier diff --git a/src/content/docs/zh-tw/distribute/Sign/linux.mdx b/src/content/docs/zh-tw/distribute/Sign/linux.mdx new file mode 100644 index 0000000000..499ffde19c --- /dev/null +++ b/src/content/docs/zh-tw/distribute/Sign/linux.mdx @@ -0,0 +1,56 @@ +--- +title: Linux 代码签名 +sidebar: + label: Linux + order: 3 +--- + +该指南提供了有关 Linux 软件包的代码签名的資訊。 +虽然在 Linux 上部署应用程序不需要进行构件签名,但可以使用它来增加对已部署应用程序的信任。 +对二进制文件进行签名允许最终用户验证其真实性,并确保其未被其他不受信任的实体修改过。 + +## 为 AppImages 签名 + +可以使用 gpg 或 gpg2 对 AppImage 进行签名。 + +### 前置条件 + +必须准备签名密钥。可以使用以下命令生成一个新的文件。 + +```shell +gpg2 --full-gen-key +``` + +请参阅 gpg 或 gpg2 文档了解更多資訊。 +您应该特别注意将私钥和公钥备份到安全的位置。 + +### 签名 + +可以通过设置以下环境变量在 AppImage 中嵌入签名: + +- **SIGN**:设置为 `1` 为 AppImage 签名。 +- **SIGN_KEY**:可选变量,用于使用特定的 GPG 密钥 ID 进行签名。 +- **APPIMAGETOOL_SIGN_PASSPHRASE**:签名密钥密码。如果未设置,gpg 将显示一个对话框,以便您可以输入它。在构建 CI/CD 平台时必须设置此参数。 +- **APPIMAGETOOL_FORCE_SIGN**:默认情况下,即使签名失败,也会生成 AppImage。要在发生错误时退出,你可以将此变量设置为 `1`。 + +可以通过运行以下命令显示 AppImage 中嵌入的签名。 + +```shell +./src-tauri/target/release/bundle/appimage/$APPNAME_$VERSION_amd64.AppImage --appimage-signature +``` + +注意,您需要根据您的配置将 $APPNAME 和 $VERSION 值更改为正确的值。 + +:::caution + +**签名未被验证** + +AppImage 不验证签名,因此您不能依赖它来检查文件是否被篡改。 +要验证签名,您必须为用户提供外部工具。 +这需要您在经过身份验证的渠道上发布公钥(例如通过 TLS 提供的网站),以便最终用户可以下载并进行验证。 + +有关更多資訊,请参阅 [AppImage 官方文档]。 + +::: + +[AppImage 官方文档]: https://docs.appimage.org/packaging-guide/optional/signatures.html diff --git a/src/content/docs/zh-tw/distribute/Sign/macos.mdx b/src/content/docs/zh-tw/distribute/Sign/macos.mdx new file mode 100644 index 0000000000..21c28a1f3c --- /dev/null +++ b/src/content/docs/zh-tw/distribute/Sign/macos.mdx @@ -0,0 +1,102 @@ +--- +title: macOS 代码签名 +sidebar: + label: macOS + order: 1 +--- + +在 macOS 上,代码签名是必需的,这样才能让你的应用程序出现在[苹果应用商店]列表中,并防止从浏览器下载应用程序时出现应用程序崩溃和无法启动的警告。 + +## 前置条件 + +在 iOS 上进行代码签名需要加入[苹果开发者]计划,截至撰写本文时每年费用为 99 美元。 +您还需要一台苹果设备来执行代码签名。这是由于签名过程和苹果的条款和条件所要求的。 + +## 签名 + +要为 macOS 设置代码签名,您必须创建 Apple 代码签名证书并将其安装到您的 Mac 计算机 keychain 中,或将其导出以便在 CI/CD 平台中使用。 + +### 创建签名证书 + +要创建一个新的签名证书,你必须在你的Mac计算机上生成一个证书签名请求(certificate signing Request, CSR)文件。 +参见[创建证书签名请求]了解如何创建用于代码签名的CSR文件。 + +在你的苹果开发者账户上,导航到 [Certificates, IDs & Profiles 页面],然后点击 `Create a certificate` 按钮打开界面来创建一个新的证书。 +选择合适的证书类型(`Apple Distribution` 用于将应用提交到 App Store, `Developer ID Application` 用于将应用发布到 App Store 之外)。 +上传你的 CSR 文件,证书就会被创建出来。 + +:::note +只有苹果开发者“账户持有者”才能创建\* _开发者ID应用程序_ \*证书。但它可以通过使用不同的用户电子邮件地址创建一个 CSR 来关联到不同的 Apple ID。 +::: + +### 下载证书 + +在 [Certificates, IDs & Profiles 页面],点击你想要使用的证书,然后点击 `Download` 按钮。 +它会保存一个 `.cer` 文件,打开后将证书安装到 keychain 上。 + +### Tauri 配置 + +当在本地机器上构建 macOS 应用程序或使用 CI/CD 平台时,您可以配置 Tauri 使用您的证书。 + +#### 本地签名 + +在 Mac 计算机密钥链中安装证书后,您可以配置 Tauri 将其用于代码签名。 + +证书的 keychain 条目的名称代表了 `signing identity`,也可以通过执行以下命令找到它: + +``` +security find-identity -v -p codesigning +``` + +这个身份可以通过 [`tauri.conf.json > bundle > macOS > signingIdentity`] 配置选项或者通过 `APPLE_SIGNING_IDENTITY` 环境变量来提供。 + +:::note + +签名证书只有与你的 Apple ID 相关联时才有效。 +无效证书不会列在 _Keychain Access > My certifates_ 选项卡或 _security find-identity -v -p codesigning_ 输出中。 +如果证书没有下载到正确的位置,请确保在下载 .cer 文件时,在 “Default Keychains” 下选择 “login” 选项。 + +::: + +#### 在 CI/CD 平台中进行签名 + +要在 CI/CD 平台中使用证书,必须将证书导出为 base64 字符串,并配置 `APPLE_CERTIFICATE` 和 `APPLE_CERTIFICATE_PASSWORD` 环境变量。 + +1. 打开 `Keychain Access` 应用程序,点击 _login_ Keychain 中的 _My Certificates_ 标签,找到你的证书条目。 +2. 展开条目,双击 key 项,并选择 `Export "$KEYNAME"`。 +3. 选择保存证书的 `.p12` 文件的路径,并为导出的证书设置一个密码。 +4. 在终端运行以下脚本将 `.p12` 文件转换为 base64: + +``` +openssl base64 -in /path/to/certificate.p12 -out certificate-base64.txt +``` + +5. 将 `certificate-base64.txt` 文件的内容设置为 `APPLE_CERTIFICATE` 环境变量的值。 +6. 将证书密码设置为 `APPLE_CERTIFICATE_PASSWORD` 环境变量。 + +## 公正 + +要公证您的应用程序,您必须为 Tauri 提供凭证,以便与 Apple 进行认证: + +- APPLE_API_ISSUER、APPLE_API_KEY 和 APPLE_API_KEY_PATH:使用 App Store Connect API 密钥进行身份验证 + + 打开 [App Store Connect 用户和访问页面],选择 Integrations 选项卡,单击 Add 按钮并选择名称和开发者权限。 + 在 keys 表中可以看到 APPLE_API_ISSUER (颁发者 ID),而 APPLE_API_KEY 是该表中 Key ID 列的值。 + 你还需要下载私钥,它只能下载一次,并且只有在页面重新加载后才可见(该按钮显示在新创建密钥的表格行上)。 + 私钥文件路径必须通过 APPLE_API_KEY_PATH 环境变量设置。 + +- APPLE_ID、APPLE_PASSWORD 和 APPLE_TEAM_ID:使用你的 Apple ID 进行身份验证 + + 或者,要用你的 Apple ID 进行身份验证,可以把 APPLE_ID 设置为你的苹果账户的电子邮件地址,把 APPLE_PASSWORD 设置为苹果账户特定于应用程序的密码。 + +:::note +当使用**开发者 ID 申请**证书时,需要公证。 +::: + +[Certificates]: https://developer.apple.com/account/resources/certificates/list +[苹果开发者]: https://developer.apple.com +[苹果应用商店]: https://www.apple.com/app-store/ +[App Store Connect 用户和访问页面]: https://appstoreconnect.apple.com/access/users +[`tauri.conf.json > bundle > macOS > signingIdentity`]: /reference/config/#signingidentity +[创建证书签名请求]: https://developer.apple.com/help/account/create-certificates/create-a-certificate-signing-request +[Certificates, IDs & Profiles 页面]: https://developer.apple.com/account/resources/certificates/list diff --git a/src/content/docs/zh-tw/distribute/Sign/windows.mdx b/src/content/docs/zh-tw/distribute/Sign/windows.mdx new file mode 100644 index 0000000000..1b0b165467 --- /dev/null +++ b/src/content/docs/zh-tw/distribute/Sign/windows.mdx @@ -0,0 +1,284 @@ +--- +title: Windows 代码签名 +sidebar: + label: Windows + order: 2 +--- + +import { Steps } from '@astrojs/starlight/components'; + +在 Windows 上,代码签名是必需的,以允许您的应用程序出现在 [Microsoft Store] 中,并防止从浏览器下载应用程序时出现 [SmartScreen] 警告,即您的应用程序不受信任且无法启动。 + +只要你的终端用户可以忽略 [SmartScreen] 警告,或者你的用户不通过浏览器下载,则不需要在 Windows 上不需要执行你的应用程序。 +本指南涵盖了通过 OV(组织验证)证书和 Azure 密钥库进行签名。 +如果您使用本文未介绍的任何其他签名机制,例如 EV (Extended Validation,扩展验证)证书, +查看您的证书颁发者文档并参考[自定义签名命令](#自定义签名命令)一节。 + +## OV 证书 + +:::danger +本指南仅适用于 2023 年 6 月 1 日前获得的 OV 代码签名证书!对于在该日期之后收到的 EV 证书和 OV 证书的代码签名,请查阅证书颁发机构的文档。 +::: + +:::note +如果您使用 EV 证书为应用程序签名,它将立即获得微软 SmartScreen 的认可,并且不会向用户显示任何警告。 + +如果你选择 OV 证书,这种证书通常更便宜,而且个人可以获得,微软 SmartScreen 仍然会在用户下载应用程序时向他们显示警告。 +你的证书可能需要一段时间才能建立足够的认可。您可以选择[提交您的应用程序]到 Microsoft 进行手动审查。 +虽然不能保证,但如果应用程序不包含任何恶意代码,微软可能会授予额外的认可,并可能删除该特定上传文件的警告。 + +查看[对比](https://www.digicert.com/difference-between-dv-ov-and-ev-ssl-certificates)了解更多关于 OV 和 EV 证书的資訊。 +::: + +### 前置条件 + +- Windows - 你也可以使用其他平台,但本教程使用 Powershell 的原生功能。 +- 一个工作的 Tauri 应用程序 +- 代码签名证书 - 代码签名证书——你可以在 [Microsoft 文档]中列出的服务中获取。对于非 EV 证书,可能还有其他的权威机构,请您自己比较并选择一个,风险自负。 + - 请确保获取**代码签名**证书,SSL 证书不起作用! + +### 开始 + +要让 Windows 为代码签名做好准备,我们必须做几件事。这包括将我们的证书转换为特定的格式,安装此证书,以及从证书中解码所需的資訊。 + + + +1. #### 将 `.cer` 转换为 `.pfx` + + - 你将需要以下内容: + + - 证书文件 (我是 `cert.cer`) + - 私钥文件 (我是 `private-key.key`) + + - 打开一个命令提示符,使用 `cd Documents/Certs` 切换到当前目录 + + - 使用 `openssl pkcs12 -export -in cert.cer -inkey private-key.key -out certificate.pfx` 将您的 `.cer` 文件转换为 `.pfx` 文件 + + - 你应该被提示输入导出密码**别忘了!** + +2. #### 将你的 `.pfx` 文件导入密钥库。 + + - 我们现在需要导入我们的 `.pfx` 文件。 + + - 使用 `$WINDOWS_PFX_PASSWORD = 'MYPASSWORD'` 将您的导出密码分配到一个变量 + + - 现在使用 `Import-PfxCertificate -FilePath certificate.pfx -CertStoreLocation Cert:\CurrentUser\My -Password (ConvertTo-SecureString -String $WINDOWS_PFX_PASSWORD -Force -AsPlainText)` 导入证书。 + +3. #### 准备变量 + + - 开始 ➡️ 打开 `certmgr.msc` 以打开个人证书管理,然后打开"个人/证书"。 + + - 找到刚导入的证书,双击它,然后点击 Details 选项卡。 + + - 签名哈希算法将是我们的 `digestAlgorithm`。(提示:这很可能是 `sha256`) + + - 向下滚动到拇指指纹。应该有一个类似于 `A1B1A2B2A3B3A4B4A5B5A6B6A7B7A8B8A9B9A0B0`的值。这是我们的 `certificateThumbprint`。 + + - 我们还需要一个时间戳 URL;这是一个时间服务器,用于验证证书签名的时间。我使用的是 `http://timestamp.comodoca.com`,但是无论你从谁那里获得证书,他可能也有一个。 + + + +### 准备 `tauri.conf.json` 文件 + +1. 现在我们有了 `certificateThumbprint`、`digestAlgorithm` 和 `timestampUrl`,我们将打开 `tauri.conf.json` 文件。 + +2. 在 `tauri.conf.json` 文件中,你需要找到 `tauri` -> `bundle` -> `windows` 部分。我们已经获取了三个变量的資訊。请按照下面的示例填写它们。 + +```json tauri.conf.json +"windows": { + "certificateThumbprint": "A1B1A2B2A3B3A4B4A5B5A6B6A7B7A8B8A9B9A0B0", + "digestAlgorithm": "sha256", + "timestampUrl": "http://timestamp.comodoca.com" +} +``` + +3. 保存并运行 `tauri build` + +4. 在控制台输出中,你应该看到如下输出。 + +``` +info: signing app +info: running signtool "C:\\Program Files (x86)\\Windows Kits\\10\\bin\\10.0.19041.0\\x64\\signtool.exe" +info: "Done Adding Additional Store\r\nSuccessfully signed: APPLICATION FILE PATH HERE +``` + +这表明你已经成功地对 `.exe` 进行了签名。 + +就是这样!您已经成功设置了用于 Windows 签名的 Tauri 应用程序。 + +### 使用 GitHub Actions 为你的应用签名。 + +我们还可以创建一个工作流,使用 GitHub Actions 对应用程序进行签名。 + +#### GitHub 密钥 + +我们需要新增一些 GitHub 密钥来正确配置 GitHub Action。你可以随意命名它们。 + +- 你可以查看 [encrypted secrets] 指南,了解如何新增 GitHub 密钥。 + +我们使用的密钥如下。 + +| GitHub 密钥 | 变量值 | +| :--------------------------: | :-----------------------------------------------------------------------------------------------------: | +| WINDOWS_CERTIFICATE | 将您的 .pfx 证书进行 Base64 编码,可以使用 `certutil -encode certificate.pfx base64cert.txt` 命令完成。 | +| WINDOWS_CERTIFICATE_PASSWORD | 在创建 .pfx 证书时使用的证书导出密码。 | + +#### 工作流的修改 + +1. 我们需要在工作流中新增一个步骤来将证书导入 Windows 环境。该工作流完成以下工作。 + + 1. 将 GitHub 密钥分配给环境变量 + 2. 创建一个新的 `certificate` 目录 + 3. 将 `WINDOWS_CERTIFICATE` 导入到 tempCert.txt 文件中 + 4. 使用 `certutil` 将 tempCert.txt 从 base64 解码为 `.pfx` 文件。 + 5. 移除 tempCert.txt 文件 + 6. 将 `.pfx` 文件导入到 Windows 的证书存储中,并将 `WINDOWS_CERTIFICATE_PASSWORD` 转换为安全字符串,以便在导入命令中使用。 + +2. 我们将使用 [`tauri-action` 发布模板]。 + +```yml +name: 'publish' +on: + push: + branches: + - release + +jobs: + publish-tauri: + strategy: + fail-fast: false + matrix: + platform: [macos-latest, ubuntu-latest, windows-latest] + + runs-on: ${{ matrix.platform }} + steps: + - uses: actions/checkout@v2 + - name: setup node + uses: actions/setup-node@v1 + with: + node-version: 12 + - name: install Rust stable + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + - name: install webkit2gtk (ubuntu only) + if: matrix.platform == 'ubuntu-latest' + run: | + sudo apt-get update + sudo apt-get install -y webkit2gtk-4.0 + - name: install app dependencies and build it + run: yarn && yarn build + - uses: tauri-apps/tauri-action@v0 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tagName: app-v__VERSION__ # 这个操作会自动将 \_\_VERSION\_\_ 替换为应用的版本号 + releaseName: 'App v__VERSION__' + releaseBody: 'See the assets to download this version and install.' + releaseDraft: true + prerelease: false +``` + +3. 就在上面 `-name: install app dependencies and build it` 你需要新增以下步骤 + +```yml +- name: import windows certificate + if: matrix.platform == 'windows-latest' + env: + WINDOWS_CERTIFICATE: ${{ secrets.WINDOWS_CERTIFICATE }} + WINDOWS_CERTIFICATE_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }} + run: | + New-Item -ItemType directory -Path certificate + Set-Content -Path certificate/tempCert.txt -Value $env:WINDOWS_CERTIFICATE + certutil -decode certificate/tempCert.txt certificate/certificate.pfx + Remove-Item -path certificate -include tempCert.txt + Import-PfxCertificate -FilePath certificate/certificate.pfx -CertStoreLocation Cert:\CurrentUser\My -Password (ConvertTo-SecureString -String $env:WINDOWS_CERTIFICATE_PASSWORD -Force -AsPlainText) +``` + +4. 保存并推送到仓库。 + +5. 您的工作流现在可以导入您的 Windows 证书并将其导入 GitHub Actions 程序,从而实现自动代码签名! + +## Azure Key Vault + +你可以通过提供 Azure Key Vault 的证书和凭据对 Windows 可执行文件进行签名。 + +:::note +本指南使用 [relic],因为它支持基于秘密的身份验证,如果你喜欢,你可以配置其他工具。 +要下载 relic,请查看它的[发布页面][relic releases page]或运行 `go install github.com/sassoftware/relic/v8@latest`。 +::: + +1. Key Vault + +在 [Azure 门户]中,点击 “create” 按钮,导航到 [Key vaults 服务]来创建一个新的密钥库。 +记住“密钥库名称”,因为你将需要这些資訊来配置证书 URL。 + +2. 证书 + +创建密钥库后,选择它并转到 “Objects > Certificates” 页面创建新证书,并单击 “Generate/Import” 按钮。 +记住“证书名称”,因为你需要这些資訊来配置证书的 URL。 + +3. Tauri 配置 + +[relic] 使用配置文件来确定应该使用哪个签名密钥。对于 Azure Key Vault,你还需要证书 URL。 +在 `src-tauri` 文件夹中创建一个 `relic.conf` 文件,并配置 relic 以使用你的证书: + +```yml title=src-tauri/relic.conf +tokens: + azure: + type: azure + +keys: + azure: + token: azure + id: https://\.vault.azure.net/certificates/\ +``` + +注意,你必须将 \ 和 \ 替换为前面步骤中的适当名称。 + +要配置 Tauri 使用 Azure Key Vault 配置进行签名,请更改 [bundle > windows > signCommand] 配置值: + +```json title=tauri.conf.json +{ + "bundle": { + "windows": { + "signCommand": "relic sign --file %1 --key azure --config relic.conf" + } + } +} +``` + +4. 凭证 + +[relic] 必须通过 Azure 进行身份验证才能加载证书。 +在 Azure portal 的登录页面中,转到 “Microsoft Entra ID” 服务,并转到 “Manage > App registrations” 页面。 +点击 “New registration” 创建新应用。创建应用后,您将重定向到应用详情页面,在那里您可以看到“应用(客户端)ID” 和“目录(租户)ID” 值。 +将这些 ID 分别设置为 `AZURE_VAULT_ID` 和 `AZURE_TENANT_ID` 环境变量。 + +在 “Manage > Certificates & secrets” 页面单击 “New client secret” 按钮,并将 “Value” 列中的文本设置为 “AZURE_CLIENT_SECRET” 环境变量的值。 + +设置好所有凭据后,回到您的密钥库页面并导航到“访问控制(IAM)”页面。 +您必须为新创建的应用程序分配 “Key Vault Certificate User” 和 “Key Vault Crypto User” 角色。 + +设置好所有这些变量后,运行 `tauri build` 将生成签名的Windows安装程序! + +## 自定义签名命令 + +在上面的 [Azure Key Vault](#azure-key-vault)文档中,我们使用了一个强大的 Tauri Windows 签名配置来强制 Tauri CLI 使用特殊的 shell 命令来签署 Windows 安装程序可执行文件。 +[bundle > windows > signCommand] 配置选项可以用于使用任何能够签署 Windows 可执行文件的代码签名工具。 + +:::tip +在交叉编译 Linux 和 macOS 机器上的 Windows 安装程序时,你**必须**使用自定义的 sign 命令,因为默认实现只能在 Windows 机器上工作。 +::: + +[Azure 门户]: https://portal.azure.com +[Key vaults service]: https://portal.azure.com/#browse/Microsoft.KeyVault%2Fvaults +[Microsoft 文档]: https://learn.microsoft.com/en-us/windows-hardware/drivers/dashboard/code-signing-cert-manage +[提交您的应用程序]: https://www.microsoft.com/en-us/wdsi/filesubmission/ +[encrypted secrets]: https://docs.github.com/en/actions/reference/encrypted-secrets +[`tauri-action` 发布模板]: https://github.com/tauri-apps/tauri-action +[relic]: https://github.com/sassoftware/relic +[relic releases page]: https://github.com/sassoftware/relic/releases/ +[bundle > windows > signCommand]: /reference/config/#signcommand +[SmartScreen]: https://en.wikipedia.org/wiki/Microsoft_SmartScreen +[Microsoft Store]: https://apps.microsoft.com/ diff --git a/src/content/docs/zh-tw/distribute/aur.mdx b/src/content/docs/zh-tw/distribute/aur.mdx new file mode 100644 index 0000000000..7389e81c50 --- /dev/null +++ b/src/content/docs/zh-tw/distribute/aur.mdx @@ -0,0 +1,162 @@ +--- +title: AUR +sidebar: + order: 1 +--- + +# 发布到 Arch 用户仓库 + +## 设置 + +首先,前往 `https://aur.archlinux.org` 创建一个账户。确保新增正确的 SSH 密钥。接下来,使用以下命令克隆一个空的 Git 存储库。 + +```sh +git clone https://aur.archlinux.org/your-repo-name +``` + +完成上述步骤后,创建一个名为 `PKGBUILD` 的文件。一旦文件创建成功,您可以继续进行下一步。 + +### 编写一个 PKGBUILD 文件 + +```ini title="PKGBUILD" +pkgname= +pkgver=1.0.0 +pkgrel=1 +pkgdesc="Description of your app" +arch=('x86_64' 'aarch64') +url="https://github.com//" +license=('mit') +depends=('cairo' 'desktop-file-utils' 'gdk-pixbuf2' 'glib2' 'gtk3' 'hicolor-icon-theme' 'libsoup' 'pango' 'webkit2gtk') +options=('!strip' '!emptydirs') +install=${pkgname}.install +source_x86_64=("https://github.com///releases/download/v$pkgver/appname_"$pkgver"_amd64.deb") +source_aarch64=("https://github.com///releases/download/v$pkgver/appname_"$pkgver"_arm64.deb") +``` + +- 在文件的顶部,定义你的包名并将其赋值给变量 `pkgname`。 +- 设置你的 `pkgver` 变量。通常最好在源变量中使用这个变量来增加可维护性。 +- `pkgdesc` 变量在你的 aur 仓库页面上告诉访问者你的应用程序是做什么的。 +- `arch` 变量控制哪些架构可以安装你的软件包。 +- `url` 变量虽然不是必需的,但有助于使您的软件包看起来更专业。 +- `install` 变量定义一个运行安装命令的文件。 +- `depends` 变量包含了一系列必需的项目,这些项目是使你的应用程序运行所必须的。对于任何 Tauri 应用程序,你必须包括上述所有依赖项。 +- `source` 变量是必需的,它定义了上游软件包所在的位置。您可以通过在变量名末尾新增架构来使 `source` 与特定架构相关联。 + +### 生成 `SRCINFO` + +为了将您的 repo 推送到 aur,您必须生成一个 `srcinfo` 文件。可以使用以下命令完成此操作。 + +```sh +makepkg --printsrcinfo >> .SRCINFO +``` + +### 测试 + +测试这个应用程序非常简单。你只需要在与 pkgbuild 文件相同的目录中运行 makepkg -f 命令,然后看它是否正常工作。 + +### 发布 + +最后,在测试阶段结束后,您可以使用以下命令将应用程序发布到用户存储库。 + +```sh +git add . + +git commit -m "Initial Commit" + +git push +``` + +如果一切顺利,你的仓库现在应该会出现在 AUR 网站上。 + +## 示例 + +### 从 Debian 软件包中提取 + +```ini title="PKGBUILD" +# Maintainer: +# Contributor: +pkgname= +pkgver=1.0.0 +pkgrel=1 +pkgdesc="Description of your app" +arch=('x86_64' 'aarch64') +url="https://github.com//" +license=('mit') +depends=('cairo' 'desktop-file-utils' 'gdk-pixbuf2' 'glib2' 'gtk3' 'hicolor-icon-theme' 'libsoup' 'pango' 'webkit2gtk') +options=('!strip' '!emptydirs') +install=${pkgname}.install +source_x86_64=("https://github.com///releases/download/v$pkgver/appname_"$pkgver"_amd64.deb") +source_aarch64=("https://github.com///releases/download/v$pkgver/appname_"$pkgver"_arm64.deb") +sha256sums_x86_64=('ca85f11732765bed78f93f55397b4b4cbb76685088553dad612c5062e3ec651f') +sha256sums_aarch64=('ed2dc3169d34d91188fb55d39867713856dd02a2360ffe0661cb2e19bd701c3c') +package() { + + # Extract package data + tar -xz -f data.tar.gz -C "${pkgdir}" + +} +``` + +```ini title="my-tauri-app.install" +post_install() { + gtk-update-icon-cache -q -t -f usr/share/icons/hicolor + update-desktop-database -q +} + +post_upgrade() { + post_install +} + +post_remove() { + gtk-update-icon-cache -q -t -f usr/share/icons/hicolor + update-desktop-database -q +} + +``` + +### 从源码构建 + +```ini title="PKGBUILD" +# Maintainer: +pkgname=-git +pkgver=1.1.0 +pkgrel=1 +pkgdesc="Description of your app" +arch=('any') +url="https://github.com//" +license=('mit') +depends=('cairo' 'desktop-file-utils' 'gdk-pixbuf2' 'glib2' 'gtk3' 'hicolor-icon-theme' 'libsoup' 'pango' 'webkit2gtk') +makedepends=('git' 'file' 'openssl' 'appmenu-gtk-module' 'libappindicator-gtk3' 'librsvg' 'base-devel' 'curl' 'wget' 'rustup' 'npm' 'nodejs' 'dpkg') +provides=('') +conflicts=('' '') +options=('!strip' '!emptydirs') +source=('git+https://github.com//') +sha256sums=('SKIP') +prepare() { + cd + npm install + npm run tauri build +} +package() { + cd "$srcdir"//src-tauri/target/*unknown-linux*/release/bundle/deb + dpkg-deb -x *.deb here + cd here + + install -Dm755 usr/bin/myapp "$pkgdir"/usr/bin/myapp + + # Install desktop file + install -Dm644 usr/share/applications/myapp.desktop "$pkgdir"/usr/share/applications/myapp.desktop + + # Install icons + install -Dm644 usr/share/icons/hicolor/128x128/apps/myapp.png "$pkgdir"/usr/share/icons/hicolor/128x128/apps/myapp.png + install -Dm644 usr/share/icons/hicolor/256x256@2/apps/myapp.png "$pkgdir"/usr/share/icons/hicolor/256x256@2/apps/myapp.png + install -Dm644 usr/share/icons/hicolor/32x32/apps/myapp.png "$pkgdir"/usr/share/icons/hicolor/32x32/apps/myapp.png + # Extract package data +} +``` + +[`async_runtime::spawn`]: https://docs.rs/tauri/2.0.0/tauri/async_runtime/fn.spawn.html +[`serde::serialize`]: https://docs.serde.rs/serde/trait.Serialize.html +[`serde::deserialize`]: https://docs.serde.rs/serde/trait.Deserialize.html +[`thiserror`]: https://github.com/dtolnay/thiserror +[`result`]: https://doc.rust-lang.org/std/result/index.html diff --git a/src/content/docs/zh-tw/distribute/dmg.mdx b/src/content/docs/zh-tw/distribute/dmg.mdx new file mode 100644 index 0000000000..8675806a64 --- /dev/null +++ b/src/content/docs/zh-tw/distribute/dmg.mdx @@ -0,0 +1,127 @@ +--- +title: DMG +sidebar: + order: 1 +--- + +import CommandTabs from '@components/CommandTabs.astro'; +import { Image } from 'astro:assets'; +import StandardDmgLight from '@assets/distribute/dmg/standard-dmg-light.png'; +import StandardDmgDark from '@assets/distribute/dmg/standard-dmg-dark.png'; + +DMG(苹果磁盘镜像)格式是一个常见的 macOS 安装程序文件,它将你的 [App Bundle][App Bundle 分发指南]包裹在一个用户友好的安装窗口中。 + +安装程序窗口包括你的应用程序图标和应用程序文件夹图标,用户需要将应用程序图标拖动到应用程序文件夹图标来安装它。 +对于发布在 App Store 之外的 macOS 应用来说,这是最常见的安装方法。 + +本指南仅涵盖使用 DMG 格式在 App Store 之外发布应用程序的细节。 +有关 macOS 分发选项和配置的更多資訊,请参阅 [App Bundle 分发指南]。 +要在 App Store 中发布你的 macOS 应用,请参阅 [App Store 分发指南]。 + +要为你的应用创建一个苹果磁盘镜像(DMG),你可以使用 Tauri 命令行并在 Mac 电脑上运行 `tauri build` 命令。 + + + +Standard DMG window +Standard DMG window + +## 窗口背景 + +你可以用 [`tauri.conf.json > bundle > macOS > dmg > background`] 配置选项设置 DMG 安装窗口的自定义背景图像。 + +```json title="tauri.conf.json" ins={4-6} +{ + "bundle": { + "macOS": { + "dmg": { + "background": "./images/" + } + } + } +} +``` + +例如,你的 DMG 背景图像可以包括一个箭头,告诉用户它必须将应用程序图标拖动到应用程序文件夹。 + +## 窗口大小和位置 + +默认窗口大小为 660x400。如果你需要不同的尺寸来适应你的自定义背景图片,请设置 [`tauri.conf.json > bundle > macOS > dmg > windowSize`] 配置。 + +```json title="tauri.conf.json" ins={5-8} +{ + "bundle": { + "macOS": { + "dmg": { + "windowSize": { + "width": 800, + "height": 600 + } + } + } + } +} +``` + +此外,你可以通过 [`tauri.conf.json > bundle > macOS > dmg > windowPosition`] 设置初始窗口位置。 + +```json title="tauri.conf.json" ins={5-8} +{ + "bundle": { + "macOS": { + "dmg": { + "windowPosition": { + "x": 400, + "y": 400 + } + } + } + } +} +``` + +## 图标位置 + +你可以使用 [appPosition] and [applicationFolderPosition] 配置值分别更改 app 和*应用程序文件夹*的图标位置。 + +```json title="tauri.conf.json" ins={5-12} +{ + "bundle": { + "macOS": { + "dmg": { + "appPosition": { + "x": 180, + "y": 220 + }, + "applicationFolderPosition": { + "x": 480, + "y": 220 + } + } + } + } +} +``` + +:::caution +由于一个已知的问题,在 CI/CD 平台上创建 DMG 时,图标大小和位置不适用。 +请参阅 [tauri-apps/tauri#1731] 了解更多資訊。 +::: + +[App Bundle 分发指南]: /distribute/macos-application-bundle/ +[App Store 分发指南]: /distribute/app-store/ +[appPosition]: /reference/config/#appposition +[applicationFolderPosition]: /reference/config/#applicationfolderposition +[tauri-apps/tauri#1731]: https://github.com/tauri-apps/tauri/issues/1731 diff --git a/src/content/docs/zh-tw/distribute/flatpak.mdx b/src/content/docs/zh-tw/distribute/flatpak.mdx new file mode 100644 index 0000000000..f1bdb6e3fb --- /dev/null +++ b/src/content/docs/zh-tw/distribute/flatpak.mdx @@ -0,0 +1,153 @@ +--- +title: Flathub +sidebar: + order: 1 +--- + +import { Tabs, TabItem, Card } from '@astrojs/starlight/components'; + +要了解 Flatpak 的工作原理的详细資訊,您可以阅读[构建您的第一个 Flatpak](https://docs.flatpak.org/en/latest/first-build.html)。 + +本指南假设您希望通过 [Flathub](https://flathub.org/) 来分发您的 Flatpak,这是最常用的 Flatpak 分发平台。如果您计划使用其他平台,请参阅它们的文档。 + +### 前置条件 + +为了在 Flatpak 运行时中测试您的应用程序,您可以先在本地构建 Flatpak,然后再将应用程序上传到 Flathub。如果您想快速共享开发版本,这也会很有帮助。 + +**1. 安装 `flatpak` 和 `flatpak-builder`** + +要在本地构建 Flatpaks,您需要使用 `flatpak` 和 `flatpak-builder` 工具。例如,在 Ubuntu 上您可以运行以下命令。 + + + + +```sh +sudo apt install flatpak flatpak-builder +``` + + + + +```sh +sudo pacman -S --needed flatpak flatpak-builder +``` + + + + +```sh +sudo dnf install flatpak flatpak-builder +``` + + + + +```sh +sudo emerge --ask \ +sys-apps/flatpak \ +dev-util/flatpak-builder +``` + + + + +**2. 安装 Flatpak 运行时** + +```shell +flatpak install flathub org.Gnome.Platform//46 org.Gnome.Sdk//46 +``` + +**3. [为你的 tauri-app 构建 .deb 文件](https://deploy-preview-2279--tauri-v2.netlify.app/reference/config/#bundleconfig)** + +**4. 创建 manifest** + +```yaml +id: org.your.id + +runtime: org.gnome.Platform +runtime-version: '46' +sdk: org.gnome.Sdk + +command: tauri-app +finish-args: + - --socket=wayland # Permission needed to show the window + - --socket=fallback-x11 # Permission needed to show the window + - --device=dri # OpenGL, not necessary for all projects + - --share=ipc + +modules: + - name: binary + buildsystem: simple + sources: + - type: file + url: https://github.com/your_username/your_repository/releases/download/v1.0.1/yourapp_1.0.1_amd64.deb + sha256: 08305b5521e2cf0622e084f2b8f7f31f8a989fc7f407a7050fa3649facd61469 # This is required if you are using a remote source + only-arches: [x86_64] #This source is only used on x86_64 Computers + # This path points to the binary file which was created in the .deb bundle. + # Tauri also creates a folder which corresponds to the content of the unpacked .deb. + build-commands: + - ar -x *.deb + - tar -xf data.tar.gz + - 'install -Dm755 usr/bin/tauri-app /app/bin/tauri-app' + - install -Dm644 usr/share/applications/yourapp.desktop /app/share/applications/org.your.id.desktop + - install -Dm644 usr/share/icons/hicolor/128x128/apps/yourapp.png /app/share/icons/hicolor/128x128/apps/org.your.id.png + - install -Dm644 usr/share/icons/hicolor/32x32/apps/yourapp.png /app/share/icons/hicolor/32x32/apps/org.your.id.png + - install -Dm644 usr/share/icons/hicolor/256x256@2/apps/yourapp.png /app/share/icons/hicolor/256x256@2/apps/org.your.id.png + - install -Dm644 org.your.id.metainfo.xml /app/share/metainfo/org.your.id.rosary.metainfo.xml +``` + +Gnome 46 运行时包含了标准 Tauri 应用程序的所有依赖项,并且它们的版本都是正确的。 + +**5. 安装并测试该应用程序** + +```shell + +# Install the flatpak +flatpak -y --user install + +# Run it +flatpak run + +# Update it +flatpak -y --user update +``` + +## 新增额外的库 + +如果您的最终二进制文件比默认的 tauri 应用程序需要更多的库,您需要在 flatpak 清单中新增它们。 +有两种方法可以做到这一点。对于快速本地开发,可能只需将已经构建好的库文件(.so)从本地系统包含进来就可以工作。 +然而,这不推荐用于 flatpak 的最终构建,因为您本地的库文件并非为 flatpak 运行时环境构建而成。 +这可能会引入各种很难找到的错误。 +因此,建议将程序依赖的库从源代码在 flatpak 内部进行构建步骤。 + +## 提交到 flathub + +**_1. Fork [Flathub 存储库](https://github.com/flathub/flathub/fork)_** + +**_2. 克隆 Fork 的仓库_** + +```shell +git clone --branch=new-pr git@github.com:your_github_username/flathub.git +``` + +**_3. 进入存储库_** + +```shell +cd flathub +``` + +**_4. 创建一个新分支_** + +```shell +git checkout -b your_app_name +``` + +**_5. 将您的应用程序清单新增到分支中。提交更改,然后推送它们。_** + +**_6. 在 github 上对 `new-pr` 分支发起一个 pull request。_** + +**_7. 您的应用现在将进入审核流程,可能会要求您对项目进行更改。_** + +当您的拉取请求被批准后,您将收到一个编辑应用程序存储库的邀请。从此以后,您可以持续更新您的应用程序。 + +您可以在 [flatpak 文档](https://docs.flatpak.org/en/latest/dependencies.html#bundling)中阅读更多相关資訊。 diff --git a/src/content/docs/zh-tw/distribute/rpm.mdx b/src/content/docs/zh-tw/distribute/rpm.mdx new file mode 100644 index 0000000000..f9e7fd89ed --- /dev/null +++ b/src/content/docs/zh-tw/distribute/rpm.mdx @@ -0,0 +1,339 @@ +--- +title: RPM +sidebar: + order: 1 +--- + +import CommandTabs from '@components/CommandTabs.astro'; + +# 打包为 RPM + +:::note +这个指南中的一些部分是可选的。这包括配置脚本和其他特定步骤。根据您的具体需求和要求,可以自由地调整指示內容。 +::: + +本指南介绍了如何分发和管理 RPM 软件包,包括获取软件包資訊、配置脚本、设置依赖关系和签名软件包。 + +## RPM 包配置 + +Tauri 允许您通过新增脚本、设置依赖项、新增许可证、包含自定义文件等来配置 RPM 软件包。 +有关可配置选项的详细資訊,请参考:[RpmConfig](https://v2.tauri.app/reference/config/#rpmconfig)。 + +### 新增 post、pre-install/remove 脚本到安装包 + +RPM 软件包管理器允许您在安装或删除软件包之前或之后运行脚本。例如,您可以使用这些脚本在软件包安装后启动一个服务。 + +下面是新增这些脚本的示例: + +1. 在项目的 `src-tauri` 目录下创建一个名为 `scripts` 的文件夹。 + +```bash +mkdir src-tauri/scripts +``` + +2. 在文件夹中创建脚本文件。 + +```bash +touch src-tauri/scripts/postinstall.sh \ +touch src-tauri/scripts/preinstall.sh \ +touch src-tauri/scripts/preremove.sh \ +touch src-tauri/scripts/postremove.sh +``` + +现在如果我们查看 `/src-tauri/scripts`,我们将看到。 + +```bash +ls src-tauri/scripts/ +postinstall.sh postremove.sh preinstall.sh preremove.sh +``` + +3. 向脚本新增一些内容。 + +```bash title="preinstall.sh" +echo "-------------" +echo "This is pre" +echo "Install Value: $1" +echo "Upgrade Value: $1" +echo "Uninstall Value: $1" +echo "-------------" +``` + +```bash title="postinstall.sh" +echo "-------------" +echo "This is post" +echo "Install Value: $1" +echo "Upgrade Value: $1" +echo "Uninstall Value: $1" +echo "-------------" +``` + +```bash title="preremove.sh" +echo "-------------" +echo "This is preun" +echo "Install Value: $1" +echo "Upgrade Value: $1" +echo "Uninstall Value: $1" +echo "-------------" +``` + +```bash title="postremove.sh" +echo "-------------" +echo "This is postun" +echo "Install Value: $1" +echo "Upgrade Value: $1" +echo "Uninstall Value: $1" +echo "-------------" +``` + +4. 将脚本新增到 `tauri.conf.json` 文件中 + +```json title="tauri.conf.json" +{ + "bundle": { + "linux": { + "rpm": { + "epoch": 0, + "files": {}, + "release": "1", + // 在此新增脚本 + "preInstallScript": "/path/to/your/project/src-tauri/scripts/prescript.sh", + "postInstallScript": "/path/to/your/project/src-tauri/scripts/postscript.sh", + "preRemoveScript": "/path/to/your/project/src-tauri/scripts/prescript.sh", + "postRemoveScript": "/path/to/your/project/src-tauri/scripts/postscript.sh" + } + } + } +} +``` + +### 设置 Conflict、 Provides、 Depends、 Files、 Obsoletes、 DesktopTemplate 和 Epoch + +- **conflict**:防止安装与另一个包冲突的包。 + 例如,如果您更新了应用程序所依赖的 RPM 包,但新版本与您的应用程序不兼容。 + +- **provides**:列出应用程序提供的 RPM 依赖项。 + +- **depends**:列出应用程序运行所需的 RPM 依赖项。 + +- **files**:指定包中包含的文件。 + +- **obsoletes**:列出您的应用程序废弃的 RPM 依赖项。 + +:::note +如果安装了这个软件包,那么被列为“过时”的软件包将会在存在的情况下自动删除。 +::: + +- **desktopTemplate**:向包中新增自定义桌面文件。 + +- **epoch**:基于版本号定义加权依赖关系。 + +:::caution +除非必要,否则不建议使用 epoch,因为它会改变包管理器比较包版本的方式。 +有关 epoch 的更多資訊,请查看:[RPM 打包指南](https://rpm-packaging-guide.github.io/#epoch-scriptlets-and-triggers)。 +::: + +要使用这些选项,请将以下内容新增到你的 `tauri.conf.json` 文件中。 + +```json title="tauri.conf.json" +{ + "bundle": { + "linux": { + "rpm": { + "postRemoveScript": "/path/to/your/project/src-tauri/scripts/postscript.sh", + "conflicts": ["oldLib.rpm"], + "depends": ["newLib.rpm"], + "obsoletes": ["veryoldLib.rpm"], + "provides": ["coolLib.rpm"], + "desktopTemplate": "/path/to/your/project/src-tauri/desktop-template.desktop" + } + } + } +} +``` + +### 给包新增一个许可证 + +要给包新增许可证,请将以下内容新增到 `src-tauri/cargo.toml` 或者 `src-tauri/tauri.conf.json` 文件中: + +```toml title="src-tauri/cargo.toml" +[package] +name = "tauri-app" +version = "0.0.0" +description = "A Tauri App" +authors = ["you"] +edition = "2021" +license = "MIT" # add the license here +# ... rest of the file +``` + +对于 `src-tauri/tauri.conf.json` + +```json title="src-tauri/tauri.conf.json" +{ + "bundle": { + "licenseFile": "../LICENSE", // 将许可证文件路径放在此 + "license": "MIT" // 将许可证新增在此 + } +} +``` + +## 构建 RPM 包 + +要构建 RPM 包,你可以使用以下命令。 + + + +这个命令会在 `src-tauri/target/release/bundle/rpm` 目录下构建 RPM 包。 + +## 签名 RPM 包 + +Tauri 允许您在构建过程中使用系统中的密钥对包进行签名。为此,你需要生成一个 GPG 密钥。 + +#### 生成 GPG 密钥 + +要生成 GPG 密钥,可以使用以下命令。 + +```bash +gpg --gen-key +``` + +按照说明生成密钥。 + +生成密钥后,需要将其新增到环境变量中。 +你可以将以下内容新增到 .bashrc 或 .zshrc 文件中,或者直接在终端中导出。 + +```bash +export TAURI_SIGNING_RPM_KEY=$(cat /home/johndoe/my_super_private.key) +``` + +如果密钥有密码,可以将其新增到环境变量中。 + +```bash +export TAURI_SIGNING_RPM_KEY_PASSPHRASE=password +``` + +现在你可以使用以下命令构建包。 + + + +### 验证签名 + +:::note +只有在本地测试签名时才应该这样做。 +::: + +在验证签名之前,需要先创建并导入公钥到 RPM 数据库。 + +```bash +gpg --export -a 'Tauri-App' > RPM-GPG-KEY-Tauri-App +``` + +```bash +sudo rpm --import RPM-GPG-KEY-Tauri-App +``` + +现在密钥已经导入,我们必须编辑 `~/.rpmmacros` 文件来使用密钥。 + +```bash title="~/.rpmmacros" +%_signature gpg +%_gpg_path /home/johndoe/.gnupg +%_gpg_name Tauri-App +%_gpgbin /usr/bin/gpg2 +%__gpg_sign_cmd %{__gpg} \ + gpg --force-v3-sigs --digest-algo=sha1 --batch --no-verbose --no-armor \ + --passphrase-fd 3 --no-secmem-warning -u "%{_gpg_name}" \ + -sbo %{__signature_filename} %{__plaintext_filename} +``` + +最后,你可以使用以下命令来验证这个包。 + +```bash +rpm -v --checksig tauri-app-0.0.0-1.x86_64.rpm +``` + +## 调试 RPM 包 + +在本节中,我们将看到如何通过检查 RPM 包的内容来调试 RPM 包以及获取有关包的資訊。 + +### 获取关于包的資訊 + +要获取有关包的資訊,如版本、发行版和架构, +使用下面的命令: + +```bash +rpm -qip package_name.rpm +``` + +### 查询包的详细資訊 + +例如,如果你想获取包的名称、版本、发行版、架构和大小,可以使用以下命令。 + +```bash +rpm -qp --queryformat '[%{NAME} %{VERSION} %{RELEASE} %{ARCH} %{SIZE}\n]' package_name.rpm +``` + +:::note +_`--queryformat`_ 是一个格式字符串,可用于获取关于包的特定資訊。 +可以检索的資訊来自 rpm -qip 命令。 +::: + +### 检查包的内容 + +要检查包的内容,可以使用以下命令。 + +```bash +rpm -qlp package_name.rpm +``` + +该命令将列出该包中包含的所有文件。 + +### 调试脚本 + +要调试 post/pre-install/remove 脚本,使用以下命令。 + +```bash +rpm -qp --scripts package_name.rpm +``` + +这个命令会打印脚本的内容。 + +### 检查依赖关系 + +要检查包的依赖关系,使用以下命令。 + +```bash +rpm -qp --requires package_name.rpm +``` + +### 列出依赖于特定包的包 + +要列出依赖于特定包的包,可以使用以下命令。 + +```bash +rpm -q --whatrequires package_name.rpm +``` + +### 调试安装问题 + +如果您在安装 RPM 包期间遇到问题, +你可以使用 `-vv`(very verbose)选项来获得详细的输出。 + +```bash +rpm -ivvh package_name.rpm +``` + +或者对于已经安装的包。 + +```bash +rpm -Uvvh package_name.rpm +``` diff --git a/src/content/docs/zh-tw/distribute/snapcraft.mdx b/src/content/docs/zh-tw/distribute/snapcraft.mdx new file mode 100644 index 0000000000..08c09a6507 --- /dev/null +++ b/src/content/docs/zh-tw/distribute/snapcraft.mdx @@ -0,0 +1,165 @@ +--- +title: Snapcraft +sidebar: + order: 1 +--- + +## 前置条件 + +import { Tabs, TabItem, Card } from '@astrojs/starlight/components'; + +**1. 安装 `snap`** + +{/* prettier-ignore */} + + + ```shell + sudo apt install snapd + ``` + + + ```shell + sudo pacman -S --needed git base-devel + git clone https://aur.archlinux.org/snapd.git + cd snapd + makepkg -si + sudo systemctl enable --now snapd.socket + sudo systemctl start snapd.socket + sudo systemctl enable --now snapd.apparmor.service + ``` + + + ```shell + sudo dnf install snapd + # Enable classic snap support + sudo ln -s /var/lib/snapd/snap /snap + ``` + + 然后重新启动系统。 + + + + +**2. 安装 snap 基座** + +```shell +sudo snap install core22 +``` + +**3. 安装 `snapcraft`** + +```shell +sudo snap install snapcraft --classic +``` + +## 配置 + +1. 创建一个 UbuntuOne 账号。 +2. 请前往 [Snapcraft](https://snapcraft.io) 网站注册一个应用名称。 +3. 在你项目的根目录创建一个 snapcraft.yaml 文件。 +4. 调整 snapcraft.yaml 文件中的 name。 + +```yaml +name: appname +base: core22 +version: '0.1.0' +summary: Your summary # 79 char long summary +description: | + Your description + +grade: stable +confinement: strict + +layout: + /usr/libexec/webkit2gtk-4.1: + symlink: $SNAP/usr/libexec/webkit2gtk-4.1 + /usr/lib/x86_64-linux-gnu/webkit2gtk-4.1: + symlink: $SNAP/usr/lib/x86_64-linux-gnu/webkit2gtk-4.1 + /usr/lib/aarch64-linux-gnu/webkit2gtk-4.1: + symlink: $SNAP/usr/lib/aarch64-linux-gnu/webkit2gtk-4.1 + /usr/lib/webkit2gtk-4.1/injected-bundle: + symlink: $SNAP/usr/lib/webkit2gtk-4.1/injected-bundle + +apps: + appname: + command: usr/bin/appname + desktop: usr/share/applications/appname.desktop + plugs: + - wayland + - x11 + +package-repositories: + - type: apt + components: [main] + suites: [noble] + key-id: 78E1918602959B9C59103100F1831DDAFC42E99D + url: http://ppa.launchpad.net/snappy-dev/snapcraft-daily/ubuntu + +parts: + build-app: + plugin: dump + build-snaps: + - node/20/stable + - rustup/latest/stable + build-packages: + - libwebkit2gtk-4.1-dev + - build-essential + - curl + - wget + - file + - libxdo-dev + - libssl-dev + - libayatana-appindicator3-dev + - librsvg2-dev + - dpkg + stage-packages: + - libwebkit2gtk-4.1-0 + - libayatana-appindicator3-1 + - libglu1-mesa + - freeglut3 + source: . + override-build: | + set -eu + npm install + npm run tauri build -- --bundles deb + dpkg -x src-tauri/target/release/bundle/deb/*.deb $SNAPCRAFT_PART_INSTALL/ + sed -i -e "s|Icon=appname|Icon=/usr/share/icons/hicolor/32x32/apps/appname.png|g" $SNAPCRAFT_PART_INSTALL/usr/share/applications/appname.desktop +``` + +### 解释 + +- `name` 变量定义了你的应用程序的名称,并且必须设置为之前注册的名称。 +- `base` 变量定义了你正在使用的核心。 +- `version` 变量定义了版本,并且应该随着源代码库的每次更改而更新。 +- `apps` 部分允许你公开桌面和二进制文件以供用户运行你的应用。 +- `package-repositories` 部分允许你新增一个包仓库来帮助你满足你的依赖。 +- `build-packages`/`build-snaps` 为你的 snap 定义构建依赖。 +- `stage-packages`/`stage-snaps` 定义了你的 snap 的运行时依赖。 +- `override-pull` 部分在拉取数据源之前运行一系列命令。 +- `craftctl default` 执行默认的拉取命令。 +- `organize` 部分将文件移动到合适的目录,以便二进制文件和桌面文件可以暴露给 `apps` 部分。 + +## 构建 + +```sh +sudo snapcraft +``` + +## 测试 + +```shell +snap run your-app +``` + +## 手动发布 + +```shell +snapcraft login # 用你的 UbuntuOne 凭证登录 +snapcraft upload --release=stable mysnap_latest_amd64.snap +``` + +## 自动构建 + +1. 在你的 app 开发者页面上,点击 `builds` 选项卡。 +2. 点击 `login with github`. +3. 输入存储库的详细資訊。 diff --git a/src/content/docs/zh-tw/index.mdx b/src/content/docs/zh-tw/index.mdx new file mode 100644 index 0000000000..7399dfeba2 --- /dev/null +++ b/src/content/docs/zh-tw/index.mdx @@ -0,0 +1,63 @@ +--- +title: Tauri 2.0 +description: 跨平台應用程式建置工具包 +i18nReady: true +editUrl: false +lastUpdated: false +template: splash +tableOfContents: false +prev: false +next: false +hero: + tagline: 建立小型、快速、安全、跨平台的應用程式 + image: + file: ../../../assets/logo-outline.svg + actions: + - text: 快速入門 + link: /zh-tw/start/ + icon: right-arrow + variant: primary + - text: Tauri 1.0 文件 + link: https://v1.tauri.app + icon: external + variant: minimal +--- + +import { Card, CardGrid, LinkCard } from '@astrojs/starlight/components'; +import Cta from '@fragments/cta.mdx'; + +
+ +
+
+
+ +
+ + + +
+ + + + 將你現有的網路技術堆疊帶到 Tauri 或開始新的專案。 + Tauri 支援任何前端框架,所以你不需要改變你的技術堆疊。 + + + 使用單一程式碼函式庫為 Linux、macOS、Windows、Android 和 iOS + 建立你的應用程式。 + + + 用 JavaScript 編寫前端,用 Rust 編寫應用程式邏輯, 並使用 Swift 和 Kotlin + 在系統中深入整合。 + + + Tauri 團隊的首要目標,推動我們的首要任務和最大的創新。 + + + 使用作業系統的本機網頁渲染器,Tauri 應用程式的體積可達最小 600KB。 + + + 以效能和安全性為中心,Rust 是下一代應用程式的語言。 + + diff --git a/src/content/docs/zh-tw/learn/window-customization.mdx b/src/content/docs/zh-tw/learn/window-customization.mdx new file mode 100644 index 0000000000..3e63f02eb7 --- /dev/null +++ b/src/content/docs/zh-tw/learn/window-customization.mdx @@ -0,0 +1,221 @@ +--- +title: 窗口自定义 +tableOfContents: + maxHeadingLevel: 4 +--- + +import { Icon } from '@astrojs/starlight/components'; + +Tauri 提供了许多自定义应用程序窗口外观的选项。您可以创建自定义标题栏、透明窗口、强制大小约束等。 + +## 配置 + +有三种方法可以修改 Window 的配置。 + +- [通过 + tauri.conf.json](/zh-tw/reference/config/#windowconfig) +- [通过 JavaScript + API](/zh-tw/reference/javascript/api/namespacewindow/#window) +- [通过 Rust 的 + Window](https://docs.rs/tauri/2.0.0/tauri/window/struct.Window.html) + +## 用法 + +- [创建自定义标题栏](#创建自定义标题栏) +- [(macOS) 具有自定义窗口背景颜色的透明标题栏](#macos-具有自定义窗口背景颜色的透明标题栏) + +### 创建自定义标题栏 + +这些窗口特性的一个常用用途是创建自定义标题栏。这篇简短的教程将指导你完成这个过程。 + +:::note +对于 macOS,使用自定义标题栏也会失去系统提供的某些功能,比如[移动或对齐窗口](https://support.apple.com/start/mac-help/work-with-app-windows-mchlp2469/mac)。 +另一种自定义标题栏但保留原生功能的方法是使标题栏透明并设置窗口背景色,参见 [(macOS) 具有自定义窗口背景颜色的透明标题栏](#macos-具有自定义窗口背景颜色的透明标题栏)的用法。 +::: + +#### tauri.conf.json + +在你的 `tauri.conf.json` 文件中将 `decorations` 设置为 `false`。 + +```json title="tauri.conf.json" {4} +"tauri": { + "windows": [ + { + "decorations": false + } + ] +} +``` + +#### 权限 + +在能力(capability)文件中新增窗口权限。 + +默认情况下,所有外掛命令都被阻止,无法访问。你必须在你的 `capabilities` 配置中定义一个权限列表。 + +更多資訊请参见[访问控制列表](/zh-tw/reference/acl/)。 + +```json title="src-tauri/capabilities/default.json" ins={6} +{ + "$schema": "../gen/schemas/desktop-schema.json", + "identifier": "main-capability", + "description": "Capability for the main window", + "windows": ["main"], + "permissions": ["core:window:default", "core:window:allow-start-dragging"] +} +``` + +| 权限 | 描述 | +| --------------------------------------- | ------------------------------------------------------------------ | +| `window:default` | 外掛的默认权限。除了 `window:allow-start-dragging`。 | +| `window:allow-close` | 在没有预先配置有效範圍的情况下,启用 close 命令。 | +| `window:allow-minimize` | 在没有预先配置有效範圍的情况下,启用 minimize 命令。 | +| `window:allow-start-dragging` | 在没有预先配置有效範圍的情况下,启用 start_dragging 命令。 | +| `window:allow-toggle-maximize` | 在没有预先配置有效範圍的情况下,启用 toggle_maximize 命令。 | +| `window:allow-internal-toggle-maximize` | 在没有预先配置有效範圍的情况下,启用 internal_toggle_maximize 命令。 | + +#### CSS + +新增下面的 CSS 示例,使其保持在屏幕顶部,并为按钮新增样式。 + +```css +.titlebar { + height: 30px; + background: #329ea3; + user-select: none; + display: flex; + justify-content: flex-end; + position: fixed; + top: 0; + left: 0; + right: 0; +} +.titlebar-button { + display: inline-flex; + justify-content: center; + align-items: center; + width: 30px; + height: 30px; + user-select: none; + -webkit-user-select: none; +} +.titlebar-button:hover { + background: #5bbec3; +} +``` + +#### HTML + +将以下内容放在 `` 标签的顶部。 + +```html +
+
+ minimize +
+
+ maximize +
+
+ close +
+
+``` + +请注意,你可能需要将其余内容向下移动,以免标题栏覆盖它。 + +#### JavaScript + +使用下面的代码片段来实现按钮。 + +```javascript +import { Window } from '@tauri-apps/api/window'; + +const appWindow = new Window('main'); + +document + .getElementById('titlebar-minimize') + ?.addEventListener('click', () => appWindow.minimize()); +document + .getElementById('titlebar-maximize') + ?.addEventListener('click', () => appWindow.toggleMaximize()); +document + .getElementById('titlebar-close') + ?.addEventListener('click', () => appWindow.close()); +``` + +### (macOS) 具有自定义窗口背景颜色的透明标题栏 + +我们将创建主窗口,并从 Rust 侧更改其背景颜色。 + +从 `tauri.conf.json` 文件中删除主窗口 + + ```json title="tauri.conf.json" del={3-7} + "tauri": { + "windows": [ + { + "title": "Transparent Titlebar Window", + "width": 800, + "height": 600 + } + ], + } + ``` + +新增 `cocoa` crate 到依赖中,这样我们就可以使用它来调用 macOS 原生 API。 + + ```toml title="src-tauri/Cargo.toml" + [target."cfg(target_os = \"macos\")".dependencies] + cocoa = "0.25" + ``` + +创建主窗口并更改其背景颜色。 + + ```rust title="src-tauri/src/lib.rs" + use tauri::{TitleBarStyle, WebviewUrl, WebviewWindowBuilder}; + + fn run() { + tauri::Builder::default() + .setup(|app| { + let win_builder = + WebviewWindowBuilder::new(app, "main", WebviewUrl::default()) + .title("Transparent Titlebar Window") + .inner_size(800.0, 600.0); + + // 仅在 macOS 时设置透明标题栏 + #[cfg(target_os = "macos")] + let win_builder = win_builder.title_bar_style(TitleBarStyle::Transparent); + + let window = win_builder.build().unwrap(); + + // 仅在构建 macOS 时设置背景颜色 + #[cfg(target_os = "macos")] + { + use cocoa::appkit::{NSColor, NSWindow}; + use cocoa::base::{id, nil}; + + let ns_window = window.ns_window().unwrap() as id; + unsafe { + let bg_color = NSColor::colorWithRed_green_blue_alpha_( + nil, + 50.0 / 255.0, + 158.0 / 255.0, + 163.5 / 255.0, + 1.0, + ); + ns_window.setBackgroundColor_(bg_color); + } + } + + Ok(()) + }) + .run(tauri::generate_context!()) + .expect("error while running tauri application"); + } + ``` diff --git a/src/content/docs/zh-tw/plugin/autostart.mdx b/src/content/docs/zh-tw/plugin/autostart.mdx new file mode 100644 index 0000000000..03ef5bae12 --- /dev/null +++ b/src/content/docs/zh-tw/plugin/autostart.mdx @@ -0,0 +1,146 @@ +--- +title: 自动启动 +description: 在系统启动时自动启动应用程序。 +plugin: autostart +--- + +import PluginLinks from '@components/PluginLinks.astro'; +import Compatibility from '@components/plugins/Compatibility.astro'; + +import { Tabs, TabItem } from '@astrojs/starlight/components'; +import CommandTabs from '@components/CommandTabs.astro'; + + + +在系统启动时自动启动应用程序。 + +## 支持的平台 + + + +## 设置 + +请安装 autostart 外掛。 + + + + +使用项目的包管理器来新增依赖。 + +{' '} + + + + + + +1. 运行 `cargo add tauri-plugin-autostart` 命令,将外掛新增到项目的 `Cargo.toml` 依赖中。 + +2. 修改 `lib.rs` 来初始化外掛。 + +```rust title="lib.rs" ins={1, 6} +use tauri_plugin_autostart::MacosLauncher; + +#[cfg_attr(mobile, tauri::mobile_entry_point)] +fn run() { + tauri::Builder::default() + .plugin(tauri_plugin_autostart::init(MacosLauncher::LaunchAgent, Some(vec!["--flag1", "--flag2"]) /* arbitrary number of args to pass to your app */)) + .run(tauri::generate_context!()) + .expect("error while running tauri application"); +} +``` + +3. 你可以使用你喜欢的 JavaScript 包管理器来安装 JavaScript Guest 绑定。 + + + + + +## 用法 + +autostart 外掛有 JavaScript 和 Rust 两种版本。 + + + + +```javascript +import { enable, isEnabled, disable } from '@tauri-apps/plugin-autostart'; + +// 启用 autostart +await enable(); +// 检查 enable 状态 +console.log(`registered for autostart? ${await isEnabled()}`); +// 禁用 autostart +disable(); +``` + + + + +```rust +use tauri_plugin_autostart::MacosLauncher; +use tauri_plugin_autostart::ManagerExt; + +#[cfg_attr(mobile, tauri::mobile_entry_point)] +fn run() { + tauri::Builder::default() + .plugin(tauri_plugin_autostart::init( + MacosLauncher::LaunchAgent, + Some(vec!["--flag1", "--flag2"]), + )) + .setup(|app| { + // Get the autostart manager + let autostart_manager = app.autolaunch(); + // 启用 autostart + let _ = autostart_manager.enable(); + // 检查 enable 状态 + println!("registered for autostart? {}", autostart_manager.is_enabled().unwrap()); + // 禁用 autostart + let _ = autostart_manager.disable(); + Ok(()) + }) + .run(tauri::generate_context!()) + .expect("error while running tauri application"); +} +``` + + + + +## 权限 + +默认情况下,所有外掛命令都被阻止,无法访问。 +你必须在你的 `capabilities` 配置中定义一个权限列表。 + +更多資訊请参见[访问控制列表](/zh-tw/reference/acl/)。 + +```json title="src-tauri/capabilities/default.json" +{ + "permissions": [ + ..., + "autostart:allow-enable", + "autostart:allow-disable", + "autostart:allow-is-enabled" + ] +} +``` + +| 权限 | 描述 | +| ---------------------------- | ------------------------------------------ | +| `autostart:allow-disable` | 启用 disable 命令,不需要预先配置有效範圍。 | +| `autostart:deny-disable` | 拒绝没有预先配置有效範圍的 disable 命令。 | +| `autostart:allow-enable` | 启用 enable 命令,不需要预先配置有效範圍。 | +| `autostart:deny-enable` | 拒绝使用没有预先配置有效範圍的 enable 命令。 | +| `autostart:allow-is-enabled` | 启用没有预先配置有效範圍的 is_enabled 命令。 | +| `autostart:deny-is-enabled` | 拒绝没有预先配置有效範圍的 is_enabled 命令。 | diff --git a/src/content/docs/zh-tw/plugin/barcode-scanner.mdx b/src/content/docs/zh-tw/plugin/barcode-scanner.mdx new file mode 100644 index 0000000000..9698652a78 --- /dev/null +++ b/src/content/docs/zh-tw/plugin/barcode-scanner.mdx @@ -0,0 +1,117 @@ +--- +title: 条形码扫描器 +description: 允许您的移动应用程序使用相机扫描 QR 码、EAN-13 和其他类型的条形码。 +sidebar: + badge: + text: New + variant: tip +plugin: barcode-scanner +--- + +import PluginLinks from '@components/PluginLinks.astro'; +import Compatibility from '@components/plugins/Compatibility.astro'; + +import { Tabs, TabItem } from '@astrojs/starlight/components'; +import CommandTabs from '@components/CommandTabs.astro'; + + + +允许您的移动应用程序使用相机扫描 QR 码、EAN-13 和其他类型的条形码。 + +## 支持的平台 + + + +## 设置 + +_这个外掛要求 Rust 版本至少是 **1.64**_ + +请安装条形码扫描器外掛。 + + + + +使用项目的包管理器来新增依赖。 + +{' '} + + + + + + +1. 运行 `cargo add tauri-plugin-barcode-scanner` 以将外掛新增到 `Cargo.toml` 的项目依赖中。 + +2. 修改 `lib.rs` 来初始化外掛。 + +```rust title="lib.rs" ins={4} +#[cfg_attr(mobile, tauri::mobile_entry_point)] +fn run() { + tauri::Builder::default() + .plugin(tauri_plugin_barcode_scanner::init()) + .run(tauri::generate_context!()) + .expect("error while running tauri application"); +} +``` + +3. 使用你喜欢的 JavaScript 包管理器安装 JavaScript Guest 绑定。 + + + + + +## 用法 + +条形码扫描器外掛在 JavaScript 中可用。 + +```javascript +import { scan, Format } from '@tauri-apps/plugin-barcode-scanner'; + +// `windowed: true` 实际上将 webview 设置为透明的 +// 而不是为相机打开一个单独的视图 +// 确保你的用户界面已经准备好使用透明元素显示下面的内容 +scan({ windowed: true, formats: [Format.QRCode] }); +``` + +## 权限 + +默认情况下,所有外掛命令都被阻止,无法访问。 +你必须在你的 `capabilities` 配置中定义一个权限列表。 + +更多資訊请参见[访问控制列表](/zh-tw/reference/acl/)。 + +```json title="src-tauri/capabilities/mobile.json" +{ + "$schema": "./schemas/mobile-schema.json", + "identifier": "mobile-capability", + "windows": ["main"], + "platforms": ["iOS", "android"], + "permissions": ["barcode-scanner:allow-scan", "barcode-scanner:allow-cancel"] +} +``` + +| 权限 | 描述 | +| ------------------------------------------- | ------------------------------------------------------------- | +| `barcode-scanner:allow-cancel` | 在没有预先配置有效範圍的情况下,启用 cancel 命令。 | +| `barcode-scanner:deny-cancel` | 拒绝没有任何预先配置的有效範圍的 cancel 命令。 | +| `barcode-scanner:allow-check-permissions` | 在没有预先配置有效範圍的情况下,启用 check_permissions 命令。 | +| `barcode-scanner:deny-check-permissions` | 拒绝没有任何预先配置的有效範圍的 check_permissions 命令。 | +| `barcode-scanner:allow-open-app-settings` | 在没有预先配置有效範圍的情况下,启用 open_app_settings 命令。 | +| `barcode-scanner:deny-open-app-settings` | 拒绝没有任何预先配置的有效範圍的 open_app_settings 命令。 | +| `barcode-scanner:allow-request-permissions` | 在没有预先配置有效範圍的情况下,启用 request_permissions 命令。 | +| `barcode-scanner:deny-request-permissions` | 拒绝没有任何预先配置的有效範圍的 request_permissions 命令。 | +| `barcode-scanner:allow-scan` | 在没有预先配置有效範圍的情况下,启用 scan 命令。 | +| `barcode-scanner:deny-scan` | 拒绝没有任何预先配置的有效範圍的 scan 命令。 | +| `barcode-scanner:allow-vibrate` | 在没有预先配置有效範圍的情况下,启用 vibrate 命令。 | +| `barcode-scanner:deny-vibrate` | 拒绝没有任何预先配置的有效範圍的 vibrate 命令。 | diff --git a/src/content/docs/zh-tw/plugin/cli.mdx b/src/content/docs/zh-tw/plugin/cli.mdx new file mode 100644 index 0000000000..0592b4bec6 --- /dev/null +++ b/src/content/docs/zh-tw/plugin/cli.mdx @@ -0,0 +1,280 @@ +--- +title: 命令行接口 (CLI) +description: 从命令行接口解析参数。 +plugin: cli +--- + +import PluginLinks from '@components/PluginLinks.astro'; +import Compatibility from '@components/plugins/Compatibility.astro'; + +import { Tabs, TabItem } from '@astrojs/starlight/components'; +import CommandTabs from '@components/CommandTabs.astro'; + + + +Tauri 使您的应用程序能够通过 [clap](https://github.com/clap-rs/clap)(一个强大的命令行参数解析器)拥有 CLI。通过 `tauri.conf.json` 文件中的简单 CLI 定义,您可以定义接口并读取其参数匹配 JavaScript/Rust 上的映射。 + +## 支持的平台 + + + +## 设置 + +请安装 CLI 外掛。 + + + + +使用项目的包管理器来新增依赖。 + +{' '} + + + + + + +1. 通过将以下内容新增到 `Cargo.toml` 的文件中来安装外掛。 + +```toml title="src-tauri/Cargo.toml" +# 如果你的目标不是移动设备,你可以在 `[dependencies]` 部分新增依赖 +[target."cfg(not(any(target_os = \"android\", target_os = \"ios\")))".dependencies] +tauri-plugin-cli = "2.0.0" +# 或者使用 Git +tauri-plugin-cli = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" } +``` + +2. 修改 `lib.rs` 来初始化外掛。 + +```rust title="src-tauri/src/lib.rs" ins={4} +#[cfg_attr(mobile, tauri::mobile_entry_point)] +fn run() { + tauri::Builder::default() + .plugin(tauri_plugin_cli::init()) + .run(tauri::generate_context!()) + .expect("error while running tauri application"); +} +``` + +3. 使用你喜欢的 JavaScript 包管理器安装 JavaScript Guest 绑定。 + + + + + +## 基本配置 + +在 `tauri.conf.json` 中,你可以使用以下结构来配置接口: + +```json title="src-tauri/tauri.conf.json" +{ + "plugins": { + "cli": { + "description": "Tauri CLI Plugin Example", + "args": [ + { + "short": "v", + "name": "verbose", + "description": "Verbosity level" + } + ], + "subcommands": { + "run": { + "description": "Run the application", + "args": [ + { + "name": "debug", + "description": "Run application in debug mode" + }, + { + "name": "release", + "description": "Run application in release mode" + } + ] + } + } + } + } +} +``` + +:::note + +这里所有的JSON配置都只是示例,为了清晰起见,许多其他字段都被省略了。 + +::: + +## 新增参数 + +`args` 数组表示其命令或子命令接受的参数列表。 + +{/* TODO: List available configuration */} + +### 位置参数 + +位置参数由其在参数列表中的位置标识。通过以下配置: + +```json title="src-tauri/tauri.conf.json" +{ + "args": [ + { + "name": "source", + "index": 1, + "takesValue": true + }, + { + "name": "destination", + "index": 2, + "takesValue": true + } + ] +} +``` + +用户可以以 `./app tauri.txt dest.txt` 的格式运行你的应用程序,参数匹配映射将把 `source` 定义为 `"tauri.txt"`,把 `destination` 定义为 `"dest.txt"`。 + +### 命名参数 + +命名参数是一个 (key, value) 对,键标识值。通过以下配置: + +```json title="tauri-src/tauri.conf.json" +{ + "args": [ + { + "name": "type", + "short": "t", + "takesValue": true, + "multiple": true, + "possibleValues": ["foo", "bar"] + } + ] +} +``` + +用户可以以 `./app --type foo bar`、`./app -t foo -t bar`、`./app --type=foo,bar` 的形式运行你的应用,匹配的参数映射将会将 `type` 定义为 `["foo", "bar"]`。 + +### 标志参数 + +标志参数是一个独立的键,它的存在或不存在为应用程序提供資訊。通过以下配置: + +```json title="tauri-src/tauri.conf.json" +{ + "args": [ + { + "name": "verbose", + "short": "v" + } + ] +} +``` + +用户可以以 `./app -v -v -v`、`./app --verbose --verbose --verbose`、`./app -vvv` 的形式运行你的应用程序, 匹配的参数映射将会将 `verbose` 定义为 `true` 和 `occurrences = 3`。 + +## 子命令 + +有些 CLI 应用程序有额外的接口作为子命令。例如,`git` CLI 有 `git branch`、`git commit` 和 `git push`。你可以使用 `subcommands` 数组定义额外的嵌套接口。 + +```json title="tauri-src/tauri.conf.json" +{ + "cli": { + ... + "subcommands": { + "branch": { + "args": [] + }, + "push": { + "args": [] + } + } + } +} +``` + +它的配置和根应用的配置一样,都有 `description`、`longDescription`、`args` 等。 + +## 用法 + +CLI 有 JavaScript 和 Rust 两种版本。 + + + + +```javascript +import { getMatches } from '@tauri-apps/plugin-cli'; + +const matches = await getMatches(); +if (matches.subcommand?.name === 'run') { + // `./your-app run $ARGS` was executed + const args = matches.subcommand.matches.args; + if (args.debug?.value === true) { + // `./your-app run --debug` was executed + } + if (args.release?.value === true) { + // `./your-app run --release` was executed + } +} +``` + + + + +```rust title="src-tauri/src/lib.rs" {1, 6-18} +use tauri_plugin_cli::CliExt; + +#[cfg_attr(mobile, tauri::mobile_entry_point)] +fn run() { + tauri::Builder::default() + .plugin(tauri_plugin_cli::init()) + .setup(|app| { + match app.cli().matches() { + // `matches` here is a Struct with { args, subcommand }. + // `args` is `HashMap` where `ArgData` is a struct with { value, occurrences }. + // `subcommand` is `Option>` where `SubcommandMatches` is a struct with { name, matches }. + Ok(matches) => { + println!("{:?}", matches) + } + Err(_) => {} + } + Ok(()) + }) + .run(tauri::generate_context!()) + .expect("error while running tauri application"); +} +``` + + + + +## 权限 + +默认情况下,所有外掛命令都被阻止,无法访问。 +你必须在你的 `capabilities` 配置中定义一个权限列表。 + +更多資訊请参见[访问控制列表](/zh-tw/reference/acl/)。 + +```json title="src-tauri/capabilities/default.json" ins={6} +{ + "$schema": "./schemas/desktop-schema.json", + "identifier": "main-capability", + "description": "Capability for the main window", + "windows": ["main"], + "permissions": ["cli:default"] +} +``` + +| 权限 | 描述 | +| ----------------------- | ----------------------------------------------------- | +| `cli:default` | 允许读取 CLI 匹配项。 | +| `cli:allow-cli-matches` | 在没有预先配置有效範圍的情况下,启用 cli_matches 命令。 | +| `cli:deny-cli-matches` | 拒绝没有预先配置有效範圍的 cli_matches 命令。 | diff --git a/src/content/docs/zh-tw/plugin/clipboard.mdx b/src/content/docs/zh-tw/plugin/clipboard.mdx new file mode 100644 index 0000000000..849f8a571c --- /dev/null +++ b/src/content/docs/zh-tw/plugin/clipboard.mdx @@ -0,0 +1,112 @@ +--- +title: 剪切板 +description: 读取和写入系统剪贴板。 +plugin: clipboard-manager +--- + +import Stub from '@components/Stub.astro'; +import PluginLinks from '@components/PluginLinks.astro'; +import Compatibility from '@components/plugins/Compatibility.astro'; + +import { Tabs, TabItem } from '@astrojs/starlight/components'; +import CommandTabs from '@components/CommandTabs.astro'; + + + +使用剪贴板外掛读取和写入系统剪贴板。 + +## Supported Platforms + + + +## 设置 + +请安装剪贴板外掛。 + + + + + 使用项目的包管理器来新增依赖: + + + + + + + 1. 运行 `cargo add tauri-plugin-clipboard-manager` 命令,将外掛新增到项目的 `Cargo.toml` 依赖中。 + + 2. 修改 `lib.rs` 来初始化外掛。 + + ```rust + // lib.rs + #[cfg_attr(mobile, tauri::mobile_entry_point)] + pub fn run() { + tauri::Builder::default() + // Initialize the plugin + .plugin(tauri_plugin_clipboard_manager::init()) + .run(tauri::generate_context!()) + .expect("error while running tauri application"); + } + ``` + + 3. 如果你想用 JavaScript 管理剪贴板,还需要安装 npm 包。 + + + + + + + +## 用法 + +{/* TODO: Link to which language to use, frontend vs. backend guide when it's made */} + +剪贴板外掛有 JavaScript 和 Rust 两种版本。 + + + + +```javascript +import { writeText, readText } from '@tauri-apps/plugin-clipboard-manager'; + +// 将内容写到剪贴板 +await writeText('Tauri is awesome!'); + +// 从剪贴板读取内容 +const content = await readText(); +console.log(content); +// Prints "Tauri is awesome!" to the console +``` + + + + +```rust +use tauri_plugin_clipboard_manager::ClipboardExt; + +// 将内容写到剪贴板 +let clipboard_content = tauri_plugin_clipboard_manager::ClipKind::PlainText { + label: Some("Label".to_string()), + text: "Tauri is awesome!".to_string(), +}; +app.clipboard().write(clipboard_content).unwrap(); + +// 从剪贴板读取内容 +let content = app.clipboard().read(); +println!("{:?}", content.unwrap()); +// Prints "Tauri is awesome!" to the terminal + + +``` + + + diff --git a/src/content/docs/zh-tw/plugin/deep-linking.mdx b/src/content/docs/zh-tw/plugin/deep-linking.mdx new file mode 100644 index 0000000000..4ac2327302 --- /dev/null +++ b/src/content/docs/zh-tw/plugin/deep-linking.mdx @@ -0,0 +1,225 @@ +--- +title: 深度链接(deep-link) +description: 将你的 Tauri 应用程序设置为 URL 的默认处理程序。 +sidebar: + badge: + text: New + variant: tip +plugin: deep-link +--- + +import PluginLinks from '@components/PluginLinks.astro'; +import Compatibility from '@components/plugins/Compatibility.astro'; + +import { Tabs, TabItem } from '@astrojs/starlight/components'; +import CommandTabs from '@components/CommandTabs.astro'; + + + +将你的 Tauri 应用程序设置为 URL 的默认处理程序。 + +## 支持的平台 + + + +## 设置 + +请安装 deep-link 外掛。 + + + + +使用项目的包管理器来新增依赖。 + +{' '} + + + + + + +1. 运行 `cargo add tauri-plugin-deep-link` 以将外掛新增到 `Cargo.toml` 的项目依赖中。 + +2. 修改 `lib.rs` 来初始化外掛。 + +```rust title="lib.rs" ins={4} +#[cfg_attr(mobile, tauri::mobile_entry_point)] +fn run() { + tauri::Builder::default() + .plugin(tauri_plugin_deep_link::init()) + .run(tauri::generate_context!()) + .expect("error while running tauri application"); +} +``` + +3. 使用你喜欢的 JavaScript 包管理器安装 JavaScript Guest 绑定。 + + + + + +## 设置 + +### Android + +对于 [app links](https://developer.android.com/training/app-links#android-app-links),你需要一个具有 `.well-known/assetlinks.json` 端点的服务器,该端点必须返回给定格式的文本响应。 + +```json title=".well-known/assetlinks.json" +[ + { + "relation": ["delegate_permission/common.handle_all_urls"], + "target": { + "namespace": "android_app", + "package_name": "$APP_BUNDLE_ID", + "sha256_cert_fingerprints": [ + $CERT_FINGERPRINT + ] + } + } +] +``` + +其中 `$APP_BUNDLE_ID` 是 `tauri.conf.json > identifier` 上定义的值,其中 `-` 替换为 `_` , `$CERT_FINGERPRINT` 是你的应用签名证书的 SHA256 指纹列表,请参阅 [verify android applinks](https://developer.android.com/training/app-links/verify-android-applinks#web-assoc) 以获取更多資訊。 + +### iOS + +#### Server + +对于 [universal links](https://developer.apple.com/documentation/xcode/allowing-apps-and-websites-to-link-to-your-content?language=obj),你需要一个具有 `.well-known/apple-app-site-association` 端点的服务器,该端点必须返回给定格式的文本响应。 + +```json title=".well-known/apple-app-site-association" +{ + "applinks": { + "details": [ + { + "appIDs": ["$DEVELOPMENT_TEAM_ID.$APP_BUNDLE_ID"], + "components": [ + { + "/": "/open/*", + "comment": "Matches any URL whose path starts with /open/" + } + ] + } + ] + } +} +``` + +其中 `$DEVELOPMENT_TEAM_ID` 是 `tauri.conf.json > tauri > bundle > iOS > developmentTeam` 或 `TAURI_APPLE_DEVELOPMENT_TEAM` 环境变量上定义的值,`$APP_BUNDLE_ID`是定义在`tauri.conf.json > identifier` 上的值。请参阅 [applinks.details](https://developer.apple.com/documentation/bundleresources/applinks/details) 以获取更多資訊。 + +#### App + +你还需要将相关域名新增到应用的 `entitlement` 文件中。 + +```xml title="src-tauri/gen/apple/[App Name]_iOS/[App Name]_iOS.entitlements" ins={5-9} + + + + + com.apple.developer.associated-domains + + applinks:your.website.com + applinks:nother.site.br + + + +``` + +有关更多資訊,请参阅 [supporting associated domains](https://developer.apple.com/documentation/xcode/supporting-associated-domains?language=objc)。 + +## 配置 + +在 `tauri.conf.json > plugins > deep-link` 下,配置你想要关联到你的应用程序的域。 + +```json title="tauri.conf.json" +{ + "plugins": { + "deep-link": { + "mobile": [ + { "host": "your.website.com", "pathPrefix": ["/open"] }, + { "host": "another.site.br" } + ], + "desktop": { + "schemes": ["something", "my-tauri-app"] + } + } + } +} +``` + +## 用法 + +deep-link 有 JavaScript 和 Rust 两种版本。 + + + + +```javascript +import { onOpenUrl } from '@tauri-apps/plugin-deep-link'; + +await onOpenUrl((urls) => { + console.log('deep link:', urls); +}); +``` + + + + +```rust title="src-tauri/src/lib.rs" +use tauri_plugin_cli::CliExt; + +#[cfg_attr(mobile, tauri::mobile_entry_point)] +fn run() { + tauri::Builder::default() + .plugin(tauri_plugin_deep_link::init()) + .setup(|app| { + app.listen("deep-link://new-url", |url| { + dbg!(url); + }); + Ok(()) + }) + .run(tauri::generate_context!()) + .expect("error while running tauri application"); +} +``` + + + + +## 权限 + +默认情况下,所有外掛命令都被阻止,无法访问。 +你必须在你的 `capabilities` 配置中定义一个权限列表。 + +更多資訊请参见[访问控制列表](/zh-tw/reference/acl/)。 + +```json title="src-tauri/capabilities/default.json" ins={9} +{ + "$schema": "./schemas/mobile-schema.json", + "identifier": "mobile-capability", + "windows": ["main"], + "platforms": ["iOS", "android"], + "permissions": [ + // 通常需要 event:default 来监听 deep-link 事件 + "core:event:default", + "deep-link:default" + ] +} +``` + +| 权限 | 描述 | +| ----------------------------- | ----------------------------------------------------- | +| `deep-link:default` | 允许通过 get_current 命令读取打开的深度链接。 | +| `deep-link:allow-get-current` | 在没有预先配置的有效範圍的情况下启用 get_current 命令。 | +| `deep-link:deny-get-current` | 拒绝没有任何预配置范围的 get_current 命令。 | diff --git a/src/content/docs/zh-tw/plugin/dialog.mdx b/src/content/docs/zh-tw/plugin/dialog.mdx new file mode 100644 index 0000000000..8c8de11370 --- /dev/null +++ b/src/content/docs/zh-tw/plugin/dialog.mdx @@ -0,0 +1,299 @@ +--- +title: 对话框 +description: 本机系统对话框,用于打开和保存文件,以及消息对话框。 +i18nReady: true +tableOfContents: + maxHeadingLevel: 4 +plugin: dialog +--- + +import PluginLinks from '@components/PluginLinks.astro'; +import Compatibility from '@components/plugins/Compatibility.astro'; + +import { Tabs, TabItem } from '@astrojs/starlight/components'; +import CommandTabs from '@components/CommandTabs.astro'; + + + +本机系统对话框,用于打开和保存文件,以及消息对话框。 + +## Supported Platforms + + + +## 设置 + +从安装对话框外掛开始。 + + + + + 使用项目的包管理器来新增依赖: + + + + + + + 1. 运行 `cargo add tauri-plugin-dialog` 命令,将外掛新增到项目的 `cargo .toml` 依赖中。 + + 2. 修改 `lib.rs` 来初始化外掛。 + + ```rust + // lib.rs + #[cfg_attr(mobile, tauri::mobile_entry_point)] + pub fn run() { + tauri::Builder::default() + // Initialize the plugin + .plugin(tauri_plugin_dialog::init()) + .run(tauri::generate_context!()) + .expect("error while running tauri application"); + } + ``` + + 3. 如果你想在 JavaScript 中创建对话框,还需要安装 npm 包: + + + + + + +## 用法 + +对话框外掛可以在 JavaScript 和 Rust 中使用。你可以这样使用它: + +在 JavaScript: + +- [创建 Yes/No 对话框](#创建-yesno-对话框) +- [创建 Ok/Cancel 对话框](#创建-okcancel-对话框) +- [创建 Message 对话框](#创建-message-对话框) +- [打开一个文件选择对话框](#打开一个文件选择对话框) +- [保存到文件对话框](#保存到文件对话框) + +在 Rust: + +- [建立一个询问对话框](#建立一个询问对话框) +- [建立消息对话框](#建立消息对话框) +- [建立一个文件选择器对话框](#建立一个文件选择器对话框) + +--- + +### JavaScript + +可以在 JavaScript API 参考中查看所有 [Dialog 选项](/zh-tw/reference/javascript/dialog/)。 + +{/* ASK */} + +#### 创建 Yes/No 对话框 + +显示一个带有 "Yes" 和 "No" 按钮的提问对话框。 + +```javascript +import { ask } from '@tauri-apps/plugin-dialog'; + +// 创建 Yes/No 对话框 +const answer = await ask('This action cannot be reverted. Are you sure?', { + title: 'Tauri', + kind: 'warning', +}); + +console.log(answer); +// Prints boolean to the console +``` + +{/* CONFIRM */} + +#### 创建 Ok/Cancel 对话框 + +显示一个带有 "Ok" 和 "Cancel" 按钮的提问对话框。 + +```javascript +import { confirm } from '@tauri-apps/plugin-dialog'; + +// Creates a confirmation Ok/Cancel dialog +const confirmation = await confirm( + 'This action cannot be reverted. Are you sure?', + { title: 'Tauri', kind: 'warning' } +); + +console.log(confirmation); +// Prints boolean to the console +``` + +{/* MESSAGE */} + +#### 创建 Message 对话框 + +一个带有 "Ok" 按钮的消息对话框。请注意,如果用户关闭对话框,它将返回 `false`。 + +```javascript +import { message } from '@tauri-apps/plugin-dialog'; + +// Shows message +await message('File not found', { title: 'Tauri', kind: 'error' }); +``` + +{/* OPEN */} + +#### 打开一个文件选择对话框 + +打开一个文件/目录选择对话框。 + +`multiple` 选项控制对话框是否允许多重选择,而 `directory` 则控制对话框是否允许目录选择。 + +```javascript +import { open } from '@tauri-apps/plugin-dialog'; + +// Open a dialog +const file = await open({ + multiple: false, + directory: false, +}); +console.log(file); +// Prints file path and name to the console +``` + +{/* SAVE */} + +#### 保存到文件对话框 + +打开一个文件/目录保存对话框。 + +```javascript +import { save } from '@tauri-apps/plugin-dialog'; +// Prompt to save a 'My Filter' with extension .png or .jpeg +const path = await save({ + filters: [ + { + name: 'My Filter', + extensions: ['png', 'jpeg'], + }, + ], +}); +console.log(path); +// Prints the chosen path +``` + +--- + +### Rust + +请参阅 [Rust API 参考](https://docs.rs/tauri-plugin-dialog/)以查看所有可用选项。 + +#### 建立一个询问对话框 + +显示一个带有 "Absolutely" 和 "Totally" 按钮的问题对话框。 + +```rust +use tauri_plugin_dialog::DialogExt; + +let answer = app.dialog() + .message("Tauri is Awesome") + .title("Tauri is Awesome") + .ok_button_label("Absolutely") + .cancel_button_label("Totally") + .blocking_show(); +``` + +如果你需要一个非阻塞操作,你可以使用 `show()`: + +```rust +use tauri_plugin_dialog::DialogExt; + +app.dialog() + .message("Tauri is Awesome") + .title("Tauri is Awesome") + .ok_button_label("Absolutely") + .cancel_button_label("Totally") + .show(|result| match result { + true => // do something, + false =>// do something, + }); +``` + +#### 建立消息对话框 + +一个带有 "Ok" 按钮的消息对话框。请注意,如果用户关闭对话框,它将返回 `false`。 + +```rust +use tauri_plugin_dialog::{DialogExt, MessageDialogKind}; + +let ans = app.dialog() + .message("File not found") + .kind(MessageDialogKind::Error) + .title("Warning") + .blocking_show(); +``` + +如果你需要一个非阻塞操作,你可以使用 `show()`: + +```rust +use tauri_plugin_dialog::{DialogExt, MessageDialogKind}; + +app.dialog() + .message("Tauri is Awesome") + .kind(MessageDialogKind::Info) + .title("Information") + .ok_button_label("Absolutely") + .show(|result| match result { + true => // do something, + false => // do something, + }); +``` + +#### 建立一个文件选择器对话框 + +#### 选择文件 + +```rust +use tauri_plugin_dialog::DialogExt; + +let file_path = app.dialog().file().blocking_pick_file(); +// return a file_path `Option`, or `None` if the user closes the dialog +``` + +如果你需要一个非阻塞操作,你可以使用 `show()`: + +```rust +use tauri_plugin_dialog::DialogExt; + +app.dialog().file().pick_file(|file_path| { + // return a file_path `Option`, or `None` if the user closes the dialog + }) +``` + +#### 保存文件 + +```rust +use tauri_plugin_dialog::DialogExt; + +let file_path = app + .dialog() + .file() + .add_filter("My Filter", &["png", "jpeg"]) + .blocking_save_file(); + // do something with the optional file path here + // the file path is `None` if the user closed the dialog +``` + +或者: + +```rust +use tauri_plugin_dialog::DialogExt; + +app.dialog() + .file() + .add_filter("My Filter", &["png", "jpeg"]) + .pick_file(|file_path| { + // return a file_path `Option`, or `None` if the user closes the dialog + }); +``` diff --git a/src/content/docs/zh-tw/plugin/file-system.mdx b/src/content/docs/zh-tw/plugin/file-system.mdx new file mode 100644 index 0000000000..9e204e3e05 --- /dev/null +++ b/src/content/docs/zh-tw/plugin/file-system.mdx @@ -0,0 +1,492 @@ +--- +title: 文件系统 +description: 访问文件系统。 +plugin: fs +--- + +import PluginLinks from '@components/PluginLinks.astro'; +import Compatibility from '@components/plugins/Compatibility.astro'; + +import { Tabs, TabItem } from '@astrojs/starlight/components'; +import CommandTabs from '@components/CommandTabs.astro'; + + + +访问文件系统。 + +## 支持的平台 + + + +## 设置 + +安装 fs 外掛开始。 + + + + +使用项目的包管理器来新增依赖: + +{ ' ' } + + + + + + +1. 通过将以下内容新增到 `Cargo.toml` 的文件中来安装 fs 外掛。 + +```toml title="src-tauri/Cargo.toml" +[dependencies] +tauri-plugin-fs = "2.0.0" +# 或者使用 Git: +tauri-plugin-fs = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" } +``` + +2. 修改 `lib.rs` 来初始化外掛。 + +```rust title="src-tauri/src/lib.rs" ins={4} +#[cfg_attr(mobile, tauri::mobile_entry_point)] +fn run() { + tauri::Builder::default() + .plugin(tauri_plugin_fs::init()) + .run(tauri::generate_context!()) + .expect("error while running tauri application"); +} +``` + +3. 使用你喜欢的 JavaScript 包管理器安装 JavaScript Guest 绑定。 + + + + + +## 用法 + +fs 外掛有 JavaScript 和 Rust 两种版本。 + + + + +```javascript +import { exists, BaseDirectory } from '@tauri-apps/plugin-fs'; + +// 检查 `$APPDATA/avatar.png` 文件是否存在 +await exists('avatar.png', { baseDir: BaseDirectory.AppData }); +``` + + + + +```rust title="src-tauri/src/lib.rs" +use tauri_plugin_fs::FsExt; + +#[cfg_attr(mobile, tauri::mobile_entry_point)] +fn run() { + tauri::Builder::default() + .plugin(tauri_plugin_fs::init()) + .setup(|app| { + // 允许指定目录 + let scope = app.fs_scope(); + scope.allow_directory("/path/to/directory", false); + dbg!(scope.allowed()); + + Ok(()) + }) + .run(tauri::generate_context!()) + .expect("error while running tauri application"); +} +``` + + + + +## 安全 + +这个模块阻止路径遍历,不允许绝对路径或父目录组件(即 `/usr/path/to/file` 或 `../path/to/file` 路径是不允许的)。使用这个 API 访问的路径必须相对于一个基本目录,因此如果你需要访问任意的文件系统路径,你必须在核心层上编写这样的逻辑。 + +更多資訊请参见 [@tauri-apps/plugin-fs - Security](/zh-tw/reference/javascript/fs/#security)。 + +## 权限 + +默认情况下,所有外掛命令都被阻止,无法访问。你必须在你的 `capabilities` 配置中定义一个权限列表。 + +更多資訊请参见[访问控制列表](/zh-tw/reference/acl/)。 + +```json title="src-tauri/capabilities/default.json" ins={7-11} +{ + "$schema": "../gen/schemas/desktop-schema.json", + "identifier": "main-capability", + "description": "Capability for the main window", + "windows": ["main"], + "permissions": [ + "fs:default", + { + "identifier": "fs:allow-exists", + "allow": [{ "path": "$APPDATA/*" }] + } + ] +} +``` + +### 默认权限 + +这个配置文件定义了授予文件系统的默认权限。 + +#### 授予的权限 + +这个默认权限设置启用了所有与读相关的命令,并允许访问 `$APP` 文件夹和在其中创建的子目录。 `$APP` 文件夹的位置取决于应用程序运行的操作系统。 + +通常情况下,在访问其中的文件或文件夹之前,需要在运行时由应用程序手动创建 `$APP` 文件夹。 + +#### 拒绝的权限 + +这个默认权限设置默认阻止访问 Tauri 应用程序的关键组件。在 Windows 上,webview 数据文件夹访问被拒绝。 + +| 权限 | 描述 | +| ----------------- | ------------------------------------------------------- | +| `fs:default` | | +| `fs:deny-default` | 默认情况下拒绝访问与 Tauri 相关文件和文件夹的危险操作。 | + +### 有效範圍范围 + +| 权限 | 描述 | +| --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `fs:allow-app-read-recursive` | 这允许对完整的 `$APP` 文件夹、文件和子目录进行完全递归读访问。 | +| `fs:allow-app-write-recursive` | 这个允许对整个 `$APP` 文件夹、文件和子目录的完全递归写访问。 | +| `fs:allow-app-read` | 这个允许对 `$APP` 文件夹的非递归读访问。 | +| `fs:allow-app-write` | 这个允许对 `$APP` 文件夹的非递归写访问。 | +| `fs:allow-app-meta-recursive` | 这允许读取 `$APP` 文件夹的元数据,包括文件列表和统计資訊。 | +| `fs:allow-app-meta` | 这允许读取 `$APP` 文件夹的元数据,包括文件列表和统计資訊。 | +| `fs:scope-app-recursive` | 这个有效範圍可以递归访问整个 `$APP` 文件夹,包括子目录和文件。 | +| `fs:scope-app` | 这个有效範圍允许访问 `$APP` 文件夹中的所有文件和顶级目录的列表内容。 | +| `fs:scope-app-index` | 这个有效範圍允许列出 `$APP` 文件夹中的所有文件和文件夹。 | +| `fs:allow-appcache-read-recursive` | 这个允许完全递归读取整个 `$APPCACHE` 文件夹、文件和子目录。 | +| `fs:allow-appcache-write-recursive` | 这个允许完全递归写入整个 `$APPCACHE` 文件夹、文件和子目录。 | +| `fs:allow-appcache-read` | 这个允许非递归读取 `$APPCACHE` 文件夹。 | +| `fs:allow-appcache-write` | 这允许对 `$APPCACHE` 文件夹进行非递归写访问。 | +| `fs:allow-appcache-meta-recursive` | 这允许读取 `$APPCACHE` 文件夹的元数据,包括文件列表和统计資訊。 | +| `fs:allow-appcache-meta` | 这允许读取 `$APPCACHE` 文件夹的元数据,包括文件列表和统计資訊。 | +| `fs:scope-appcache-recursive` | 这个有效範圍递归访问整个 `$APPCACHE` 文件夹,包括子目录和文件。 | +| `fs:scope-appcache` | 这个有效範圍允许访问 `$APPCACHE` 文件夹中的所有文件和顶级目录的内容列表 | +| `fs:scope-appcache-index` | 这个范围允许列出 `$APPCACHE` 文件夹中的所有文件和文件夹。 | +| `fs:allow-appconfig-read-recursive` | 这个选项允许对整个 `$APPCONFIG` 文件夹、文件和子目录进行完全递归读取访问。 | +| `fs:allow-appconfig-write-recursive` | 这个选项允许对整个 `$APPCONFIG` 文件夹、文件和子目录进行完全递归写入访问。 | +| `fs:allow-appconfig-read` | 这个选项允许对 `$APPCONFIG` 文件夹进行非递归读取访问。 | +| `fs:allow-appconfig-write` | 这个选项允许对 `$APPCONFIG` 文件夹进行非递归写入访问。 | +| `fs:allow-appconfig-meta-recursive` | 这允许读取 `$APPCONFIG` 文件夹的元数据,包括文件列表和统计資訊。 | +| `fs:allow-appconfig-meta` | 这允许读取 `$APPCONFIG` 文件夹的元数据,包括文件列表和统计資訊。 | +| `fs:scope-appconfig-recursive` | 这个有效範圍递归访问完整的 `$APPCONFIG` 文件夹,包括子目录和文件。 | +| `fs:scope-appconfig` | 这个有效範圍允许访问 `$APPCONFIG` 文件夹中的所有文件和顶级目录的内容列表 | +| `fs:scope-appconfig-index` | 这个有效範圍允许列出 `$APPCONFIG` 文件夹中的所有文件和文件夹。 | +| `fs:allow-appdata-read-recursive` | 这允许对完整的 `$APPDATA` 文件夹、文件和子目录进行完全递归读访问。 | +| `fs:allow-appdata-write-recursive` | 这允许对完整的 `$APPDATA` 文件夹、文件和子目录进行完全递归写访问。 | +| `fs:allow-appdata-read` | 这允许对 `$APPDATA` 文件夹进行非递归读访问。 | +| `fs:allow-appdata-write` | 这允许对 `$APPDATA` 文件夹进行非递归写访问。 | +| `fs:allow-appdata-meta-recursive` | 这允许读取 `$APPDATA` 文件夹的元数据,包括文件列表和统计資訊。 | +| `fs:allow-appdata-meta` | 这允许读取 `$APPDATA` 文件夹的元数据,包括文件列表和统计資訊。 | +| `fs:scope-appdata-recursive` | 这个有效範圍递归访问完整的 `$APPDATA` 文件夹,包括子目录和文件。 | +| `fs:scope-appdata` | 这个有效範圍允许访问 `$APPDATA` 文件夹中的所有文件和顶级目录的内容列表。 | +| `fs:scope-appdata-index` | 这个有效範圍允许列出 `$APPDATA` 文件夹中的所有文件和文件夹。 | +| `fs:allow-applocaldata-read-recursive` | 这个选项允许对整个 `$APPLOCALDATA` 文件夹、文件和子目录进行完全递归读取访问。 | +| `fs:allow-applocaldata-write-recursive` | 这个选项允许对整个 `$APPLOCALDATA` 文件夹、文件和子目录进行完全递归写入访问。 | +| `fs:allow-applocaldata-read` | 这个选项允许对 `$APPLOCALDATA` 文件夹进行非递归读取访问。 | +| `fs:allow-applocaldata-write` | 这个选项允许对 `$APPLOCALDATA` 文件夹进行非递归写入访问。 | +| `fs:allow-applocaldata-meta-recursive` | 这允许读取访问元数据的`$APPLOCALDATA`文件夹,包括文件列表和统计数据。 | +| `fs:allow-applocaldata-meta` | 这允许读取访问元数据的`$APPLOCALDATA`文件夹,包括文件列表和统计数据。 | +| `fs:scope-applocaldata-recursive` | 这个有效範圍递归访问完整的`$APPLOCALDATA`文件夹,包括子目录和文件。 | +| `fs:scope-applocaldata` | 这个有效範圍允许访问所有文件和`$APPLOCALDATA`文件夹中顶级目录的内容列表。 | +| `fs:scope-applocaldata-index` | 这个有效範圍允许列出`$APPLOCALDATA`文件夹中的所有文件和文件夹。 | +| `fs:allow-applog-read-recursive` | 这允许对完整的 `$APPLOG` 文件夹、文件和子目录进行完全递归读访问。 | +| `fs:allow-applog-write-recursive` | 这允许对完整的 `$APPLOG` 文件夹、文件和子目录进行完全递写访问。 | +| `fs:allow-applog-read` | 这允许对 `$APPLOG` 文件夹进行非递归读访问。 | +| `fs:allow-applog-write` | 这允许对 `$APPLOG` 文件夹进行非递归写访问。 | +| `fs:allow-applog-meta-recursive` | 这允许读取 `$APPLOG` 文件夹的元数据,包括文件列表和统计資訊。 | +| `fs:allow-applog-meta` | 这允许读取 `$APPLOG` 文件夹的元数据,包括文件列表和统计資訊。 | +| `fs:scope-applog-recursive` | 这个有效範圍递归访问完整的 `$APPLOG` 文件夹,包括子目录和文件。 | +| `fs:scope-applog` | 这个有效範圍允许访问 `$APPLOG` 文件夹中的所有文件和顶级目录的内容列表。 | +| `fs:scope-applog-index` | 这个有效範圍允许列出 `$APPLOG` 文件夹中的所有文件和文件夹。 | +| `fs:allow-audio-read-recursive` | 这个允许对完整的 `$AUDIO` 文件夹、文件和子目录进行完全递归读访问。 | +| `fs:allow-audio-write-recursive` | 这个允许对完整的 `$AUDIO` 文件夹、文件和子目录进行完全递归写访问。 | +| `fs:allow-audio-read` | 这个允许对 `$AUDIO` 文件夹进行非递归读访问。 | +| `fs:allow-audio-write` | 这个允许对 `$AUDIO` 文件夹进行非递归写访问。 | +| `fs:allow-audio-meta-recursive` | 这个允许对 `$AUDIO` 文件夹的元数据进行读访问,包括文件列表和统计資訊。 | +| `fs:allow-audio-meta` | 这个允许对 `$AUDIO` 文件夹的元数据进行读访问,包括文件列表和统计資訊。 | +| `fs:scope-audio-recursive` | 这个有效範圍递归访问完整的 `$AUDIO` 文件夹,包括子目录和文件。 | +| `fs:scope-audio` | 这个有效範圍允许访问 `$AUDIO` 文件夹中的所有文件和顶级目录的列表内容。 | +| `fs:scope-audio-index` | 这个有效範圍允许列出 `$AUDIO` 文件夹中的所有文件和文件夹。 | +| `fs:allow-cache-read-recursive` | 这个允许对完整的 `$CACHE` 文件夹、文件和子目录进行完全递归读访问。 | +| `fs:allow-cache-write-recursive` | 这个允许对完整的 `$CACHE` 文件夹、文件和子目录进行完全递归写访问。 | +| `fs:allow-cache-read` | 这个允许对 `$CACHE` 文件夹进行非递归读访问。 | +| `fs:allow-cache-write` | 这个允许对 `$CACHE` 文件夹进行非递归写访问。 | +| `fs:allow-cache-meta-recursive` | 这个允许对 `$CACHE` 文件夹的元数据进行读访问,包括文件列表和统计資訊。 | +| `fs:allow-cache-meta` | 这个允许对 `$CACHE` 文件夹的元数据进行读访问,包括文件列表和统计資訊。 | +| `fs:scope-cache-recursive` | 这个有效範圍递归访问完整的 `$CACHE` 文件夹,包括子目录和文件。 | +| `fs:scope-cache` | 这个有效範圍允许访问 `$CACHE` 文件夹中的所有文件和顶级目录的列表内容。 | +| `fs:scope-cache-index` | 这个有效範圍允许列出 `$CACHE` 文件夹中的所有文件和文件夹。 | +| `fs:allow-config-read-recursive` | 这个允许对完整的 `$CONFIG` 文件夹、文件和子目录进行完全递归读访问。 | +| `fs:allow-config-write-recursive` | 这个允许对完整的 `$CONFIG` 文件夹、文件和子目录进行完全递归写访问。 | +| `fs:allow-config-read` | 这个允许对 `$CONFIG` 文件夹进行非递归读访问。 | +| `fs:allow-config-write` | 这个允许对 `$CONFIG` 文件夹进行非递归写访问。 | +| `fs:allow-config-meta-recursive` | 这个允许对 `$CONFIG` 文件夹的元数据进行读访问,包括文件列表和统计資訊。 | +| `fs:allow-config-meta` | 这个允许对 `$CONFIG` 文件夹的元数据进行读访问,包括文件列表和统计資訊。 | +| `fs:scope-config-recursive` | 这个有效範圍递归访问完整的 `$CONFIG` 文件夹,包括子目录和文件。 | +| `fs:scope-config` | 这个有效範圍允许访问 `$CONFIG` 文件夹中的所有文件和顶级目录的列表内容。 | +| `fs:scope-config-index` | 这个有效範圍允许列出 `$CONFIG` 文件夹中的所有文件和文件夹。 | +| `fs:allow-data-read-recursive` | 这个允许对完整的 `$DATA` 文件夹、文件和子目录进行完全递归读访问。 | +| `fs:allow-data-write-recursive` | 这个允许对完整的 `$DATA` 文件夹、文件和子目录进行完全递归写访问。 | +| `fs:allow-data-read` | 这个允许对 `$DATA` 文件夹进行非递归读访问。 | +| `fs:allow-data-write` | 这个允许对 `$DATA` 文件夹进行非递归写访问。 | +| `fs:allow-data-meta-recursive` | 这个允许对 `$DATA` 文件夹的元数据进行读访问,包括文件列表和统计資訊。 | +| `fs:allow-data-meta` | 这个允许对 `$DATA` 文件夹的元数据进行读访问,包括文件列表和统计資訊。 | +| `fs:scope-data-recursive` | 这个有效範圍递归访问完整的 `$DATA` 文件夹,包括子目录和文件。 | +| `fs:scope-data` | 这个有效範圍允许访问 `$DATA` 文件夹中的所有文件和顶级目录的列表内容。 | +| `fs:scope-data-index` | 这个有效範圍允许列出 `$DATA` 文件夹中的所有文件和文件夹。 | +| `fs:allow-desktop-read-recursive` | 这个允许对整个 `$DESKTOP` 文件夹、文件和子目录进行完全递归读访问。 | +| `fs:allow-desktop-write-recursive` | 这个允许对整个 `$DESKTOP` 文件夹、文件和子目录进行完全递归写访问。 | +| `fs:allow-desktop-read` | 这个允许对 `$DESKTOP` 文件夹进行非递归读访问。 | +| `fs:allow-desktop-write` | 这个允许对 `$DESKTOP` 文件夹进行非递归写访问。 | +| `fs:allow-desktop-meta-recursive` | 这个允许对 `$DESKTOP` 文件夹的元数据进行读访问,包括文件列表和统计資訊。 | +| `fs:allow-desktop-meta` | 这个允许对 `$DESKTOP` 文件夹的元数据进行读访问,包括文件列表和统计資訊。 | +| `fs:scope-desktop-recursive` | 这个有效範圍递归访问整个 `$DESKTOP` 文件夹,包括子目录和文件。 | +| `fs:scope-desktop` | 这个有效範圍允许访问 `$DESKTOP` 文件夹中的所有文件和顶级目录的列表内容。 | +| `fs:scope-desktop-index` | 这个有效範圍允许列出 `$DESKTOP` 文件夹中的所有文件和文件夹。 | +| `fs:allow-document-read-recursive` | 这个允许对完整的 `$DOCUMENT` 文件夹、文件和子目录进行完全递归读访问。 | +| `fs:allow-document-write-recursive` | 这个允许对完整的 `$DOCUMENT` 文件夹、文件和子目录进行完全递归写访问。 | +| `fs:allow-document-read` | 这个允许对 `$DOCUMENT` 文件夹进行非递归读访问。 | +| `fs:allow-document-write` | 这个允许对 `$DOCUMENT` 文件夹进行非递归写访问。 | +| `fs:allow-document-meta-recursive` | 这个允许对 `$DOCUMENT` 文件夹的元数据进行读访问,包括文件列表和统计資訊。 | +| `fs:allow-document-meta` | 这个允许对 `$DOCUMENT` 文件夹的元数据进行读访问,包括文件列表和统计資訊。 | +| `fs:scope-document-recursive` | 这个有效範圍递归访问完整的 `$DOCUMENT` 文件夹,包括子目录和文件。 | +| `fs:scope-document` | 这个有效範圍允许访问 `$DOCUMENT` 文件夹中的所有文件和顶级目录的列表内容。 | +| `fs:scope-document-index` | 这个有效範圍允许列出 `$DOCUMENT` 文件夹中的所有文件和文件夹。 | +| `fs:allow-download-read-recursive` | 这个允许对完整的 `$DOWNLOAD` 文件夹、文件和子目录进行完全递归读访问。 | +| `fs:allow-download-write-recursive` | 这个允许对完整的 `$DOWNLOAD` 文件夹、文件和子目录进行完全递归写访问。 | +| `fs:allow-download-read` | 这个允许对 `$DOWNLOAD` 文件夹进行非递归读访问。 | +| `fs:allow-download-write` | 这个允许对 `$DOWNLOAD` 文件夹进行非递归写访问。 | +| `fs:allow-download-meta-recursive` | 这个允许对 `$DOWNLOAD` 文件夹的元数据进行读访问,包括文件列表和统计資訊。 | +| `fs:allow-download-meta` | 这个允许对 `$DOWNLOAD` 文件夹的元数据进行读访问,包括文件列表和统计資訊。 | +| `fs:scope-download-recursive` | 这个有效範圍递归访问整个 `$DOWNLOAD` 文件夹,包括子目录和文件。 | +| `fs:scope-download` | 这个有效範圍允许访问 `$DOWNLOAD` 文件夹中的所有文件和顶级目录的列表内容。 | +| `fs:scope-download-index` | 这个有效範圍允许列出 `$DOWNLOAD` 文件夹中的所有文件和文件夹。 | +| `fs:allow-exe-read-recursive` | 这个允许对完整的 `$EXE` 文件夹、文件和子目录进行完全递归读访问。 | +| `fs:allow-exe-write-recursive` | 这个允许对完整的 `$EXE` 文件夹、文件和子目录进行完全递归写访问。 | +| `fs:allow-exe-read` | 这个允许对 `$EXE` 文件夹进行非递归读访问。 | +| `fs:allow-exe-write` | 这个允许对 `$EXE` 文件夹进行非递归写访问。 | +| `fs:allow-exe-meta-recursive` | 这个允许对 `$EXE` 文件夹的元数据进行读访问,包括文件列表和统计資訊。 | +| `fs:allow-exe-meta` | 这个允许对 `$EXE` 文件夹的元数据进行读访问,包括文件列表和统计資訊。 | +| `fs:scope-exe-recursive` | 这个有效範圍递归访问完整的 `$EXE` 文件夹,包括子目录和文件。 | +| `fs:scope-exe` | 这个有效範圍允许访问 `$EXE` 文件夹中的所有文件和顶级目录的列表内容。 | +| `fs:scope-exe-index` | 这个有效範圍允许列出 `$EXE` 文件夹中的所有文件和文件夹。 | +| `fs:allow-font-read-recursive` | 这个允许对整个 `$FONT` 文件夹、文件和子目录进行完全递归读访问。 | +| `fs:allow-font-write-recursive` | 这个允许对整个 `$FONT` 文件夹、文件和子目录进行完全递归写访问。 | +| `fs:allow-font-read` | 这个允许对 `$FONT` 文件夹进行非递归读访问。 | +| `fs:allow-font-write` | 这个允许对 `$FONT` 文件夹进行非递归写访问。 | +| `fs:allow-font-meta-recursive` | 这个允许对 `$FONT` 文件夹的元数据进行读访问,包括文件列表和统计資訊。 | +| `fs:allow-font-meta` | 这个允许对 `$FONT` 文件夹的元数据进行读访问,包括文件列表和统计資訊。 | +| `fs:scope-font-recursive` | 这个有效範圍递归访问整个 `$FONT` 文件夹,包括子目录和文件。 | +| `fs:scope-font` | 这个有效範圍允许访问 `$FONT` 文件夹中的所有文件和顶级目录的列表内容。 | +| `fs:scope-font-index` | 这个有效範圍允许列出 `$FONT` 文件夹中的所有文件和文件夹。 | +| `fs:allow-home-read-recursive` | 这个允许对整个 `$HOME` 文件夹、文件和子目录进行完全递归读访问。 | +| `fs:allow-home-write-recursive` | 这个允许对整个 `$HOME` 文件夹、文件和子目录进行完全递归写访问。 | +| `fs:allow-home-read` | 这个允许对 `$HOME` 文件夹进行非递归读访问。 | +| `fs:allow-home-write` | 这个允许对 `$HOME` 文件夹进行非递归写访问。 | +| `fs:allow-home-meta-recursive` | 这个允许对 `$HOME` 文件夹的元数据进行读访问,包括文件列表和统计資訊。 | +| `fs:allow-home-meta` | 这个允许对 `$HOME` 文件夹的元数据进行读访问,包括文件列表和统计資訊。 | +| `fs:scope-home-recursive` | 这个有效範圍递归访问整个 `$HOME` 文件夹,包括子目录和文件。 | +| `fs:scope-home` | 这个有效範圍允许访问 `$HOME` 文件夹中的所有文件和顶级目录的列表内容。 | +| `fs:scope-home-index` | 这个有效範圍允许列出 `$HOME` 文件夹中的所有文件和文件夹。 | +| `fs:allow-localdata-read-recursive` | 这个允许对完整的 `$LOCALDATA` 文件夹、文件和子目录进行完全递归读访问。 | +| `fs:allow-localdata-write-recursive` | 这个允许对完整的 `$LOCALDATA` 文件夹、文件和子目录进行完全递归写访问。 | +| `fs:allow-localdata-read` | 这个允许对 `$LOCALDATA` 文件夹进行非递归读访问。 | +| `fs:allow-localdata-write` | 这个允许对 `$LOCALDATA` 文件夹进行非递归写访问。 | +| `fs:allow-localdata-meta-recursive` | 这个允许对 `$LOCALDATA` 文件夹的元数据进行读访问,包括文件列表和统计資訊。 | +| `fs:allow-localdata-meta` | 这个允许对 `$LOCALDATA` 文件夹的元数据进行读访问,包括文件列表和统计資訊。 | +| `fs:scope-localdata-recursive` | 这个有效範圍递归访问完整的 `$LOCALDATA` 文件夹,包括子目录和文件。 | +| `fs:scope-localdata` | 这个有效範圍允许访问 `$LOCALDATA` 文件夹中的所有文件和顶级目录的列表内容。 | +| `fs:scope-localdata-index` | 这个有效範圍允许列出 `$LOCALDATA` 文件夹中的所有文件和文件夹。 | +| `fs:allow-log-read-recursive` | 这个允许对完整的 `$LOG` 文件夹、文件和子目录进行完全递归读访问。 | +| `fs:allow-log-write-recursive` | 这个允许对完整的 `$LOG` 文件夹、文件和子目录进行完全递归写访问。 | +| `fs:allow-log-read` | 这个允许对 `$LOG` 文件夹进行非递归读访问。 | +| `fs:allow-log-write` | 这个允许对 `$LOG` 文件夹进行非递归写访问。 | +| `fs:allow-log-meta-recursive` | 这个允许对 `$LOG` 文件夹的元数据进行读访问,包括文件列表和统计資訊。 | +| `fs:allow-log-meta` | 这个允许对 `$LOG` 文件夹的元数据进行读访问,包括文件列表和统计資訊。 | +| `fs:scope-log-recursive` | 这个有效範圍递归访问完整的 `$LOG` 文件夹,包括子目录和文件。 | +| `fs:scope-log` | 这个有效範圍允许访问 `$LOG` 文件夹中的所有文件和顶级目录的列表内容。 | +| `fs:scope-log-index` | 这个有效範圍允许列出 `$LOG` 文件夹中的所有文件和文件夹。 | +| `fs:allow-picture-read-recursive` | 这个允许对完整的 `$PICTURE` 文件夹、文件和子目录进行完全递归读访问。 | +| `fs:allow-picture-write-recursive` | 这个允许对完整的 `$PICTURE` 文件夹、文件和子目录进行完全递归写访问。 | +| `fs:allow-picture-read` | 这个允许对 `$PICTURE` 文件夹进行非递归读访问。 | +| `fs:allow-picture-write` | 这个允许对 `$PICTURE` 文件夹进行非递归写访问。 | +| `fs:allow-picture-meta-recursive` | 这个允许对 `$PICTURE` 文件夹的元数据进行读访问,包括文件列表和统计資訊。 | +| `fs:allow-picture-meta` | 这个允许对 `$PICTURE` 文件夹的元数据进行读访问,包括文件列表和统计資訊。 | +| `fs:scope-picture-recursive` | 这个有效範圍递归访问完整的 `$PICTURE` 文件夹,包括子目录和文件。 | +| `fs:scope-picture` | 这个有效範圍允许访问 `$PICTURE` 文件夹中的所有文件和顶级目录的列表内容。 | +| `fs:scope-picture-index` | 这个有效範圍允许列出 `$PICTURE` 文件夹中的所有文件和文件夹。 | +| `fs:allow-public-read-recursive` | 这个允许对完整的 `$PUBLIC` 文件夹、文件和子目录进行完全递归读访问。 | +| `fs:allow-public-write-recursive` | 这个允许对完整的 `$PUBLIC` 文件夹、文件和子目录进行完全递归写访问。 | +| `fs:allow-public-read` | 这个允许对 `$PUBLIC` 文件夹进行非递归读访问。 | +| `fs:allow-public-write` | 这个允许对 `$PUBLIC` 文件夹进行非递归写访问。 | +| `fs:allow-public-meta-recursive` | 这个允许对 `$PUBLIC` 文件夹的元数据进行读访问,包括文件列表和统计資訊。 | +| `fs:allow-public-meta` | 这个允许对 `$PUBLIC` 文件夹的元数据进行读访问,包括文件列表和统计資訊。 | +| `fs:scope-public-recursive` | 这个有效範圍递归访问完整的 `$PUBLIC` 文件夹,包括子目录和文件。 | +| `fs:scope-public` | 这个有效範圍允许访问 `$PUBLIC` 文件夹中的所有文件和顶级目录的列表内容。 | +| `fs:scope-public-index` | 这个有效範圍允许列出 `$PUBLIC` 文件夹中的所有文件和文件夹。 | +| `fs:allow-resource-read-recursive` | 这个允许对完整的 `$RESOURCE` 文件夹、文件和子目录进行完全递归读访问。 | +| `fs:allow-resource-write-recursive` | 这个允许对完整的 `$RESOURCE` 文件夹、文件和子目录进行完全递归写访问。 | +| `fs:allow-resource-read` | 这个允许对 `$RESOURCE` 文件夹进行非递归读访问。 | +| `fs:allow-resource-write` | 这个允许对 `$RESOURCE` 文件夹进行非递归写访问。 | +| `fs:allow-resource-meta-recursive` | 这个允许对 `$RESOURCE` 文件夹的元数据进行读访问,包括文件列表和统计資訊。 | +| `fs:allow-resource-meta` | 这个允许对 `$RESOURCE` 文件夹的元数据进行读访问,包括文件列表和统计資訊。 | +| `fs:scope-resource-recursive` | 这个有效範圍递归访问完整的 `$RESOURCE` 文件夹,包括子目录和文件。 | +| `fs:scope-resource` | 这个有效範圍允许访问 `$RESOURCE` 文件夹中的所有文件和顶级目录的列表内容。 | +| `fs:scope-resource-index` | 这个有效範圍允许列出 `$RESOURCE` 文件夹中的所有文件和文件夹。 | +| `fs:allow-runtime-read-recursive` | 这个允许对完整的 `$RUNTIME` 文件夹、文件和子目录进行完全递归读访问。 | +| `fs:allow-runtime-write-recursive` | 这个允许对完整的 `$RUNTIME` 文件夹、文件和子目录进行完全递归写访问。 | +| `fs:allow-runtime-read` | 这个允许对 `$RUNTIME` 文件夹进行非递归读访问 | +| `fs:allow-runtime-write` | 这个允许对 `$RUNTIME` 文件夹进行非递归写访问 | +| `fs:allow-runtime-meta-recursive` | 这个允许对 `$RUNTIME` 文件夹的元数据进行读访问,包括文件列表和统计資訊。 | +| `fs:allow-runtime-meta` | 这个允许对 `$RUNTIME` 文件夹的元数据进行读访问,包括文件列表和统计資訊。 | +| `fs:scope-runtime-recursive` | 这个有效範圍递归访问完整的 `$RUNTIME` 文件夹,包括子目录和文件。 | +| `fs:scope-runtime` | 这个有效範圍允许访问 `$RUNTIME` 文件夹中的所有文件和顶级目录的列表内容。 | +| `fs:scope-runtime-index` | 这个有效範圍允许列出 `$RUNTIME` 文件夹中的所有文件和文件夹。 | +| `fs:allow-temp-read-recursive` | 这个允许对完整的 `$TEMP` 文件夹、文件和子目录进行完全递归读访问。 | +| `fs:allow-temp-write-recursive` | 这个允许对完整的 `$TEMP` 文件夹、文件和子目录进行完全递归写访问。 | +| `fs:allow-temp-read` | 这个允许对 `$TEMP` 文件夹进行非递归读访问。 | +| `fs:allow-temp-write` | 这个允许对 `$TEMP` 文件夹进行非递归写访问。 | +| `fs:allow-temp-meta-recursive` | 这个允许对 `$TEMP` 文件夹的元数据进行读访问,包括文件列表和统计資訊。 | +| `fs:allow-temp-meta` | 这个允许对 `$TEMP` 文件夹的元数据进行读访问,包括文件列表和统计資訊。 | +| `fs:scope-temp-recursive` | 这个有效範圍递归访问完整的 `$TEMP` 文件夹,包括子目录和文件。 | +| `fs:scope-temp` | 这个有效範圍允许访问 `$TEMP` 文件夹中的所有文件和顶级目录的列表内容。 | +| `fs:scope-temp-index` | 这个有效範圍允许列出 `$TEMP` 文件夹中的所有文件和文件夹。 | +| `fs:allow-template-read-recursive` | 这个允许对完整的 `$TEMPLATE` 文件夹、文件和子目录进行完全递归读访问。 | +| `fs:allow-template-write-recursive` | 这个允许对完整的 `$TEMPLATE` 文件夹、文件和子目录进行完全递归写访问。 | +| `fs:allow-template-read` | 这个允许对 `$TEMPLATE` 文件夹进行非递归读访问。 | +| `fs:allow-template-write` | 这个允许对 `$TEMPLATE` 文件夹进行非递归写访问。 | +| `fs:allow-template-meta-recursive` | 这个允许对 `$TEMPLATE` 文件夹的元数据进行读访问,包括文件列表和统计資訊。 | +| `fs:allow-template-meta` | 这个允许对 `$TEMPLATE` 文件夹的元数据进行读访问,包括文件列表和统计資訊。 | +| `fs:scope-template-recursive` | 这个有效範圍允许递归访问整个 `$TEMPLATE` 文件夹,包括子目录和文件。 | +| `fs:scope-template` | 这个有效範圍允许访问 `$TEMPLATE` 文件夹中的所有文件和顶级目录的列表内容。 | +| `fs:scope-template-index` | 这个有效範圍允许列出 `$TEMPLATE` 文件夹中的所有文件和文件夹。 | +| `fs:allow-video-read-recursive` | 这个允许对整个 `$VIDEO` 文件夹、文件和子目录进行完全递归读访问 | +| `fs:allow-video-write-recursive` | 这个允许对整个 `$VIDEO` 文件夹、文件和子目录进行完全递归写访问。 | +| `fs:allow-video-read` | 这个允许对 `$VIDEO` 文件夹进行非递归读访问。 | +| `fs:allow-video-write` | 这个允许对 `$VIDEO` 文件夹进行非递归写访问。 | +| `fs:allow-video-meta-recursive` | 这允许读取 `$VIDEO` 文件夹的元数据,包括文件列表和统计資訊。 | +| `fs:allow-video-meta` | 这允许读取 `$VIDEO` 文件夹的元数据,包括文件列表和统计資訊。 | +| `fs:scope-video-recursive` | 这个有效範圍允许递归访问整个 `$VIDEO` 文件夹,包括子目录和文件。 | +| `fs:scope-video` | 这个有效範圍允许访问 `$VIDEO` 文件夹中所有文件和顶级目录的列表内容。 | +| `fs:scope-video-index` | 这个有效範圍允许列出 `$VIDEO` 文件夹中的所有文件和文件夹。 | +| `fs:deny-webview-data-linux` | 这会拒绝对linux上的`$APPLOCALDATA`文件夹的读访问,因为webview数据和配置值都存储在这里。允许访问可能会导致敏感資訊泄露,应该仔细考虑。 | +| `fs:deny-webview-data-windows` | 这会拒绝对 Windows 上的 `$APPLOCALDATA/EBWebView` 文件夹的读访问,因为 webview 数据和配置值都存储在这里。允许访问可能会导致敏感資訊泄露,应该仔细考虑。 | + +### 命令的权限 + +| 权限 | 描述 | +| ------------------------------------ | ------------------------------------------------------------------------ | +| `fs:allow-copy-file` | 在没有预先配置的有效範圍的情况下启用 copy_file 命令。 | +| `fs:deny-copy-file` | 拒绝没有任何预配置范围的 copy_file 命令。 | +| `fs:allow-create` | 在没有预先配置的有效範圍的情况下启用 create 命令。 | +| `fs:deny-create` | 拒绝没有任何预配置范围的 create 命令。 | +| `fs:allow-exists` | 在没有预先配置的有效範圍的情况下启用 exists 命令。 | +| `fs:deny-exists` | 拒绝没有任何预配置范围的 exists 命令。 | +| `fs:allow-fstat` | 在没有预先配置的有效範圍的情况下启用 fstat 命令。 | +| `fs:deny-fstat` | 拒绝没有任何预配置范围的 fstat 命令。 | +| `fs:allow-ftruncate` | 在没有预先配置的有效範圍的情况下启用 ftruncate 命令。 | +| `fs:deny-ftruncate` | 拒绝没有任何预配置范围的 ftruncate 命令。 | +| `fs:allow-lstat` | 在没有预先配置的有效範圍的情况下启用 lstat 命令。 | +| `fs:deny-lstat` | 拒绝没有任何预配置范围的 lstat 命令。 | +| `fs:allow-mkdir` | 在没有预先配置的有效範圍的情况下启用 mkdir 命令。 | +| `fs:deny-mkdir` | 拒绝没有任何预配置范围的 mkdir 命令。 | +| `fs:allow-open` | 在没有预先配置的有效範圍的情况下启用 open 命令。 | +| `fs:deny-open` | 拒绝没有任何预配置范围的 open 命令。 | +| `fs:allow-read` | 在没有预先配置的有效範圍的情况下启用 read 命令。 | +| `fs:deny-read` | 拒绝没有任何预配置范围的 read 命令。 | +| `fs:allow-read-dir` | 在没有预先配置的有效範圍的情况下启用 read_dir 命令。 | +| `fs:deny-read-dir` | 拒绝没有任何预配置范围的 read_dir 命令。 | +| `fs:allow-read-file` | 在没有预先配置的有效範圍的情况下启用 read_file 命令。 | +| `fs:deny-read-file` | 拒绝没有任何预配置范围的 read_file 命令。 | +| `fs:allow-read-text-file` | 在没有预先配置的有效範圍的情况下启用 read_text_file 命令。 | +| `fs:deny-read-text-file` | 拒绝没有任何预配置范围的 read_text_file 命令。 | +| `fs:allow-read-text-file-lines` | 在没有预先配置的有效範圍的情况下启用 read_text_file_lines 命令。 | +| `fs:deny-read-text-file-lines` | 拒绝没有任何预配置范围的 read_text_file_lines 命令。 | +| `fs:allow-read-text-file-lines-next` | 在没有预先配置的有效範圍的情况下启用 read_text_file_lines_next 命令。 | +| `fs:deny-read-text-file-lines-next` | 拒绝没有任何预配置范围的 read_text_file_lines_next 命令。 | +| `fs:allow-remove` | 在没有预先配置的有效範圍的情况下启用 remove 命令。 | +| `fs:deny-remove` | 拒绝没有任何预配置范围的 remove 命令。 | +| `fs:allow-rename` | 在没有预先配置的有效範圍的情况下启用 rename 命令。 | +| `fs:deny-rename` | 拒绝没有任何预配置范围的 rename 命令。 | +| `fs:allow-seek` | 在没有预先配置的有效範圍的情况下启用 seek 命令。 | +| `fs:deny-seek` | 拒绝没有任何预配置范围的 seek 命令。 | +| `fs:allow-stat` | 在没有预先配置的有效範圍的情况下启用 stat 命令。 | +| `fs:deny-stat` | 拒绝没有任何预配置范围的 stat 命令。 | +| `fs:allow-truncate` | 在没有预先配置的有效範圍的情况下启用 truncate 命令。 | +| `fs:deny-truncate` | 拒绝没有任何预配置范围的 truncate 命令。 | +| `fs:allow-unwatch` | 在没有预先配置的有效範圍的情况下启用 unwatch 命令。 | +| `fs:deny-unwatch` | 拒绝没有任何预配置范围的 unwatch 命令。 | +| `fs:allow-watch` | 在没有预先配置的有效範圍的情况下启用 watch 命令。 | +| `fs:deny-watch` | 拒绝没有任何预配置范围的 watch 命令。 | +| `fs:allow-write` | 在没有预先配置的有效範圍的情况下启用 write 命令。 | +| `fs:deny-write` | 拒绝没有任何预配置范围的 write 命令。 | +| `fs:allow-write-file` | 在没有预先配置的有效範圍的情况下启用 write_file 命令。 | +| `fs:deny-write-file` | 拒绝没有任何预配置范围的 write_file 命令。 | +| `fs:allow-write-text-file` | 在没有预先配置的有效範圍的情况下启用 write_text_file 命令。 | +| `fs:deny-write-text-file` | 拒绝没有任何预配置范围的 write_text_file 命令。 | +| `fs:read-all` | 在没有预先配置可访问路径的情况下启用所有与读相关命令。 | +| `fs:read-dirs` | 在没有预先配置可访问路径的情况下启用所有与目录读和文件元数据相关的命令。 | +| `fs:read-files` | 在没有预先配置可访问路径的情况下启用所有与文件读相关的命令。 | +| `fs:read-meta` | 在没有预先配置可访问路径的情况下启用所有与索引或元数据相关的命令。 | +| `fs:scope` | 可用于修改全局有效範圍的空权限。 | +| `fs:write-all` | 在没有预先配置可访问路径的情况下启用所有与写相关命令。 | +| `fs:write-files` | 在没有预先配置可访问路径的情况下启用所有与文件写相关的命令。 | + +### 有效範圍范围 + +允许任何 `fs` 命令访问特定的有效範圍: + +```json title="src-tauri/capabilities/default.json" {7-10} +{ + "$schema": "../gen/schemas/desktop-schema.json", + "identifier": "main-capability", + "description": "Capability for the main window", + "windows": ["main"], + "permissions": [ + { + "identifier": "fs:scope", + "allow": [{ "path": "$APPDATA" }, { "path": "$APPDATA/**" }] + } + ] +} +``` + +允许特定的 `fs` 命令访问特定的有效範圍: + +```json title="src-tauri/capabilities/default.json" {7-14} +{ + "$schema": "../gen/schemas/desktop-schema.json", + "identifier": "main-capability", + "description": "Capability for the main window", + "windows": ["main"], + "permissions": [ + { + "identifier": "fs:allow-rename", + "allow": [{ "path": "$HOME/**" }] + }, + { + "identifier": "fs:allow-exists", + "allow": [{ "path": "$APPDATA/*" }] + } + ] +} +``` diff --git a/src/content/docs/zh-tw/plugin/global-shortcut.mdx b/src/content/docs/zh-tw/plugin/global-shortcut.mdx new file mode 100644 index 0000000000..afed779bd4 --- /dev/null +++ b/src/content/docs/zh-tw/plugin/global-shortcut.mdx @@ -0,0 +1,155 @@ +--- +title: 全局快捷方式 +description: 注册全局快捷方式。 +plugin: global-shortcut +--- + +import PluginLinks from '@components/PluginLinks.astro'; +import Compatibility from '@components/plugins/Compatibility.astro'; + +import { Tabs, TabItem } from '@astrojs/starlight/components'; +import CommandTabs from '@components/CommandTabs.astro'; + + + +注册全局快捷方式。 + +## 支持的平台 + + + +## 设置 + +请安装全局快捷方式外掛。 + + + + +使用项目的包管理器来新增依赖。 + +{ ' ' } + + + + + + +1. 通过将以下内容新增到 `Cargo.toml` 的文件中来安装全局快捷方式外掛。 + +```toml title="src-tauri/Cargo.toml" +# 如果你的目标不是移动设备,你可以在 `[dependencies]` 部分新增依赖 +[target."cfg(not(any(target_os = \"android\", target_os = \"ios\")))".dependencies] +tauri-plugin-global-shortcut = "2.0.0" +# 或者使用 Git +tauri-plugin-global-shortcut = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" } +``` + +2. 修改 `lib.rs` 来初始化外掛。 + +```rust title="src-tauri/src/lib.rs" ins={3} +fn run() { + tauri::Builder::default() + .plugin(tauri_plugin_global_shortcut::Builder::new().build()) + .run(tauri::generate_context!()) + .expect("error while running tauri application"); +} +``` + +3. 使用你喜欢的 JavaScript 包管理器安装 JavaScript Guest 绑定。 + + + + + +## 用法 + +全局快捷方式外掛有 JavaScript 和 Rust 两种版本。 + + + + +```javascript +import { register } from '@tauri-apps/plugin-global-shortcut'; + +await register('CommandOrControl+Shift+C', () => { + console.log('Shortcut triggered'); +}); +``` + + + + +```rust title="src-tauri/src/lib.rs" +fn run() { + tauri::Builder::default() + .setup(|app| { + #[cfg(desktop)] + { + use tauri_plugin_global_shortcut::{Code, GlobalShortcutExt, Modifiers, Shortcut}; + + let ctrl_n_shortcut = Shortcut::new(Some(Modifiers::CONTROL), Code::KeyN); + app.handle().plugin( + tauri_plugin_global_shortcut::Builder::new().with_handler(move |_app, shortcut| { + println!("{:?}", shortcut); + if shortcut == &ctrl_n_shortcut { + println!("Ctrl-N Detected!"); + } + }) + .build(), + )?; + + app.global_shortcut().register(ctrl_n_shortcut)?; + } + Ok(()) + }) + .run(tauri::generate_context!()) + .expect("error while running tauri application"); +} +``` + + + + +## 权限 + +默认情况下,所有外掛命令都被阻止,无法访问。你必须在你的 `capabilities` 配置中定义一个权限列表。 + +更多資訊请参见[访问控制列表](/zh-tw/reference/acl/)。 + +```json title="src-tauri/capabilities/default.json" ins={7-9} +{ + "$schema": "./schemas/desktop-schema.json", + "identifier": "main-capability", + "description": "Capability for the main window", + "windows": ["main"], + "permissions": [ + "global-shortcut:allow-is-registered", + "global-shortcut:allow-register", + "global-shortcut:allow-unregister" + ] +} +``` + +| 权限 | 描述 | +| -------------------------------------- | -------------------------------------------------------- | +| `global-shortcut:allow-is-registered` | 在没有预先配置有效範圍的情况下,启用 is_registered 命令。 | +| `global-shortcut:deny-is-registered` | 拒绝没有任何预先配置的有效範圍的 is_registered 命令。 | +| `global-shortcut:allow-register` | 在没有预先配置有效範圍的情况下,启用 register 命令。 | +| `global-shortcut:deny-register` | 拒绝没有任何预先配置的有效範圍的 is_registered 命令。 | +| `global-shortcut:allow-register-all` | 在没有预先配置有效範圍的情况下,启用 is_registered 命令。 | +| `global-shortcut:deny-register-all` | 拒绝没有任何预先配置的有效範圍的 is_registered 命令。 | +| `global-shortcut:allow-unregister` | 在没有预先配置有效範圍的情况下,启用 is_registered 命令。 | +| `global-shortcut:deny-unregister` | 拒绝没有任何预先配置的有效範圍的 is_registered 命令。 | +| `global-shortcut:allow-unregister-all` | 在没有预先配置有效範圍的情况下,启用 unregister_all 命令。 | +| `global-shortcut:deny-unregister-all` | 拒绝没有任何预先配置的有效範圍的 unregister_all 命令。 | diff --git a/src/content/docs/zh-tw/plugin/http-client.mdx b/src/content/docs/zh-tw/plugin/http-client.mdx new file mode 100644 index 0000000000..cdb69ee268 --- /dev/null +++ b/src/content/docs/zh-tw/plugin/http-client.mdx @@ -0,0 +1,122 @@ +--- +title: HTTP 客户端 +description: 访问用 Rust 编写的 HTTP 客户端。 +plugin: http +--- + +import PluginLinks from '@components/PluginLinks.astro'; +import Compatibility from '@components/plugins/Compatibility.astro'; + +import { Tabs, TabItem, Steps } from '@astrojs/starlight/components'; +import CommandTabs from '@components/CommandTabs.astro'; + + + +使用 HTTP 外掛发起 HTTP 请求。 + +## Supported Platforms + + + +## 设置 + +请安装 http 外掛。 + + + + + 使用项目的包管理器来新增依赖: + + + + + + + 1. 运行 `cargo add tauri-plugin-http` 命令,将外掛新增到项目的 `cargo.toml` 依赖中。 + + 2. 修改 lib.rs 来初始化外掛。 + + ```rust ins={6} + // lib.rs + #[cfg_attr(mobile, tauri::mobile_entry_point)] + pub fn run() { + tauri::Builder::default() + // Initialize the plugin + .plugin(tauri_plugin_http::init()) + .run(tauri::generate_context!()) + .expect("error while running tauri application"); + } + ``` + + 3. 如果你想用 JavaScript 发送 http 请求,还需要安装 npm 包。 + + + + + + + +## 用法 + +http 外掛既有 JavaScript API 版本,也有 Rust [reqwest](https://docs.rs/reqwest/) 重新导出的版本。 + +### JavaScript + + + +1. 配置允许访问的 URL + + ```json + //src-tauri/capabilities/base.json + { + "permissions": [ + { + "identifier": "http:default", + "allow": [{ "url": "https://*.tauri.app" }], + "deny": [{ "url": "https://private.tauri.app" }] + } + ] + } + ``` + + 更多資訊,请参阅[权限概述](/zh-tw/security/permissions/)的文档。 + +2. 发送请求 + + ```javascript + import { fetch } from '@tauri-apps/plugin-http'; + + // Send a GET request + const response = await fetch('http://my.api.host/data.json', { + method: 'GET', + }); + console.log(response.status); // e.g. 200 + console.log(response.statusText); // e.g. "OK" + ``` + + :::note + 当前的 `fetch` 方法是一个 Rust 后端 API。 它试图与 [`fetch` Web API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) 尽可能接近和兼容。 + ::: + + + +### Rust + +在 Rust 中,你可以利用外掛重新导出的 `reqwest` 包。更多细节请参考 [reqwest 文档](https://docs.rs/reqwest/)。 + +```rust +use tauri_plugin_http::reqwest; + +let res = reqwest::get("http://my.api.host/data.json").await; +println!("{:?}", res.status()); // e.g. 200 +println!("{:?}", res.text().await); // e.g Ok("{ Content }") +``` diff --git a/src/content/docs/zh-tw/plugin/index.mdx b/src/content/docs/zh-tw/plugin/index.mdx new file mode 100644 index 0000000000..d8f6290e12 --- /dev/null +++ b/src/content/docs/zh-tw/plugin/index.mdx @@ -0,0 +1,30 @@ +--- +title: 功能及秘诀列表 +i18nReady: true +--- + +import { LinkCard } from '@astrojs/starlight/components'; +import FeaturesList from '@components/list/Features.astro'; +import CommunityList from '@components/list/Community.astro'; +import Search from '@components/CardGridSearch.astro'; +import AwesomeTauri from '@components/AwesomeTauri.astro'; + +Tauri 考虑到了可扩展性。在此页面上,你可以找到: + +- **[特性](#特性)**:Tauri 内置功能和特性 +- **[社区资源](#社区资源)**:更多由 Tauri 社区创作的外掛和秘诀 + + + ## 特性 + + ## 社区资源 + + ### 外掛 + + ### 集成 + + diff --git a/src/content/docs/zh-tw/plugin/localhost.mdx b/src/content/docs/zh-tw/plugin/localhost.mdx new file mode 100644 index 0000000000..d7340f6a20 --- /dev/null +++ b/src/content/docs/zh-tw/plugin/localhost.mdx @@ -0,0 +1,71 @@ +--- +title: Localhost +description: 在生产环境中使用 localhost 服务器。 +plugin: localhost +--- + +import PluginLinks from '@components/PluginLinks.astro'; +import Compatibility from '@components/plugins/Compatibility.astro'; + +import { Tabs, TabItem } from '@astrojs/starlight/components'; +import CommandTabs from '@components/CommandTabs.astro'; + + + +通过 localhost 服务器而不是默认的自定义协议公开你的应用资源。 + +:::caution +这个外掛带来了相当大的安全风险,你只应该在知道你在做什么的情况下使用它。如果有疑问,请使用默认的自定义协议实现。 +::: + +## 支持的平台 + +- Windows +- Linux +- macOS + +## 设置 + +1. 通过将以下内容新增到 `Cargo.toml` 中来安装 localhost 外掛。 + +```toml title="src-tauri/Cargo.toml" +[dependencies] +tauri-plugin-localhost = "2.0.0" +# 或者使用 Git: +tauri-plugin-localhost = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" } +``` + +2. 修改 `lib.rs` 来初始化外掛。 + +```rust title="src-tauri/src/lib.rs" ins={3} +fn run() { + tauri::Builder::default() + .plugin(tauri_plugin_localhost::Builder::new().build()) + .run(tauri::generate_context!()) + .expect("error while running tauri application"); +} +``` + +## 用法 + +Rust 提供了 localhost 外掛。 + +```rust title="src-tauri/src/lib.rs" {4} {7-14} +use tauri::{webview::WebviewWindowBuilder, WebviewUrl}; + +fn run() { + let port: u16 = 9527; + + tauri::Builder::default() + .plugin(tauri_plugin_localhost::Builder::new(port).build()) + .setup(move |app| { + let url = format!("http://localhost:{}", port).parse().unwrap(); + WebviewWindowBuilder::new(app, "main".to_string(), WebviewUrl::External(url)) + .title("Localhost Example") + .build()?; + Ok(()) + }) + .run(tauri::generate_context!()) + .expect("error while running tauri application"); +} +``` diff --git a/src/content/docs/zh-tw/plugin/logging.mdx b/src/content/docs/zh-tw/plugin/logging.mdx new file mode 100644 index 0000000000..41e7f2410c --- /dev/null +++ b/src/content/docs/zh-tw/plugin/logging.mdx @@ -0,0 +1,135 @@ +--- +title: 日志记录 +description: 可配置的日志记录。 +plugin: log +--- + +import PluginLinks from '@components/PluginLinks.astro'; +import Compatibility from '@components/plugins/Compatibility.astro'; + +import { Tabs, TabItem } from '@astrojs/starlight/components'; +import CommandTabs from '@components/CommandTabs.astro'; + + + +为你的 Tauri 应用程序配置日志记录。 + +## 支持的平台 + + + +## 设置 + +请安装日志外掛。 + + + + +使用项目的包管理器来新增依赖。 + +{ ' ' } + + + + + + +1. 通过将以下内容新增到 `Cargo.toml` 的文件中来安装日志外掛。 + +```toml title="src-tauri/Cargo.toml" +[dependencies] +tauri-plugin-log = "2.0.0" +# 或者使用 Git: +tauri-plugin-log = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" } +``` + +2. 修改 `lib.rs` 来初始化外掛。 + +```rust title="src-tauri/src/lib.rs" ins={4} +#[cfg_attr(mobile, tauri::mobile_entry_point)] +fn run() { + tauri::Builder::default() + .plugin(tauri_plugin_log::Builder::new().build()) + .run(tauri::generate_context!()) + .expect("error while running tauri application"); +} +``` + +3. 使用你喜欢的 JavaScript 包管理器安装 JavaScript Guest 绑定。 + + + + + +## 用法 + +1. 首先,您需要在 Tauri 上注册外掛。 + +```rust title="src-tauri/src/lib.rs" {1} {6-14} +use tauri_plugin_log::{Target, TargetKind}; + +#[cfg_attr(mobile, tauri::mobile_entry_point)] +pub fn run() { + tauri::Builder::default() + .plugin( + tauri_plugin_log::Builder::new() + .targets([ + Target::new(TargetKind::Stdout), + Target::new(TargetKind::LogDir { file_name: None }), + Target::new(TargetKind::Webview), + ]) + .build(), + ) + .run(tauri::generate_context!()) + .expect("error while running tauri application"); +} +``` + +2. 然后,外掛的所有 api 都可以通过 JavaScript 的 guest 绑定使用: + +```javascript +import { trace, info, error, attachConsole } from '@tauri-apps/plugin-log'; + +// 启用 TargetKind::Webview 后,这个函数将把日志打印到浏览器控制台 +const detach = await attachConsole(); + +trace('Trace'); +info('Info'); +error('Error'); + +// 将浏览器控制台与日志流分离 +detach(); +``` + +## 权限 + +默认情况下,所有外掛命令都被阻止,无法访问。你必须在你的 `capabilities` 配置中定义一个权限列表。 + +更多資訊请参见[访问控制列表](/zh-tw/reference/acl/)。 + +```json title="src-tauri/capabilities/default.json" ins={6} +{ + "$schema": "./schemas/desktop-schema.json", + "identifier": "main-capability", + "description": "Capability for the main window", + "windows": ["main"], + "permissions": ["log:default"] +} +``` + +| 权限 | 描述 | +| --------------- | -------------------------------------------- | +| `log:default` | 允许日志命令。 | +| `log:allow-log` | 在没有预先配置有效範圍的情况下,允许日志命令。 | +| `log:deny-log` | 拒绝使用没有预先配置有效範圍的允许日志命令。 | diff --git a/src/content/docs/zh-tw/plugin/notification.mdx b/src/content/docs/zh-tw/plugin/notification.mdx new file mode 100644 index 0000000000..0d23515857 --- /dev/null +++ b/src/content/docs/zh-tw/plugin/notification.mdx @@ -0,0 +1,148 @@ +--- +title: 通知提示 +description: 向用户发送本地通知提示。 +i18nReady: true +plugin: notification +--- + +import PluginLinks from '@components/PluginLinks.astro'; +import Compatibility from '@components/plugins/Compatibility.astro'; + +import { Tabs, TabItem } from '@astrojs/starlight/components'; +import CommandTabs from '@components/CommandTabs.astro'; +import Stub from '@components/Stub.astro'; + + + +使用通知提示外掛以向你的用户发送原生通知。 + +## Supported Platforms + + + +## 配置 + +首先,下载通知提示外掛 + + + + + 使用你的项目的包管理器以新增依赖: + + + + + + + 1. 运行 `cargo add tauri-plugin-notification` 以将外掛新增到 `Cargo.toml` 的项目依赖中。 + + 2. 修改 `lib.rs` 以初始化外掛: + + ```rust + // lib.rs + #[cfg_attr(mobile, tauri::mobile_entry_point)] + pub fn run() { + tauri::Builder::default() + // 初始化外掛 + .plugin(tauri_plugin_notification::init()) + .run(tauri::generate_context!()) + .expect("error while running tauri application"); + } + ``` + + 3. 如果你想要在 JavaScript 中使用通知提示,请安装相应的 npm 包: + + + + + + + +## 使用 + +以下是一些如何使用通知外掛的示例: + +- [向用户发送通知](#发送通知) +- [向通知中新增一个行为](#行为动作) +- [向通知新增附件](#附件) +- [在特定频道中发送通知](#频道) + +{/* TODO: Link to which language to use, frontend vs. backend guide when it's made */} + +通知外掛有 JavaScript 和 Rust 两种版本。 + +### 发送通知 + +{/* TODO: Demo component */} + +按照以下步骤发送通知: + +1. 检查是否授予了权限 +2. 如果未授予,请求权限 +3. 发送通知 + + + + +```javascript +import { + isPermissionGranted, + requestPermission, + sendNotification, +} from '@tauri-apps/plugin-notification'; + +// 你有发送通知的权限吗? +let permissionGranted = await isPermissionGranted(); + +// 如果没有,我们需要请求它 +if (!permissionGranted) { + const permission = await requestPermission(); + permissionGranted = permission === 'granted'; +} + +// 一旦获得许可,我们就可以发送通知 +if (permissionGranted) { + sendNotification({ title: 'Tauri', body: 'Tauri is awesome!' }); +} +``` + + + + +{/* TODO: */} + + + + + + +### 行为动作 + +{/* TODO: */} + + + +### 附件 + +{/* TODO: */} + + + +### 频道 + +{/* TODO: */} + + + +## 安全考虑 + +除了用户输入的正常数据净化程序之外,目前还没有已知的安全考虑因素。 diff --git a/src/content/docs/zh-tw/plugin/opener.mdx b/src/content/docs/zh-tw/plugin/opener.mdx new file mode 100644 index 0000000000..d2411ceb6c --- /dev/null +++ b/src/content/docs/zh-tw/plugin/opener.mdx @@ -0,0 +1,135 @@ +--- +title: 指定打开应用 +description: 在外部应用中打开文件和URL。 +plugin: opener +--- + +import PluginLinks from '@components/PluginLinks.astro'; +import Compatibility from '@components/plugins/Compatibility.astro'; + +import { Tabs, TabItem, Steps } from '@astrojs/starlight/components'; +import CommandTabs from '@components/CommandTabs.astro'; +import PluginPermissions from '@components/PluginPermissions.astro'; + + + +此外掛允许你使用特定或者默认的应用程序打开文件或者 URL。它还可以在系统文件管理器中“显示”这些文件。 + +## 支持的平台 + + + +## 设置 + +首先安装“指定打开应用”外掛。 + + + + 使用项目的包管理器来新增依赖: + { ' ' } + + + + + + 1. 在 `src-tauri` 目录下,运行下面的命令。将此外掛新增到项目的 `Cargo.toml` 文件的 `dependencies` 字段中: + + ```sh frame=none + cargo add tauri-plugin-opener + ``` + + 2. 修改 `lib.rs` 文件,初始化此外掛: + + ```rust title="src-tauri/src/lib.rs" ins={4} + #[cfg_attr(mobile, tauri::mobile_entry_point)] + pub fn run() { + tauri::Builder::default() + .plugin(tauri_plugin_opener::init()) + .run(tauri::generate_context!()) + .expect("error while running tauri application"); + } + ``` + + 3. 使用你喜欢的 JavaScript 包管理器来新增 JavaScript 端的外掛绑定: + + + + + + + +## 用法 + +此外掛有 JavaScript 和 Rust 两种调用方式。 + + + + +```javascript +import { openPath } from '@tauri-apps/plugin-opener'; +// 当配置为 `"withGlobalTauri": true` 时,你可以使用下面方式引入此外掛 +// const { openPath } = window.__TAURI__.opener; + +// 使用默认的应用来打开文件 +await openPath('/path/to/file'); +// 在 Windows 上使用 `vlc` 打开文件 +await openPath('C:/path/to/file', 'vlc'); +``` + + + + +下面代码中的 `app` 变量是 `App` 或者 [`AppHandle`](https://docs.rs/tauri/2.0.0/tauri/struct.AppHandle.html) 的实例。 + +```rust +use tauri_plugin_opener::OpenerExt; + +// 使用默认的应用来打开文件: +app.opener().open_path("/path/to/file", None::<&str>); +// 在 Windows 上使用 `vlc` 打开文件: +app.opener().open_path("C:/path/to/file", Some("vlc")); +``` + + + + + +## 权限 + +默认情况下,所有具有潜在危险的外掛命令和范围都会被阻止且无法访问。您必须修改 `capabilities` 文件夹中的配置来启用它们。 + +参见[能力概览](/zh-tw/security/capabilities/)以获取更多資訊,以及外掛的[分步导览](/zh-tw/learn/security/using-plugin-permissions/)来调整外掛权限。 + +```json title="src-tauri/capabilities/default.json" ins={6-15} +{ + "$schema": "../gen/schemas/desktop-schema.json", + "identifier": "main-capability", + "description": "Capability for the main window", + "windows": ["main"], + "permissions": [ + { + "identifier": "opener:allow-open-path", + "allow": [ + { + "path": "/path/to/file" + } + ] + } + ] +} +``` + + diff --git a/src/content/docs/zh-tw/plugin/os-info.mdx b/src/content/docs/zh-tw/plugin/os-info.mdx new file mode 100644 index 0000000000..268ae11cd3 --- /dev/null +++ b/src/content/docs/zh-tw/plugin/os-info.mdx @@ -0,0 +1,99 @@ +--- +title: 操作系统資訊 +description: 查看操作系统資訊。 +plugin: os +--- + +import PluginLinks from '@components/PluginLinks.astro'; +import Compatibility from '@components/plugins/Compatibility.astro'; + +import { Tabs, TabItem } from '@astrojs/starlight/components'; +import CommandTabs from '@components/CommandTabs.astro'; + + + +使用操作系统資訊外掛读取操作系统資訊。 + +## Supported Platforms + + + +## 设置 + +安装操作系统資訊外掛开始。 + + + + + 使用项目的包管理器来新增依赖: + + + + + + + 1. 运行 `cargo add tauri-plugin-os` 命令,将外掛新增到项目的 cargo .toml 依赖中。 + + 2. 修改 lib.rs 来初始化外掛。 + + ```rust + // lib.rs + #[cfg_attr(mobile, tauri::mobile_entry_point)] + pub fn run() { + tauri::Builder::default() + // Initialize the plugin + .plugin(tauri_plugin_os::init()) + .run(tauri::generate_context!()) + .expect("error while running tauri application"); + } + ``` + + 3. 如果你想在 JavaScript 中使用,还需要安装 npm 包。 + + + + + + + +## 用法 + +通过这个外掛,您可以查询当前操作系统的多个資訊。请参阅 [JavaScript API](/zh-tw/reference/javascript/os/) 或 [Rust API](https://docs.rs/tauri-plugin-os/) 参考资料中的所有可用函数。 + +{/* TODO: Link to which language to use, frontend vs. backend guide when it's made */} + +#### 示例:操作系统平台 + +`platform` 返回一个描述使用的特定操作系统的字符串。该值在编译时设置。可能的值有 `linux`、`macos`、`ios`、`freebsd`、`dragonfly`、`netbsd`、`openbsd`、`solaris`、`android`、`windows`。 + + + + +```javascript +import { platform } from '@tauri-apps/plugin-os'; + +const currentPlatform = platform(); +console.log(currentPlatform); +// Prints "windows" to the console +``` + + + + +```rust +let platform = tauri_plugin_os::platform(); +println!("Platform: {}", platform); +// Prints "windows" to the terminal +``` + + + diff --git a/src/content/docs/zh-tw/plugin/persisted-scope.mdx b/src/content/docs/zh-tw/plugin/persisted-scope.mdx new file mode 100644 index 0000000000..947918e998 --- /dev/null +++ b/src/content/docs/zh-tw/plugin/persisted-scope.mdx @@ -0,0 +1,53 @@ +--- +title: 持久化有效範圍(Persisted Scope) +description: 将运行时有效範圍的更改持久化到文件系统上。 +plugin: persisted-scope +--- + +import PluginLinks from '@components/PluginLinks.astro'; +import Compatibility from '@components/plugins/Compatibility.astro'; + +import { Tabs, TabItem } from '@astrojs/starlight/components'; +import CommandTabs from '@components/CommandTabs.astro'; + + + +保存文件系统和资源有效範圍,并在应用重新打开时恢复它们。 + +## 支持的平台 + +- Windows +- Linux +- macOS + +## 设置 + +请安装 persistent-scope 外掛。 + +:::note +目前需要手动安装设置 persistent-scope 外掛。 +::: + +1. 在你的 `Cargo.toml` 文件中新增以下内容来安装外掛。 + +```toml title="src-tauri/Cargo.toml" +[dependencies] +tauri-plugin-persisted-scope = "2.0.0" +# 或者使用 Git: +tauri-plugin-persisted-scope = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" } +``` + +2. 修改 `lib.rs` 来初始化外掛。 + +```rust title="src-tauri/src/lib.rs" {3} +fn run() { + tauri::Builder::default() + .plugin(tauri_plugin_persisted_scope::init()) + .run(tauri::generate_context!()) + .expect("error while running tauri application"); +} +``` + +## 用法 + +安装后,外掛将自动保存和恢复文件系统和资源范围。 diff --git a/src/content/docs/zh-tw/plugin/positioner.mdx b/src/content/docs/zh-tw/plugin/positioner.mdx new file mode 100644 index 0000000000..1b3b07d80e --- /dev/null +++ b/src/content/docs/zh-tw/plugin/positioner.mdx @@ -0,0 +1,149 @@ +--- +title: 定位器(Positioner) +description: 将窗口移动到公共位置。 +plugin: positioner +--- + +import PluginLinks from '@components/PluginLinks.astro'; +import Compatibility from '@components/plugins/Compatibility.astro'; + +import { Steps, Tabs, TabItem } from '@astrojs/starlight/components'; +import CommandTabs from '@components/CommandTabs.astro'; + + + +把窗口放在你熟悉的地方。 + +这个外掛是 [electron-positioner](https://github.com/jenslind/electron-positioner) 的 Tauri 版本。 + +## 支持的平台 + + + +## 设置 + +请安装定位器外掛。 + +:::note +如果你只想从 Rust 代码中移动窗口,你只需要 `src-tauri/Cargo.toml` 中的依赖,并且如果你选择自动安装,可以从 `lib.rs` 中删除外掛注册。 +::: + + + + + 使用项目的包管理器来新增依赖。 + + { ' ' } + + + + + + + 1. 在你的 `Cargo.toml` 文件中新增以下内容来安装定位器外掛。 + + ```toml title="src-tauri/Cargo.toml" + [dependencies] + tauri-plugin-positioner = "2.0.0" + # 或者使用 Git: + tauri-plugin-positioner = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" } + ``` + + 2. 修改 `lib.rs` 来初始化外掛。 + + ```rust title="src-tauri/src/lib.rs" ins={3} + fn run() { + tauri::Builder::default() + .plugin(tauri_plugin_positioner::init()) + .run(tauri::generate_context!()) + .expect("error while running tauri application"); + } + ``` + + 3. 使用你喜欢的 JavaScript 包管理器安装 JavaScript Guest 绑定。 + + + + + + +需要额外的设置才能使托盘相对位置工作。 + + + 1. 在你的 `Cargo.toml` 文件中新增 `tray-icon` 功能。 + ```toml title="src-tauri/Cargo.toml" ins={2} + [dependencies] + tauri-plugin-positioner = { version = "2.0.0", features = ["tray-icon"] } + ``` + + 2. 为定位器外掛设置 `on_tray_event`。 + ```rust title="src-tauri/src/lib.rs" ins={4-12} + fn run() { + tauri::Builder::default() + .plugin(tauri_plugin_positioner::init()) + // This is required to get tray-relative positions to work + .setup(|app| { + TrayIconBuilder::new() + .on_tray_icon_event(|app, event| { + tauri_plugin_positioner::on_tray_event(app.app_handle(), &event); + }) + .build(app)?; + Ok(()) + }) + .run(tauri::generate_context!()) + .expect("error while running tauri application"); + } + ``` + + + +## 用法 + +外掛的 API 可以通过 JavaScript Guest 绑定获得。 + +```javascript +import { moveWindow, Position } from '@tauri-apps/plugin-positioner'; + +moveWindow(Position.TopRight); +``` + +你可以直接通过 Rust 导入和使用 Window trait 扩展。 + +```rust +use tauri_plugin_positioner::{WindowExt, Position}; + +let mut win = app.get_webview_window("main").unwrap(); +let _ = win.as_ref().window().move_window(Position::TopRight); +``` + +## 权限 + +默认情况下,所有外掛命令都被阻止,无法访问。你必须在你的 `capabilities` 配置中定义一个权限列表。 + +更多資訊请参见[访问控制列表](/zh-tw/reference/acl/)。 + +```json title="src-tauri/capabilities/default.json" ins={4} +{ + "permissions": [ + ..., + "positioner:default", + ] +} +``` + +| 权限 | 描述 | +| ------------------------------ | ----------------------------------------------------- | +| `positioner:allow-move-window` | 在没有预先配置的有效範圍的情况下启用 move_window 命令。 | +| `positioner:deny-move-window` | 拒绝没有任何预配置范围的 move_window 命令。 | +| `positioner:default` | 允许 move_window 命令。 | diff --git a/src/content/docs/zh-tw/plugin/process.mdx b/src/content/docs/zh-tw/plugin/process.mdx new file mode 100644 index 0000000000..b74d71f785 --- /dev/null +++ b/src/content/docs/zh-tw/plugin/process.mdx @@ -0,0 +1,98 @@ +--- +title: 进程 +description: 访问当前进程。 +plugin: process +--- + +import PluginLinks from '@components/PluginLinks.astro'; +import Compatibility from '@components/plugins/Compatibility.astro'; + +import { Tabs, TabItem } from '@astrojs/starlight/components'; +import CommandTabs from '@components/CommandTabs.astro'; + + + +这个外掛提供了访问当前进程的 API。要生成子进程,请参阅 [shell](/zh-tw/plugin/shell/) 外掛。 + +## Supported Platforms + + + +## 设置 + +从安装 `plugin-process` 开始使用。 + + + + + 使用项目的包管理器来新增依赖: + + + + + + + 1. 运行 `cargo add tauri-plugin-process` 命令,将外掛新增到项目的 `Cargo.toml` 依赖中。 + + 2. 修改 `lib.rs` 来初始化外掛。 + + ```rust ins={6} + // lib.rs + #[cfg_attr(mobile, tauri::mobile_entry_point)] + pub fn run() { + tauri::Builder::default() + // Initialize the plugin + .plugin(tauri_plugin_process::init()) + .run(tauri::generate_context!()) + .expect("error while running tauri application"); + } + ``` + + 3. 如果你想在 JavaScript 中使用这个外掛,还需要安装 npm 包。 + + + + + + +## 用法 + +这个外掛有 JavaScript 和 Rust 两种版本。 + + + + +```javascript +import { exit, relaunch } from '@tauri-apps/plugin-process'; + +// exits the app with the given status code +await exit(0); + +// restarts the app +await relaunch(); +``` + + + + +请注意,`app` 是 [`AppHandle`](https://docs.rs/tauri/2.0.0/tauri/struct.AppHandle.html) 的一个实例。 + +```rust +// exits the app with the given status code +app.exit(0); + +// restarts the app +app.restart(); +``` + + + diff --git a/src/content/docs/zh-tw/plugin/shell.mdx b/src/content/docs/zh-tw/plugin/shell.mdx new file mode 100644 index 0000000000..91a508b1a3 --- /dev/null +++ b/src/content/docs/zh-tw/plugin/shell.mdx @@ -0,0 +1,157 @@ +--- +title: Shell +description: 访问系统 shell 来生成子进程。 +plugin: shell +--- + +import PluginLinks from '@components/PluginLinks.astro'; +import Compatibility from '@components/plugins/Compatibility.astro'; + +import { Steps, Tabs, TabItem } from '@astrojs/starlight/components'; +import CommandTabs from '@components/CommandTabs.astro'; +import PluginPermissions from '@components/PluginPermissions.astro'; + + + +访问系统 shell。允许你生成子进程。 + +## 支持的平台 + + + +## 指定打开应用 + +如果你正在查找 `shell.open` 接口的文档,请查看新的[指定打开应用外掛](../opener/)。 + +## 设置 + +请从安装 shell 外掛开始。 + + + + 使用项目的包管理器来新增依赖。 + + { ' ' } + + + + + + 1. 在 `src-tauri` 目录下,运行下面的命令。将此外掛新增到项目的 `Cargo.toml` 文件的 `dependencies` 字段中。 + + ```sh frame=none + cargo add tauri-plugin-shell + ``` + + 2. 修改 `lib.rs` 来初始化外掛。 + + ```rust title="src-tauri/src/lib.rs" ins={4} + #[cfg_attr(mobile, tauri::mobile_entry_point)] + pub fn run() { + tauri::Builder::default() + .plugin(tauri_plugin_shell::init()) + .run(tauri::generate_context!()) + .expect("error while running tauri application"); + } + ``` + + 3. 使用你喜欢的 JavaScript 包管理器安装 JavaScript Guest 绑定。 + + + + + + + +## 用法 + +Shell 外掛有 JavaScript 和 Rust 两种版本。 + + + + +```javascript +import { Command } from '@tauri-apps/plugin-shell'; +// 当设置 `"withGlobalTauri": true`, 你可以使用 +// const { Command } = window.__TAURI__.shell; + +let result = await Command.create('exec-sh', [ + '-c', + "echo 'Hello World!'", +]).execute(); +console.log(result); +``` + + + + +```rust +use tauri_plugin_shell::ShellExt; + +let shell = app_handle.shell(); +let output = tauri::async_runtime::block_on(async move { + shell + .command("echo") + .args(["Hello from Rust!"]) + .output() + .await + .unwrap() +}); +if output.status.success() { + println!("Result: {:?}", String::from_utf8(output.stdout)); +} else { + println!("Exit with code: {}", output.status.code().unwrap()); +} +``` + + + + + +## 权限 + +默认情况下,所有具有潜在危险的外掛命令和范围都会被阻止且无法访问。您必须修改 `capabilities` 文件夹中的配置来启用它们。 + +参见[能力概览](/zh-tw/security/capabilities/)以获取更多資訊,以及外掛的[分步导览](/zh-tw/learn/security/using-plugin-permissions/)来调整外掛权限。 + +```json title="src-tauri/capabilities/default.json" ins={6-23} +{ + "$schema": "../gen/schemas/desktop-schema.json", + "identifier": "main-capability", + "description": "Capability for the main window", + "windows": ["main"], + "permissions": [ + { + "identifier": "shell:allow-execute", + "allow": [ + { + "name": "exec-sh", + "cmd": "sh", + "args": [ + "-c", + { + "validator": "\\S+" + } + ], + "sidecar": false + } + ] + } + ] +} +``` + + diff --git a/src/content/docs/zh-tw/plugin/single-instance.mdx b/src/content/docs/zh-tw/plugin/single-instance.mdx new file mode 100644 index 0000000000..9c5990f844 --- /dev/null +++ b/src/content/docs/zh-tw/plugin/single-instance.mdx @@ -0,0 +1,121 @@ +--- +title: 单例 +description: 确保一次只运行一个 Tauri 应用程序实例。 +plugin: single-instance +--- + +import PluginLinks from '@components/PluginLinks.astro'; +import Compatibility from '@components/plugins/Compatibility.astro'; + +import { Tabs, TabItem, Steps } from '@astrojs/starlight/components'; +import CommandTabs from '@components/CommandTabs.astro'; + + + +使用单实例外掛确保 Tauri 应用程序在同一时间只运行单个实例。 + +## Supported Platforms + + + +## 设置 + +请安装单例外掛。 + + + + + 使用项目的包管理器来新增依赖。 + + + + + + +
    +
  1. + **安装:** 在 `Cargo.toml` 中将外掛新增到项目的依赖中。 + + + ```toml title="src-tauri/Cargo.toml" ins={2} + [dependencies] + tauri-plugin-single-instance = "2.0.0" + ``` + + + + ```toml title="src-tauri/Cargo.toml" ins={2} + [dependencies] + tauri-plugin-single-instance = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" } + ``` + + +
  2. +
  3. + **初始化:** 更新 `lib.rs` (或者只针对桌面应用的 `main.rs`) 来初始化外掛。 + + ```rust title="src-tauri/src/lib.rs" ins={3} + pub fn run() { + tauri::Builder::default() + .plugin(tauri_plugin_single_instance::init(|app, args, cwd| {})) + .run(tauri::generate_context!()) + .expect("error while running tauri application"); + } + ``` +
  4. +
+
+
+ +
+ +## 用法 + +外掛已经安装并初始化,应该可以立即正常运行。尽管如此,我们也可以使用 `init()` 方法来增强它的功能。 + +外掛的 `init()` 方法接受一个闭包,该闭包在新 App 实例启动时调用,但由外掛关闭。 +这个闭包有三个参数: + +1. **`app`**:应用程序的 [AppHandle](https://docs.rs/tauri/latest/tauri/struct.AppHandle.html) 。 +2. **`args`**:用户初始化新实例时传递的参数列表。 +3. **`cwd`**:当前工作目录表示启动新应用程序实例的目录。 + +因此,闭包应该如下所示 + +```rust +.plugin(tauri_plugin_single_instance::init(|app, args, cwd| { + // 在这里写代码 …… +})) +``` + +### 关注新实例 + +默认情况下,当应用程序已经在运行时启动新实例时,不会采取任何操作。当用户尝试打开一个新实例时,为了聚焦正在运行实例的窗口,修改回调闭包如下。 + +```rust title="src-tauri/src/lib.rs" {1} {5-7} {12-21} +use tauri::{AppHandle, Manager}; + +pub fn run() { + tauri::Builder::default() + .plugin(tauri_plugin_single_instance::init(|app, args, cwd| { + let _ = show_window(app); + })) + .run(tauri::generate_context!()) + .expect("error while running tauri application"); +} + +fn show_window(app: &AppHandle) { + let windows = app.webview_windows(); + + windows + .values() + .next() + .expect("Sorry, no window found") + .set_focus() + .expect("Can't Bring Window to Focus"); +} +``` diff --git a/src/content/docs/zh-tw/plugin/sql.mdx b/src/content/docs/zh-tw/plugin/sql.mdx new file mode 100644 index 0000000000..c5c0acc830 --- /dev/null +++ b/src/content/docs/zh-tw/plugin/sql.mdx @@ -0,0 +1,228 @@ +--- +title: SQL +description: 外掛提供了一个接口,让前端可以通过 sqlx 与 SQL 数据库进行通信 +plugin: sql +--- + +import PluginLinks from '@components/PluginLinks.astro'; +import Compatibility from '@components/plugins/Compatibility.astro'; + +import { Tabs, TabItem } from '@astrojs/starlight/components'; +import CommandTabs from '@components/CommandTabs.astro'; + + + +这个外掛提供了一个接口,让前端可以通过 [sqlx](https://github.com/launchbadge/sqlx) 与 SQL 数据库进行通信。 +它支持 SQLite、MySQL 和 PostgreSQL 驱动程序,通过 Cargo 特性来启用。 + +## Supported Platforms + + + +## 安装 + +首先,在你的 `Cargo.toml` 文件中新增以下内容来安装外掛。 + + + +```toml title="src-tauri/Cargo.toml" +[dependencies.tauri-plugin-sql] +features = ["sqlite"] # or "postgres", or "mysql" +version = "2.0.0" +``` + + + +```toml title="src-tauri/Cargo.toml" +[dependencies.tauri-plugin-sql] +features = ["sqlite"] # or "postgres", or "mysql" +git = "https://github.com/tauri-apps/plugins-workspace" +branch = "v2" +``` + + + + +然后,你必须使用你喜欢的 JavaScript 包管理器新增 JavaScript Guest 绑定。 + + + + + + + + + + +## 用法 + +首先,你需要在 Tauri 中注册外掛: + +```rust title="src-tauri/src/main.rs" ins={3} +fn main() { + tauri::Builder::default() + .plugin(tauri_plugin_sql::Builder::default().build()) + .run(tauri::generate_context!()) + .expect("error while running tauri application"); +} +``` + +之后,所有外掛的 API 都可以通过 JavaScript Guest 绑定使用。 + + + + +这个路径是相对于 `tauri::api::path::BaseDirectory::App` 的。 + +```javascript +import Database from '@tauri-apps/plugin-sql'; +const db = await Database.load('sqlite:test.db'); +await db.execute('INSERT INTO ...'); +``` + + + +```javascript + +import Database from '@tauri-apps/plugin-sql'; +const db = await Database.load('mysql://user:pass@host/database'); +await db.execute('INSERT INTO ...'); + +```` + + +```javascript + +import Database from "@tauri-apps/plugin-sql"; +const db = await Database.load("postgres://postgres:password@localhost/test"); +await db.execute("INSERT INTO ..."); + +```` + + + + +## 语法 + +我们使用 [sqlx](https://docs.rs/sqlx/latest/sqlx/) 作为底层库并采用它们的查询语法。 + + + +在替换查询数据时使用 "$#" 语法 +```javascript +const result = await db.execute( + "INSERT into todos (id, title, status) VALUES ($1, $2, $3)", + [todos.id, todos.title, todos.status], +); + +const result = await db.execute( +"UPDATE todos SET title = $1, status = $2 WHERE id = $3", +[todos.title, todos.status, todos.id], +); + +```` + + +在替换查询数据时使用 "?" 语法 +```javascript +const result = await db.execute( + "INSERT into todos (id, title, status) VALUES (?, ?, ?)", + [todos.id, todos.title, todos.status], +); + +const result = await db.execute( + "UPDATE todos SET title = ?, status = ? WHERE id = ?", + [todos.title, todos.status, todos.id], +); +```` + + + +在替换查询数据时使用 "$#" 语法 +```javascript +const result = await db.execute( + "INSERT into todos (id, title, status) VALUES ($1, $2, $3)", + [todos.id, todos.title, todos.status], +); + +const result = await db.execute( +"UPDATE todos SET title = $1, status = $2 WHERE id = $3", +[todos.title, todos.status, todos.id], +); + +```` + + + +## 迁移 + +这个外掛支持数据库迁移,允许你管理数据库模式随时间的变化。 + +### 定义迁移 + +迁移在 Rust 中使用 [`Migration`](https://docs.rs/tauri-plugin-sql/latest/tauri_plugin_sql/struct.Migration.html) 结构体定义。 +每个迁移都应该包含唯一的版本号、描述、要执行的 SQL 和迁移类型(向上或向下)。 + +迁移的例子: + +```rust +use tauri_plugin_sql::{Migration, MigrationKind}; + +let migration = Migration { + version: 1, + description: "create_initial_tables", + sql: "CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT);", + kind: MigrationKind::Up, +}; +```` + +### 向外掛构建器新增迁移 + +迁移用外掛提供的 [`Builder`](https://docs.rs/tauri-plugin-sql/latest/tauri_plugin_sql/struct.Builder.html) 结构体注册。 +使用 `add_migrations` 方法将迁移新增到特定数据库连接的外掛中。 + +新增迁移的例子: + +```rust title="src-tauri/src/main.rs" {1} {6-11} {17} +use tauri_plugin_sql::{Builder, Migration, MigrationKind}; + +fn main() { + let migrations = vec![ + // Define your migrations here + Migration { + version: 1, + description: "create_initial_tables", + sql: "CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT);", + kind: MigrationKind::Up, + } + ]; + + tauri::Builder::default() + .plugin( + tauri_plugin_sql::Builder::default() + .add_migrations("sqlite:mydatabase.db", migrations) + .build(), + ) + ... +} +``` + +### 应用迁移 + +迁移在外掛初始化时自动应用。外掛针对连接字符串指定的数据库运行这些迁移。确保迁移按照正确的顺序定义,并且是幂等的(可以安全运行多次)。 + +### 迁移管理 + +- **版本控制**:每个迁移必须有一个唯一的版本号。这对于确保迁移按正确的顺序应用至关重要。 +- **幂等性**:编写迁移时,要确保它们能够安全重新运行,而不会导致错误或意外后果。 +- **测试**:彻底测试迁移,确保它们按预期工作,并且不会损害数据库的完整性。 diff --git a/src/content/docs/zh-tw/plugin/store.mdx b/src/content/docs/zh-tw/plugin/store.mdx new file mode 100644 index 0000000000..523af2bd6f --- /dev/null +++ b/src/content/docs/zh-tw/plugin/store.mdx @@ -0,0 +1,184 @@ +--- +title: Store +description: 持久键值存储。 +plugin: store +--- + +import PluginLinks from '@components/PluginLinks.astro'; +import Compatibility from '@components/plugins/Compatibility.astro'; + +import { Tabs, TabItem } from '@astrojs/starlight/components'; +import CommandTabs from '@components/CommandTabs.astro'; + + + +简单、持久的键值存储。 + +## 支持的平台 + + + +## 设置 + +请安装 store 外掛。 + + + + + 使用项目的包管理器来新增依赖。 + + + + + + + 1. 在你的 `Cargo.toml` 文件中新增以下内容来安装 store 外掛。 + + ```toml title="src-tauri/Cargo.toml" + [dependencies] + tauri-plugin-store = "2.0.0" + # 或者使用 GIT: + tauri-plugin-store = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" } + ``` + + 2. 修改 `lib.rs` 来初始化外掛。 + + ```rust title="src-tauri/src/lib.rs" ins={4} + #[cfg_attr(mobile, tauri::mobile_entry_point)] + fn run() { + tauri::Builder::default() + .plugin(tauri_plugin_store::Builder::new().build()) + .run(tauri::generate_context!()) + .expect("error while running tauri application"); + } + ``` + + 3. 使用你喜欢的 JavaScript 包管理器安装 JavaScript Guest 绑定。 + + + + + + + +## 用法 + + + + +```javascript +import { Store } from '@tauri-apps/plugin-store'; + +// Store 会在 JavaScript 绑定时自动加载。 +const store = new Store('store.bin'); + +// 设置一个值。 +await store.set('some-key', { value: 5 }); + +// 获取一个值。 +const val = await store.get('some-key'); +console.log(val); // { value: 5 } + +// 您可以在进行更改后手动保存存储 +// 否则如上所述,它将在正常退出时保存。 +await store.save(); +``` + + + + +```rust title="src-tauri/src/lib.rs" +use tauri::Wry; +use tauri_plugin_store::{with_store, StoreCollection}; +use serde_json::json; + +#[cfg_attr(mobile, tauri::mobile_entry_point)] +pub fn run() { + tauri::Builder::default() + .plugin(tauri_plugin_store::Builder::default().build()) + .setup(|app| { + let stores = app.app_handle().state::>(); + let path = PathBuf::from("store.bin"); + + with_store(app.app_handle().clone(), stores, path, |store| { + // 注意,值必须是 serde_json::Value 的实例, + // 否则,它们将与 JavaScript 绑定不兼容。 + store.insert("some-key".to_string(), json!({ "value": 5 }))?; + + // 从 Store 中获取一个值。 + let value = store.get("some-key").expect("Failed to get value from store"); + println!("{}", value); // {"value":5} + + // 您可以在进行更改后手动保存存储 + // 否则如上所述,它将在正常退出时保存。 + store.save()?; + + Ok(()) + }); + + Ok(()) + }) + .run(tauri::generate_context!()) + .expect("error while running tauri application"); +} +``` + + + + +## 权限 + +默认情况下,所有外掛命令都被阻止,无法访问。你必须在你的 `capabilities` 配置中定义一个权限列表。 + +更多資訊请参见[访问控制列表](/zh-tw/reference/acl/)。 + +```json title="src-tauri/capabilities/default.json" ins={6-11} +{ + "$schema": "../gen/schemas/desktop-schema.json", + "identifier": "main-capability", + "description": "Capability for the main window", + "windows": ["main"], + "permissions": [ + "store:allow-get", + "store:allow-set", + "store:allow-save", + "store:allow-load" + ] +} +``` + +| 权限 | 描述 | +| --------------------- | ------------------------------------------------- | +| `store:allow-clear` | 在没有预先配置有效範圍的情况下,启用 clear 命令。 | +| `store:deny-clear` | 拒绝没有任何预配置范围的 clear 命令。 | +| `store:allow-delete` | 在没有预先配置有效範圍的情况下,启用 | +| `store:deny-delete` | 拒绝没有任何预配置范围的 delete 命令。 | +| `store:allow-entries` | 在没有预先配置有效範圍的情况下,启用 entries 命令。 | +| `store:deny-entries` | 拒绝没有任何预配置范围的 entries 命令。 | +| `store:allow-get` | 在没有预先配置有效範圍的情况下,启用 get 命令。 | +| `store:deny-get` | 拒绝没有任何预配置范围的 get 命令。 | +| `store:allow-has` | 在没有预先配置有效範圍的情况下,启用 has 命令。 | +| `store:deny-has` | 拒绝没有任何预配置范围的 has 命令。 | +| `store:allow-keys` | 在没有预先配置有效範圍的情况下,启用 keys 命令。 | +| `store:deny-keys` | 拒绝没有任何预配置范围的 keys 命令。 | +| `store:allow-length` | 在没有预先配置有效範圍的情况下,启用 length 命令。 | +| `store:deny-length` | 拒绝没有任何预配置范围的 length 命令。 | +| `store:allow-load` | 在没有预先配置有效範圍的情况下,启用 load 命令。 | +| `store:deny-load` | 拒绝没有任何预配置范围的 load 命令。 | +| `store:allow-reset` | 在没有预先配置有效範圍的情况下,启用 reset 命令。 | +| `store:deny-reset` | 拒绝没有任何预配置范围的 reset 命令。 | +| `store:allow-save` | 在没有预先配置有效範圍的情况下,启用 save 命令。 | +| `store:deny-save` | 拒绝没有任何预配置范围的 save 命令。 | +| `store:allow-set` | 在没有预先配置有效範圍的情况下,启用 set 命令。 | +| `store:deny-set` | 拒绝没有任何预配置范围的 set 命令。 | +| `store:allow-values` | 在没有预先配置有效範圍的情况下,启用 values 命令。 | +| `store:deny-values` | 拒绝没有任何预配置范围的 values 命令。 | diff --git a/src/content/docs/zh-tw/plugin/stronghold.mdx b/src/content/docs/zh-tw/plugin/stronghold.mdx new file mode 100644 index 0000000000..110a2f7253 --- /dev/null +++ b/src/content/docs/zh-tw/plugin/stronghold.mdx @@ -0,0 +1,238 @@ +--- +title: Stronghold +description: 加密的、安全的数据库。 +plugin: stronghold +--- + +import PluginLinks from '@components/PluginLinks.astro'; +import Compatibility from '@components/plugins/Compatibility.astro'; + +import { Steps, Tabs, TabItem } from '@astrojs/starlight/components'; +import CommandTabs from '@components/CommandTabs.astro'; + + + +使用 [IOTA Stronghold](https://github.com/iotaledger/stronghold.rs) 加密数据库和安全运行时存储秘密和密钥。 + +## 支持的平台 + + + +## 设置 + +安装 stronghold 外掛开始。 + + + + 使用项目的包管理器来新增依赖。 + + { ' ' } + + + + + + + + 1. 在你的 `Cargo.toml` 文件中新增以下内容来安装 stronghold 外掛。 + + ```toml title="src-tauri/Cargo.toml" + [dependencies] + tauri-plugin-stronghold = "2.0.0" + # 或者使用 Git: + tauri-plugin-stronghold = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" } + ``` + + 2. 修改 `lib.rs` 来初始化外掛。 + + ```rust title="src-tauri/src/lib.rs" ins={3} + fn run() { + tauri::Builder::default() + .plugin(tauri_plugin_stronghold::Builder::new(|password| {}).build()) + .run(tauri::generate_context!()) + .expect("error while running tauri application"); + } + ``` + + 3. 使用你喜欢的 JavaScript 包管理器安装 JavaScript Guest 绑定。 + + + + + + + + +## 用法 + +### 使用自定义密码散列函数初始化 + +```rust title="src-tauri/src/lib.rs" +pub fn run() { + tauri::Builder::default() + .plugin( + tauri_plugin_stronghold::Builder::new(|password| { + // 在这里使用 argon2、blake2b 或任何其他安全算法对密码进行散列。 + // 下面是一个使用 `rust-argon2` 板条箱对密码进行散列的示例实现: + use argon2::{hash_raw, Config, Variant, Version}; + + let config = Config { + lanes: 4, + mem_cost: 10_000, + time_cost: 10, + variant: Variant::Argon2id, + version: Version::Version13, + ..Default::default() + }; + let salt = "your-salt".as_bytes(); + let key = + hash_raw(password.as_ref(), salt, &config).expect("failed to hash password"); + + key.to_vec() + }) + .build(), + ) + .run(tauri::generate_context!()) + .expect("error while running tauri application"); +} +``` + +### 使用 argon2 密码散列函数初始化 + +```rust title="src-tauri/src/lib.rs" +use tauri::Manager; + +pub fn run() { + tauri::Builder::default() + .setup(|app| { + let salt_path = app + .path() + .app_local_data_dir() + .expect("could not resolve app local data path") + .join("salt.txt"); + app.handle().plugin(tauri_plugin_stronghold::Builder::with_argon2(&salt_path).build())?; + Ok(()) + }) + .run(tauri::generate_context!()) + .expect("error while running tauri application"); +} +``` + +### 在 JavaScript 使用 + +Stronghold 外掛可以在 JavaScript 中使用。 + +```javascript +import { Client, Stronghold } from '@tauri-apps/plugin-stronghold'; +import { appDataDir } from '@tauri-apps/api/path'; + +const initStronghold = async () => { + const vaultPath = `${await appDataDir()}/vault.hold`; + const vaultPassword = 'vault password'; + const stronghold = await Stronghold.load(vaultPath, vaultPassword); + + let client: Client; + const clientName = 'name your client'; + try { + client = await stronghold.loadClient(clientName); + } catch { + client = await stronghold.createClient(clientName); + } + + return { + stronghold, + client, + }; +}; + +// 向 store 中插入一条记录 +async function insertRecord(store: any, key: string, value: string) { + const data = Array.from(new TextEncoder().encode(value)); + await store.insert(key, data); +} + +// 从 store 中读取一条记录 +async function getRecord(store: any, key: string): Promise { + const data = await store.get(key); + return new TextDecoder().decode(new Uint8Array(data)); +} + +const { stronghold, client } = await initStronghold(); + +const store = client.getStore(); +const key = 'my_key'; + +// 向 store 中插入一条记录 +insertRecord(store, key, 'secret value'); + +// 从 store 中读取一条记录 +const value = await getRecord(store, key); +console.log(value); // 'secret value' + +// 保存更新 +await stronghold.save(); + +// 从 store 中删除一条记录 +await store.remove(key); +``` + +## 权限 + +默认情况下,所有外掛命令都被阻止,无法访问。你必须在你的 `capabilities` 配置中定义一个权限列表。 + +更多資訊请参见[访问控制列表](/zh-tw/reference/acl/)。 + +```json title="src-tauri/capabilities/default.json" ins={8-14} +{ + "$schema": "../gen/schemas/desktop-schema.json", + "identifier": "main-capability", + "description": "Capability for the main window", + "windows": ["main"], + "permissions": [ + "path:default", + "stronghold:allow-initialize", + "stronghold:allow-create-client", + "stronghold:allow-load-client", + "stronghold:allow-save", + "stronghold:allow-save-store-record" + "stronghold:allow-get-store-record", + "stronghold:allow-remove-store-record", + ] +} +``` + +| 权限 | 描述 | +| -------------------------------------- | ------------------------------------------------------------- | +| `stronghold:allow-create-client` | 在没有预先配置的有效範圍的情况下启用 create_client 命令。 | +| `stronghold:deny-create-client` | 拒绝没有任何预配置范围的 create_client 命令。 | +| `stronghold:allow-destroy` | 在没有预先配置的有效範圍的情况下启用 destroy 命令。 | +| `stronghold:deny-destroy` | 拒绝没有任何预配置范围的 destroy 命令。 | +| `stronghold:allow-execute-procedure` | 在没有预先配置的有效範圍的情况下启用 execute_procedure 命令。 | +| `stronghold:deny-execute-procedure` | 拒绝没有任何预配置范围的 execute_procedure 命令。 | +| `stronghold:allow-get-store-record` | 在没有预先配置的有效範圍的情况下启用 get_store_record 命令。 | +| `stronghold:deny-get-store-record` | 拒绝没有任何预配置范围的 get_store_record 命令。 | +| `stronghold:allow-initialize` | 在没有预先配置的有效範圍的情况下启用 initialize 命令。 | +| `stronghold:deny-initialize` | 拒绝没有任何预配置范围的 initialize 命令。 | +| `stronghold:allow-load-client` | 在没有预先配置的有效範圍的情况下启用 load_client 命令。 | +| `stronghold:deny-load-client` | 拒绝没有任何预配置范围的 load_client 命令。 | +| `stronghold:allow-remove-secret` | 在没有预先配置的有效範圍的情况下启用 remove_secret 命令。 | +| `stronghold:deny-remove-secret` | 拒绝没有任何预配置范围的 remove_secret 命令。 | +| `stronghold:allow-remove-store-record` | 在没有预先配置的有效範圍的情况下启用 remove_store_record 命令。 | +| `stronghold:deny-remove-store-record` | 拒绝没有任何预配置范围的 remove_store_record 命令。 | +| `stronghold:allow-save` | 在没有预先配置的有效範圍的情况下启用 save 命令。 | +| `stronghold:deny-save` | 拒绝没有任何预配置范围的 save 命令。 | +| `stronghold:allow-save-secret` | 在没有预先配置的有效範圍的情况下启用 save_secret 命令。 | +| `stronghold:deny-save-secret` | 拒绝没有任何预配置范围的 save_secret 命令。 | +| `stronghold:allow-save-store-record` | 在没有预先配置的有效範圍的情况下启用 save_store_record 命令。 | +| `stronghold:deny-save-store-record` | 拒绝没有任何预配置范围的 save_store_record 命令。 | diff --git a/src/content/docs/zh-tw/plugin/updater.mdx b/src/content/docs/zh-tw/plugin/updater.mdx new file mode 100644 index 0000000000..543890a481 --- /dev/null +++ b/src/content/docs/zh-tw/plugin/updater.mdx @@ -0,0 +1,768 @@ +--- +title: 更新 +description: Tauri 应用程序的应用内更新。 +plugin: updater +--- + +import PluginLinks from '@components/PluginLinks.astro'; +import Compatibility from '@components/plugins/Compatibility.astro'; + +import PluginPermissions from '@components/PluginPermissions.astro'; +import CommandTabs from '@components/CommandTabs.astro'; +import { TabItem, Steps, Tabs } from '@astrojs/starlight/components'; + + + +自动使用更新服务器或静态 JSON 更新你的 Tauri 应用程序。 + +## Supported Platforms + + + +## Setup + +从安装 Tauri 更新外掛开始。 + + + + + 使用项目的包管理器新增依赖项。 + + + + + + + + 1. 在 `src-tauri` 文件夹中运行以下命令,将外掛新增到 `Cargo.toml` 中的项目依赖项中。 + + + ```sh frame=none + cargo add tauri-plugin-updater --target 'cfg(any(target_os = "macos", windows, target_os = "linux"))' + ``` + + 2. 修改 `lib.rs` 来初始化外掛。 + + ```rust title="lib.rs" ins={5-6} + #[cfg_attr(mobile, tauri::mobile_entry_point)] + pub fn run() { + tauri::Builder::default() + .setup(|app| { + #[cfg(desktop)] + app.handle().plugin(tauri_plugin_updater::Builder::new().build()); + Ok(()) + }) + .run(tauri::generate_context!()) + .expect("error while running tauri application"); + } + ``` + + 3. 使用你喜欢的 JavaScript 包管理器安装 JavaScript Guest 绑定。 + + + + + + + + +## 签名更新包 + +Tauri 的更新程序需要签名来验证更新来自可信来源。这不能被禁用。 + +要对更新进行签名,你需要两个密钥: + +1. 公钥将在 `tauri.conf.json` 中设置,以便在安装前验证升级包。只要您的私钥是安全的,此公钥就可以安全地上传和共享。 +2. 私钥,用于为安装程序文件签名。你不应该与任何人共享这把钥匙。此外,如果你丢失了这个密钥,你将无法向已经安装应用程序的用户发布新的更新。把这个密钥放在安全的地方很重要! + +为了生成密钥,Tauri CLI 提供了 `signer generate` 命令。你可以运行以下命令在主文件夹中创建密钥。 + + + + + +### 构建 + +在构建您的更新包时,您需要在环境变量中配置上述生成的私钥。`.env` 文件*不起*作用! + + + + ```sh frame=none + export TAURI_SIGNING_PRIVATE_KEY="Path or content of your private key" + # optionally also add a password + export TAURI_SIGNING_PRIVATE_KEY_PASSWORD="" + ``` + + + 在 `PowerShell` 中运行。 + ```ps frame=none + $env:TAURI_SIGNING_PRIVATE_KEY="Path or content of your private key" + <# optionally also add a password #> + $env:TAURI_SIGNING_PRIVATE_KEY_PASSWORD="" + ``` + + + +之后,您可以像往常一样运行 Tauri build,Tauri 将生成更新包及其签名。 +生成的文件依赖于下面配置的 [`createUpdaterArtifacts`] 配置值。 + + + + +```json +{ + "bundle": { + "createUpdaterArtifacts": true + } +} +``` + +在 Linux 上,Tauri 将在 `target/release/bundle/appimage/` 文件夹中创建 AppImage。 + +- `myapp.AppImage` - 标准的应用程序包。它将被更新者重新使用。 +- `myapp.AppImage.sig` - 更新包的签名。 + +在 macOS 系统上,Tauri 会从 `target/release/bundle/macos/` 文件夹内的应用程序包创建一个 .tar.gz 归档文件。 + +- `myapp.app` - 标准的应用程序包。 +- `myapp.app.tar.gz` - 更新包。 +- `myapp.app.tar.gz.sig` - 更新包的签名。 + +在 Windows 系统上,Tauri 会在 `target/release/bundle/msi/` and `target/release/bundle/nsis` 文件夹内创建常规的 MSI 和 NSIS 安装程序。 + +- `myapp-setup.exe` - 标准的应用程序包。它将被更新者重新使用。 +- `myapp-setup.exe.sig` - 更新包的签名。 +- `myapp.msi` - 标准的应用程序包。它将被更新者重新使用。 +- `myapp.msi.sig` - 更新包的签名。 + +{''} + + + + +```json +{ + "bundle": { + "createUpdaterArtifacts": "v1Compatible" + } +} +``` + +在 Linux 上,Tauri 将在 `target/release/bundle/appimage/` 文件夹中创建 AppImage。 + +- `myapp.AppImage` - 标准的应用包。 +- `myapp.AppImage.tar.gz` - 更新包。 +- `myapp.AppImage.tar.gz.sig` - 更新包的签名。 + +在 macOS 系统上,Tauri 会从 `target/release/bundle/macos/` 文件夹内的应用程序包创建一个 .tar.gz 归档文件。 + +- `myapp.app` - 标准的应用包。 +- `myapp.app.tar.gz` - 更新包。 +- `myapp.app.tar.gz.sig` - 更新包的签名。 + +在 Windows 系统上,Tauri 会从 `target/release/bundle/msi/` 和 `target/release/bundle/nsis` 文件夹内的 MSI 和 NSIS 安装程序创建 .zip 归档文件。 + +- `myapp-setup.exe` - 标准的应用包。 +- `myapp-setup.nsis.zip` - 更新包。 +- `myapp-setup.nsis.zip.sig` - 更新包的签名。 +- `myapp.msi` - 标准的应用包。 +- `myapp.msi.zip` - 更新包。 +- `myapp.msi.zip.sig` - 更新包的签名。 + +{''} + + + + +## Tauri 配置 + +以这种格式设置 `tauri.conf.json`,以使更新程序开始工作。 + +| Keys | Description | +| ------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `createUpdaterArtifacts` | 将其设置为 `true` 告诉 Tauri 的应用打包器创建更新包。如果你要从较旧的 Tauri 版本迁移应用程序,请将其设置为 `"v1Compatible"`。**此设置将在 v3 中删除**,所以一旦所有用户迁移到 v2,请确保将其更改为 `true`。 | +| `pubkey` | 这必须是上面步骤中从 Tauri CLI 生成的公钥。它**不能**是文件路径! | +| `endpoints` | 这必须是一个字符串形式的 url 数组。TLS 在生产模式下强制执行。只有返回非 2xx 状态码时,Tauri 才会继续访问下一个 url! | +| `dangerousInsecureTransportProtocol` | 将其设置为 `true` 允许更新器接受非 https 端点。请谨慎使用此配置! | + +每个更新的 URL 可以包含以下动态变量,允许您在服务器端确定更新是否可用。 + +- `{{current_version}}`:请求更新的应用程序版本。 +- `{{target}}`:操作系统名称 (`linux`、`windows` 或 `darwin` 之一)。 +- `{{arch}}`:机器的架构 (`x86_64`、`i686`、`aarch64` 或 `armv7` 之一)。 + +```json title=tauri.conf.json +{ + "bundle": { + "createUpdaterArtifacts": true + }, + "plugins": { + "updater": { + "pubkey": "CONTENT FROM PUBLICKEY.PEM", + "endpoints": [ + "https://releases.myapp.com/{{target}}/{{arch}}/{{current_version}}", + // or a static github json file + "https://github.com/user/repo/releases/latest/download/latest.json" + ] + } + } +} +``` + +:::tip +不支持自定义变量,但可以定义[自定义 `{{target}}`](#自定义目标)。 +::: + +### `installMode` on Windows + +在 Windows 平台上,有一个额外的可选的 `"installMode"` 配置来更改更新包的安装方式。 + +```json title=tauri.conf.json +{ + "plugins": { + "updater": { + "windows": { + "installMode": "passive" + } + } + } +} +``` + +- `"passive"`:会有一个带有进度条的小窗口。该更新将在不需要任何用户交互的情况下安装。一般推荐使用默认模式。 +- `"basicUi"`:将显示一个基本的用户界面,它需要用户交互来完成安装。 +- `"quiet"`:没有进度反馈给用户。在这种模式下,安装程序不能自行请求管理员权限,所以它只适用于用户范围内的安装,或者当您的应用程序本身已经以管理员权限运行时。一般不推荐。 + +## 服务器的支持 + +更新外掛可以以两种方式使用。要么使用动态更新服务器,要么使用静态 JSON 文件(用于 S3 或 GitHub gist 等服务)。 + +### 静态 JSON 文件 + +使用静态文件时,只需要返回一个包含所需資訊的 JSON。 + +| Keys | Description | +| ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `version` | 必须是一个有效的 [SemVer](https://semver.org/),带或不带 `v`,这意味着 `1.0.0` 和 `v1.0.0` 都是有效的。 | +| `notes` | 更新说明。 | +| `pub_date` | 如果存在日期,则必须按照 [RFC 3339](https://datatracker.ietf.org/doc/html/rfc3339) 规范格式化。 | +| `platforms` | 每个平台的字段名都是 `OS-ARCH` 格式,其中 `OS` 是 `linux`、`darwin` 或 `windows` 中的一个,而 `ARCH` 是 `x86_64`、`aarch64`、`i686` 或 `armv7` 中的一个。 | +| `signature` | 生成的 `.sig` 文件的内容,可能会随着每次构建而改变。路径或 URL 将不起作用! | + +:::info +当使用[自定义目标](#自定义目标)时,所提供的目标字符串会与 `platforms` 键进行匹配,而非默认的 `OS-ARCH` 值。 +::: + +`"version"`、`"platforms.[target].url"` 和 `"platforms.[target].signature"` 是必需的;其它字段是可选的。 + +```json +{ + "version": "", + "notes": "", + "pub_date": "", + "platforms": { + "linux-x86_64": { + "signature": "", + "url": "" + }, + "windows-x86_64": { + "signature": "", + "url": "" + }, + "darwin-x86_64": { + "signature": "", + "url": "" + } + } +} +``` + +注意,Tauri 将在检查 version 字段之前验证整个文件,因此请确保所有现有平台配置都是有效和完整的。 + +:::tip +[Tauri Action](https://github.com/tauri-apps/tauri-action) 会生成一个静态的 JSON 文件供你在 cdn 上使用,比如 GitHub 发行版。 +::: + +### 动态更新服务器 + +在使用动态更新服务器时,Tauri 会遵循服务器的指令。若要禁用内部版本检查,您可以覆盖 [Tauri 的版本比较](https://docs.rs/tauri/latest/tauri/updater/struct.UpdateBuilder.html#method.should_install),这样就会安装服务器发送的版本(如果您需要回滚应用程序,这很有用)。 + +您的服务器可以使用上述 `endpoint` URL 中定义的变量来确定是否需要更新。如果您需要更多数据,可以根据自己的喜好在 Rust 中新增额外的[请求头](https://docs.rs/tauri/latest/tauri/updater/struct.UpdateBuilder.html#method.header)。 + +如果没有可用的更新,您的服务器应响应状态码为 [`204 无内容`](https://datatracker.ietf.org/doc/html/rfc2616#section-10.2.5)。 + +如果需要更新,您的服务器应使用状态码 [`200 OK`](http://tools.ietf.org/html/rfc2616#section-10.2.1) 进行响应,并以这种格式提供 JSON 响应。 + +| Keys | Description | +| ----------- | ------------------------------------------------------------------------------------------------------- | +| `version` | 必须是一个有效的 [SemVer](https://semver.org/),带或不带 `v`,这意味着 `1.0.0` 和 `v1.0.0` 都是有效的。 | +| `notes` | 更新说明。 | +| `pub_date` | 如果存在日期,则必须按照 [RFC 3339](https://datatracker.ietf.org/doc/html/rfc3339) 规范格式化。 | +| `url` | 这必须是的有效更新包 URL。 | +| `signature` | 生成的 `.sig` 文件的内容,可能会随着每次构建而改变。路径或 URL 将不起作用! | + +`"url"`、`"version"` and `"signature"` 是必须的;其它字段是可选的。 + +```json +{ + "version": "", + "pub_date": "", + "url": "", + "signature": "", + "notes": "" +} +``` + +:::tip +金牛座的官方合作伙伴 CrabNebula 提供了一个动态更新服务器。有关更多資訊,请参阅 [Distributing with CrabNebula Cloud] 文档。 +::: + +## 检查更新 + +用于检查和安装更新的默认 API 利用配置的端点,可以由 JavaScript 和 Rust 代码访问。 + + + + +```js +import { check } from '@tauri-apps/plugin-updater'; +import { relaunch } from '@tauri-apps/plugin-process'; + +const update = await check(); +if (update) { + console.log( + `found update ${update.version} from ${update.date} with notes ${update.body}` + ); + let downloaded = 0; + let contentLength = 0; + // alternatively we could also call update.download() and update.install() separately + await update.downloadAndInstall((event) => { + switch (event.event) { + case 'Started': + contentLength = event.data.contentLength; + console.log(`started downloading ${event.data.contentLength} bytes`); + break; + case 'Progress': + downloaded += event.data.chunkLength; + console.log(`downloaded ${downloaded} from ${contentLength}`); + break; + case 'Finished': + console.log('download finished'); + break; + } + }); + + console.log('update installed'); + await relaunch(); +} +``` + +更多有关資訊,请参阅 [JavaScript API 文档]。 + + + + + +```rust title="src-tauri/src/lib.rs" +use tauri_plugin_updater::UpdaterExt; + +pub fn run() { + tauri::Builder::default() + .setup(|app| { + let handle = app.handle().clone(); + tauri::async_runtime::spawn(async move { + update(handle).await.unwrap(); + }); + Ok(()) + }) + .run(tauri::generate_context!()) + .unwrap(); +} + +async fn update(app: tauri::AppHandle) -> tauri_plugin_updater::Result<()> { + if let Some(update) = app.updater()?.check().await? { + let mut downloaded = 0; + + // alternatively we could also call update.download() and update.install() separately + update + .download_and_install( + |chunk_length, content_length| { + downloaded += chunk_length; + println!("downloaded {downloaded} from {content_length:?}"); + }, + || { + println!("download finished"); + }, + ) + .await?; + + println!("update installed"); + app.restart(); + } + + Ok(()) +} +``` + +:::tip +要通知前端下载进度,请考虑使用带 [channel] 的命令。 + +
+ Updater command + +```rust +#[cfg(desktop)] +mod app_updates { + use std::sync::Mutex; + use serde::Serialize; + use tauri::{ipc::Channel, AppHandle, State}; + use tauri_plugin_updater::{Update, UpdaterExt}; + + #[derive(Debug, thiserror::Error)] + pub enum Error { + #[error(transparent)] + Updater(#[from] tauri_plugin_updater::Error), + #[error("there is no pending update")] + NoPendingUpdate, + } + + impl Serialize for Error { + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.to_string().as_str()) + } + } + + type Result = std::result::Result; + + #[derive(Clone, Serialize)] + #[serde(tag = "event", content = "data")] + pub enum DownloadEvent { + #[serde(rename_all = "camelCase")] + Started { + content_length: Option, + }, + #[serde(rename_all = "camelCase")] + Progress { + chunk_length: usize, + }, + Finished, + } + + #[derive(Serialize)] + #[serde(rename_all = "camelCase")] + pub struct UpdateMetadata { + version: String, + current_version: String, + } + + #[tauri::command] + pub async fn fetch_update( + app: AppHandle, + pending_update: State<'_, PendingUpdate>, + ) -> Result> { + let channel = "stable"; + let url = url::Url::parse(&format!( + "https://cdn.myupdater.com/{{{{target}}}}-{{{{arch}}}}/{{{{current_version}}}}?channel={channel}", + )).expect("invalid URL"); + + let update = app + .updater_builder() + .endpoints(vec![url])? + .build()? + .check() + .await?; + + let update_metadata = update.as_ref().map(|update| UpdateMetadata { + version: update.version.clone(), + current_version: update.current_version.clone(), + }); + + *pending_update.0.lock().unwrap() = update; + + Ok(update_metadata) + } + + #[tauri::command] + pub async fn install_update(pending_update: State<'_, PendingUpdate>, on_event: Channel) -> Result<()> { + let Some(update) = pending_update.0.lock().unwrap().take() else { + return Err(Error::NoPendingUpdate); + }; + + let started = false; + + update + .download_and_install( + |chunk_length, content_length| { + if !started { + let _ = on_event.send(DownloadEvent::Started { content_length }); + started = true; + } + + let _ = on_event.send(DownloadEvent::Progress { chunk_length }); + }, + || { + let _ = on_event.send(DownloadEvent::Finished); + }, + ) + .await?; + + Ok(()) + } + + struct PendingUpdate(Mutex>); +} + +#[cfg_attr(mobile, tauri::mobile_entry_point)] +pub fn run() { + tauri::Builder::default() + .plugin(tauri_plugin_process::init()) + .setup(|app| { + #[cfg(desktop)] + { + app.handle().plugin(tauri_plugin_updater::Builder::new().build()); + app.manage(app_updates::PendingUpdate(Mutex::new(None))); + } + Ok(()) + }) + .invoke_handler(tauri::generate_handler![ + #[cfg(desktop)] + app_updates::fetch_update, + #[cfg(desktop)] + app_updates::install_update + ]) +} +``` + +
+::: + +更多有关資訊,请参阅 [Rust API 文档]。 + +
+
+ +请注意,安装更新后不需要立即重启应用程序,你可以选择如何处理更新,要么等待用户手动重启应用程序,要么提示他选择何时这样做。 + +:::note +在 Windows 上,由于 Windows 安装程序的限制,应用程序在执行安装步骤时将自动退出。 +::: + +当检查和下载更新时,可以定义自定义的请求超时、代理和请求头。 + + + + +```js +import { check } from '@tauri-apps/plugin-updater'; + +const update = await check({ + proxy: '', + timeout: 30000 /* milliseconds */, + headers: { + Authorization: 'Bearer ', + }, +}); +``` + + + + + +```rust +use tauri_plugin_updater::UpdaterExt; +let update = app + .updater_builder() + .timeout(std::time::Duration::from_secs(30)) + .proxy("".parse().expect("invalid URL")) + .header("Authorization", "Bearer ") + .build()? + .check() + .await?; +``` + + + + +### 运行时配置 + +更新 api 还允许在运行时配置更新程序,以获得更大的灵活性。 +出于安全原因,一些 api 仅对 Rust 可用。 + +#### Endpoints + +设置运行时检查更新的 url 可以允许更多的动态更新,例如单独的发布通道: + +```rust +use tauri_plugin_updater::UpdaterExt; +let channel = if beta { "beta" } else { "stable" }; +let update_url = format!("https://{channel}.myserver.com/{{{{target}}}}-{{{{arch}}}}/{{{{current_version}}}}"); + +let update = app + .updater_builder() + .endpoints(vec![update_url])? + .build()? + .check() + .await?; +``` + +:::tip +注意,使用 format!() 来插入更新 URL 时,需要对变量进行双重转义, +例如 `{{{{target}}}}`。 +::: + +#### 公钥 + +在运行时设置公钥对于实现密钥轮换逻辑可能很有用。 +它可以由外掛构建器或更新器构建器设置: + +```rust +tauri_plugin_updater::Builder::new().pubkey("").build() +``` + +```rust +use tauri_plugin_updater::UpdaterExt; + +let update = app + .updater_builder() + .pubkey("") + .build()? + .check() + .await?; +``` + +#### 自定义目标 + +默认情况下,更新程序允许您使用 `{{target}}` and `{{arch}}` 变量来确定必须交付哪个更新资产。 +如果您需要有关更新的更多資訊(例如,在分发通用 macOS 二进制选项或有更多构建风格时),您可以设置自定义目标。 + + + + +```js +import { check } from '@tauri-apps/plugin-updater'; + +const update = await check({ + target: 'macos-universal', +}); +``` + + + + + +自定义目标可以由外掛构建者或更新器构建者来设置。 + +```rust +tauri_plugin_updater::Builder::new().target("macos-universal").build() +``` + +```rust +use tauri_plugin_updater::UpdaterExt; +let update = app + .updater_builder() + .target("macos-universal") + .build()? + .check() + .await?; +``` + +:::tip +默认的 `$target-$arch` 键可以使用 `tauri_plugin_updater::target()` 来获取,该函数返回一个 `Option`,当当前平台不支持更新器时,其值为 `None`。 +::: + + + + +:::note + +- 当使用自定义目标时,可能更容易使用它来确定更新平台,所以你可以删除 `{{arch}}` 变量。 +- 所提供的目标值是在使用[静态 JSON 文件](#静态-json-文件)时与平台键相匹配的键。 + +::: + +#### 允许降级 + +默认情况下,Tauri 会检查更新版本是否大于当前应用程序版本,以验证是否应该更新。 +为了允许降级,你必须使用更新构建器的 `version_comparator` API。 + +```rust +use tauri_plugin_updater::UpdaterExt; + +let update = app + .updater_builder() + .version_comparator(|current, update| { + // default comparison: `update.version > current` + update.version != current + }) + .build()? + .check() + .await?; +``` + +#### 窗口退出前的钩子函数 + +由于 Windows 安装程序的限制,Tauri 会在 Windows 上安装更新之前自动退出您的应用程序。 +要在此之前执行操作,请使用 `on_before_exit` 函数。 + +```rust +use tauri_plugin_updater::UpdaterExt; + +let update = app + .updater_builder() + .on_before_exit(|| { + println!("app is about to exit on Windows!"); + }) + .build()? + .check() + .await?; +``` + +:::note +如果没有设置任何构建器的值,则使用[配置](#tauri-配置)中的值作为备用。 +::: + +[`createUpdaterArtifacts`]: /reference/config/#createupdaterartifacts +[Distributing with CrabNebula Cloud]: /distribute/crabnebula-cloud/ +[channel]: /develop/calling-frontend/#channels +[JavaScript API 文档]: /reference/javascript/updater/ +[Rust API 文档]: https://docs.rs/tauri-plugin-updater + +## 权限 + +默认情况下,所有潜在危险的外掛命令和范围都被阻止且无法访问。您必须在您的 `capabilities` 配置中修改权限以启用这些。 + +有关更多資訊,请参阅[功能概述](/security/capabilities/),以及使用外掛权限的[分步指南](/learn/security/using-plugin-permissions/)。 + +```json title="src-tauri/capabilities/default.json" ins={4} +{ + "permissions": [ + ..., + "updater:default", + ] +} +``` + + diff --git a/src/content/docs/zh-tw/plugin/upload.mdx b/src/content/docs/zh-tw/plugin/upload.mdx new file mode 100644 index 0000000000..8786485781 --- /dev/null +++ b/src/content/docs/zh-tw/plugin/upload.mdx @@ -0,0 +1,98 @@ +--- +title: 上傳 +description: 透過 HTTP 上傳文件 +plugin: upload +--- + +import PluginLinks from '@components/PluginLinks.astro'; +import Compatibility from '@components/plugins/Compatibility.astro'; + +import { Tabs, TabItem, Steps } from '@astrojs/starlight/components'; +import CommandTabs from '@components/CommandTabs.astro'; + + + +透過 HTTP 從磁碟上傳檔案到遠端伺服器。從遠端 HTTP 伺服器下載檔案到磁碟。 + +## 支援的平台 + + + +## 設定 + + + + + 使用專案的套件管理器來新增相依性。 + + + + + + + + + 1. 執行 `cargo add tauri-plugin-upload` 指令,將外掛程式新增到專案的 `Cargo.toml` 相依性。 + + 2. 修改 `lib.rs` 來初始化外掛。 + + ```rust title="src-tauri/src/lib.rs" ins={5} + #[cfg_attr(mobile, tauri::mobile_entry_point)] + pb fn run() { + tauri::Builder::default() + // Initialize the plugin + .plugin(tauri_plugin_upload::init()) + .run(tauri::generate_context!()) + .expect("error while running tauri application"); + } + ``` + + 3. 使用你喜歡的 JavaScript 套件管理器安裝 JavaScript Guest 綁定。 + + + + + + + + +## 用法 + +一旦完成了外掛的註冊和設定過程,就可以透過 JavaScript Guest 綁定存取它的所有 API。 + +以下是一個使用外掛程式上傳和下載檔案的範例: + +```javascript +import { upload } from '@tauri-apps/plugin-upload'; + +upload( + 'https://example.com/file-upload', + './path/to/my/file.txt', + ({ progress, total }) => + console.log(`Uploaded ${progress} of ${total} bytes`), // 上傳進度時呼叫的回呼函數 + { 'Content-Type': 'text/plain' } // 與請求一起傳送的選用頭資訊 +); +``` + +```javascript +import { download } from '@tauri-apps/plugin-upload'; + +download( + 'https://example.com/file-download-link', + './path/to/save/my/file.txt', + ({ progress, total }) => + console.log(`Downloaded ${progress} of ${total} bytes`), // 下載進度時呼叫的回呼函數 + { 'Content-Type': 'text/plain' } // 與請求一起傳送的選用頭資訊 +); +``` \ No newline at end of file diff --git a/src/content/docs/zh-tw/plugin/websocket.mdx b/src/content/docs/zh-tw/plugin/websocket.mdx new file mode 100644 index 0000000000..9dea035fe8 --- /dev/null +++ b/src/content/docs/zh-tw/plugin/websocket.mdx @@ -0,0 +1,117 @@ +--- +title: WebSocket +description: 在 JavaScript 中使用 Rust 客戶端開啟 WebSocket 連線。 +plugin: websocket +--- + +import PluginLinks from '@components/PluginLinks.astro'; +import Compatibility from '@components/plugins/Compatibility.astro'; + +import { Steps, Tabs, TabItem } from '@astrojs/starlight/components'; +import CommandTabs from '@components/CommandTabs.astro'; + + + +在 JavaScript 中使用 Rust 客戶端開啟 WebSocket 連線。 + +## 支援的平台 + + + +## 設定 + +首先安裝 WebSocket 插件。 + + + + 使用專案的套件管理器來新增相依性。 + + { ' ' } + + + + + + + + 1. 在你的 `Cargo.toml` 檔案中新增以下內容來安裝 websocket 外掛程式。 + + ```toml title="src-tauri/Cargo.toml" + [dependencies] + tauri-plugin-websocket = "2.0.0" + # 或使用 Git: + tauri-plugin-websocket = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" } + ``` + + 2. 修改 `lib.rs` 來初始化外掛。 + + ```rust title="src-tauri/src/lib.rs" ins={3} + fn run() { + tauri::Builder::default() + .plugin(tauri_plugin_websocket::init()) + .run(tauri::generate_context!()) + .expect("error while running tauri application"); + } + ``` + + 3. 使用你喜歡的 JavaScript 套件管理器安裝 JavaScript Guest 綁定。 + + + + + + + + +## 用法 + +WebSocket 插件可以在 JavaScript 中使用。 + +```javascript +import WebSocket from '@tauri-apps/plugin-websocket'; + +const ws = await WebSocket.connect('ws://127.0.0.1:8080'); + +ws.addListener((msg) => { + console.log('Received Message:', msg); +}); + +await ws.send('Hello World!'); + +await ws.disconnect(); +``` + +## 權限 + +預設情況下,所有插件命令都被阻止,無法存取。你必須在你的 `capabilities` 設定中定義一個權限清單。 + +更多資訊請參閱[存取控制列表](/zh-tw/reference/acl/)。 + +```json title="src-tauri/capabilities/default.json" ins={6} +{ + "$schema": "../gen/schemas/desktop-schema.json", + "identifier": "main-capability", + "description": "Capability for the main window", + "windows": ["main"], + "permissions": ["websocket:default"] +} +``` + +| 權限 | 說明 | +|------------------------- |------------------------------------------------ | +| `websocket:default` | 允許連線和傳送資料到 WebSocket 伺服器 | +| `websocket:allow-connect` | 在沒有預先設定的有效範圍的情況下啟用 connect 指令。 | +| `websocket:deny-connect` | 拒絕沒有任何預先設定範圍的 connect 指令。 | +| `websocket:allow-send` | 在沒有預先設定的有效範圍的情況下啟用 send 指令。 | +| `websocket:deny-send` | 拒絕沒有任何預先配置範圍的 send 指令。 | \ No newline at end of file diff --git a/src/content/docs/zh-tw/plugin/window-state.mdx b/src/content/docs/zh-tw/plugin/window-state.mdx new file mode 100644 index 0000000000..ef2cdbcdd3 --- /dev/null +++ b/src/content/docs/zh-tw/plugin/window-state.mdx @@ -0,0 +1,143 @@ +--- +title: 視窗狀態 +description: 保持視窗大小和位置。 +plugin: window-state +--- + +import PluginLinks from '@components/PluginLinks.astro'; +import Compatibility from '@components/plugins/Compatibility.astro'; + +import { Tabs, TabItem } from '@astrojs/starlight/components'; +import CommandTabs from '@components/CommandTabs.astro'; + + + +保存視窗位置和大小,並在應用程式重新開啟時恢復它們。 + +## 支援的平台 + + + +## 設定 + +請安裝視窗狀態外掛。 + + + + +使用專案的套件管理器來新增依賴關係。 + +{' '} + + + + + + +1. 將以下內容新增至 `Cargo.toml` 的檔案中來安裝外掛。 + +```toml title="src-tauri/Cargo.toml" +[dependencies] +tauri-plugin-window-state = "2.0.0" +# 或使用 Git: +tauri-plugin-window-state = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" } +``` + +2. 修改 `lib.rs` 來初始化外掛。 + +```rust title="src-tauri/src/main.rs" {3} +fn main() { + tauri::Builder::default() + .plugin(tauri_plugin_window_state::Builder::default().build()) + .run(tauri::generate_context!()) + .expect("error while running tauri application"); +} +``` + +3. 使用你喜歡的 JavaScript 套件管理器安裝 JavaScript Guest 綁定。 + + + + + +## 用法 + +新增後,當應用程式被關閉時,將記住所有視窗的狀態,並在下次啟動時恢復到先前的狀態。 + +你也可以在 JavaScript 和 Rust 中存取視窗狀態外掛。 + +### JavaScript + +你可以使用 `saveWindowState` 手動儲存視窗狀態: + +```javascript +import { saveWindowState, StateFlags } from '@tauri-apps/plugin-window-state'; + +saveWindowState(StateFlags.ALL); +``` + +同樣,你可以手動從磁碟復原視窗的狀態: + +```javascript +import { + restoreStateCurrent, + StateFlags, +} from '@tauri-apps/plugin-window-state'; + +restoreStateCurrent(StateFlags.ALL); +``` + +### Rust + +你可以使用 `AppHandleExt` 特徵所暴露的 `save_window_state()` 方法: + +```rust +use tauri_plugin_window_state::{AppHandleExt, StateFlags}; + +// `tauri::AppHandle` 現在有了以下額外的方法 +app.save_window_state(StateFlags::all()); // 將所有開啟視窗的狀態儲存到磁碟 +``` + +同樣,你可以使用 `WindowExt` 特徵暴露的 `restore_state()` 方法從磁碟手動還原視窗的狀態: + +```rust +use tauri_plugin_window_state::{WindowExt, StateFlags}; + +// 所有的 `Window` 類型現在都有以下額外的方法 +window.restore_state(StateFlags::all()); // 將從磁碟還原視窗的狀態 +``` + +## 權限 + +預設情況下,所有外掛命令都被阻止,無法存取。 +你必須在你的 `capabilities` 設定中定義一個權限清單。 + +更多資訊請參閱[存取控制列表](/zh-tw/reference/acl/)。 + +```json title="src-tauri/capabilities/default.json" ins={4-5} +{ + "permissions": [ + ..., + "window-state:allow-restore-window-state", + "window-state:allow-save-window-state", + ] +} +``` + +| 權限 | 說明 | +|----------------------------------------- | ------------------------------------------------------------ | +| `window-state:allow-restore-window-state` | 啟用 restore_window_state 指令,不需要任何預先設定的有效範圍。 | +| `window-state:deny-restore-window-state` | 拒絕沒有任何預先配置範圍的 restore_window_state 指令。 | +| `window-state:allow-save-window-state` | 啟用 save_window_state 指令,不需要預先設定有效範圍。 | +| `window-state:deny-save-window-state` | 拒絕沒有任何預先設定的有效範圍的 save_window_state 指令。 | \ No newline at end of file diff --git a/src/content/docs/zh-tw/reference/acl.mdx b/src/content/docs/zh-tw/reference/acl.mdx new file mode 100644 index 0000000000..6317d0ab51 --- /dev/null +++ b/src/content/docs/zh-tw/reference/acl.mdx @@ -0,0 +1,175 @@ +--- +title: 存取控制列表 +--- + +每個 Tauri [命令](/zh-tw/develop/calling-rust/)都向 JavaScript 層公開一個 Rust 函數,該函數可以使用作業系統 API 執行任意操作,預設情況下,該層使用 Web 標準進行沙箱化。 +如果攻擊者可以執行存取 Tauri 命令的程式碼,這將為您的應用程式帶來風險。 + +為了緩解這種情況,Tauri 使用存取控制清單(Access Control List;ACL)來限制外掛命令的存取。 +預設情況下,所有外掛命令都被阻止,無法存取。 +若要啟用對應用程式所需命令的訪問,必須定義需要存取的權限清單。 + +## 功能 + +功能將權限集合與相關的視窗清單分組,以便您可以對單視窗和多視窗應用程式配置存取控制。 + +您可以將功能定義為 `src-tauri/capabilities` 目錄中的 JSON 或 TOML 檔案。 + +下面的 JSON 定義了一個功能,該功能為核心外掛和 `window.setTitle` API啟用預設功能。 + +```json title="src-tauri/capabilities/default.json" +{ + "$schema": "../gen/schemas/desktop-schema.json", + "identifier": "main-capability", + "description": "Capability for the main window", + "windows": ["main"], + "permissions": [ + "core:path:default", + "core:event:default", + "core:window:default", + "core:app:default", + "core:resources:default", + "core:menu:default", + "core:tray:default", + "core:window:allow-set-title" + ] +} +``` + +### 目標平台 + +透過定義 platforms 數組,功能可以是特定於平台的。 +預設情況下,功能適用於所有目標,但您可以選擇 linux、macOS、windows、iOS 和 android 目標的一部分。 + +例如,讓我們為桌面定義一個功能。 + +注意,它啟用了只能在桌面端使用的外掛權限: + +```json title="src-tauri/capabilities/desktop.json" +{ + "$schema": "../gen/schemas/desktop-schema.json", + "identifier": "desktop-capability", + "windows": ["main"], + "platforms": ["linux", "macOS", "windows"], + "permissions": ["global-shortcut:allow-register"] +} +``` + +並定義移動能力。注意,它啟用了只能在行動裝置上使用的外掛的權限: + +```json title="src-tauri/capabilities/mobile.json" +{ + "$schema": "../gen/schemas/mobile-schema.json", + "identifier": "mobile-capability", + "windows": ["main"], + "platforms": ["iOS", "android"], + "permissions": [ + "nfc:allow-scan", + "biometric:allow-authenticate", + "barcode-scanner:allow-scan" + ] +} +``` + +### JSON 模式 + +Tauri 產生一個 JSON 模式,包含應用程式可用的所有權限,這樣你就可以在 IDE 中實作自動補全。 +若要使用模式,請將 `$schema` 屬性設為 `capabilities/schemas` 目錄中的模式之一,這些模式是特定於平台的。 +通常你會將其設定為 `../gen/schemas/desktop-schema.json` 或 `../gen/schemas/mobile-schema.json`,不過你也可以為特定的目標平台定義功能。 + +在上面的範例中,我們為桌面端和行動端定義了特定的功能,並引用了相關的 JSON 模式。讓我們定義一個僅適用於 Linux 的功能: + +```json title="src-tauri/capabilities/linux.json" +{ + "$schema": "../gen/schemas/linux-schema.json", + "identifier": "linux-capability", + "windows": ["main"], + "platforms": ["iOS", "android"], + "permissions": ["dbus::call"] +} +``` + +### 多視窗 + +`windows` 屬性定義了應該引用權限清單的視窗清單。您可以使用萬用模式來引用動態視窗標籤。 + +以下的範例將該功能與 `main` 視窗和任何以 `editor-` 為前綴的標籤視窗連接起來。 + +```json title="src-tauri/capabilities/mobile.json" +{ + "windows": ["main", "editor-*"], + "permissions": [ + … + ] +} +``` + +### 作用領域 + +有效範圍進一步限制命令。它們的格式是特定於外掛程式的,但是 Tauri 提供了允許和拒絕某些命令操作的原語,通常限制命令輸入。 +例如,`fs` 外掛程式允許你使用有效範圍來允許或拒絕某些目錄和文件,`http` 外掛使用有效範圍來過濾允許存取的 url。 + +讓我們研究一些官方外掛的例子: + +- 允許任何 `fs` 命令存取應用程式資料目錄: + +```json title="src-tauri/capabilities/base.json" +{ + "permissions": [ + { + "identifier": "fs:scope", + "allow": [{ "path": "$APPDATA" }, { "path": "$APPDATA/**" }] + } + ] +} +``` + +:::note +`fs:scope` 是 fs 外掛定義的空權限,只是為了讓您定義全域範圍。 +::: + +- 允許 `fs` `rename` 指令存取主目錄: + +```json title="src-tauri/capabilities/base.json" +{ + "permissions": [ + { + "identifier": "fs:allow-rename", + "allow": [{ "path": "$HOME/**" }] + } + ] +} +``` + +- 設定 `http` 外掛的有效範圍: + +```json title="src-tauri/capabilities/base.json" +{ + "permissions": [ + { + "identifier": "http:default", + "allow": [{ "url": "https://*.tauri.app" }], + "deny": [{ "url": "https://private.tauri.app" }] + } + ] +} +``` + +### 遠端存取 + +預設情況下,每個功能只適用於應用程式的嵌入式內容(無論是你的 `devUrl` 還是 `frontendDist` 前端)。 +如果你想要允許遠端 URL 存取 Tauri 指令(這很危險,需要仔細設定),你可以使用 `context` 屬性。 + +在下面的範例中,我們將該功能與任何 `tauri.app` 子網域關聯。 + +```json title="src-tauri/capabilities/remote.json" +{ + "remote": { + "urls": ["https://*.tauri.app"] + }, + "local": false, + "permissions": [ + … + ] +} +``` \ No newline at end of file diff --git a/src/content/docs/zh-tw/rss.mdx b/src/content/docs/zh-tw/rss.mdx new file mode 100644 index 0000000000..8870a8182a --- /dev/null +++ b/src/content/docs/zh-tw/rss.mdx @@ -0,0 +1,22 @@ +--- +title: Tauri RSS 訂閱 +i18nReady: true +--- + +import { LinkCard } from '@astrojs/starlight/components'; + + + + diff --git a/src/content/docs/zh-tw/start/create-project.mdx b/src/content/docs/zh-tw/start/create-project.mdx new file mode 100644 index 0000000000..03dea69353 --- /dev/null +++ b/src/content/docs/zh-tw/start/create-project.mdx @@ -0,0 +1,142 @@ +--- +title: 建立專案 +sidebar: + order: 3 +--- + +import { Card, Steps } from '@astrojs/starlight/components'; + +import Cta from '@fragments/cta.mdx'; + +Tauri 如此灵活的一点在于它能够与几乎任何前端框架配合工作。 +我们创建了 [`create-tauri-app`](https://github.com/tauri-apps/create-tauri-app) 工具,帮助您使用官方维护的框架模板创建新的 Tauri 项目。 + +`create-tauri-app` 目前包含以下模板:无框架(纯HTML、CSS and JavaScript)、[Vue.js](https://vuejs.org)、[Svelte](https://svelte.dev)、[React](https://reactjs.org/)、[SolidJS](https://www.solidjs.com/)、[Angular](https://angular.io/)、[Preact](https://preactjs.com/)、[Yew](https://yew.rs/)、[Leptos](https://github.com/leptos-rs/leptos) 和 [Sycamore](https://sycamore-rs.netlify.app/)。您还可以在 [Awesome Tauri 仓库](https://github.com/tauri-apps/awesome-tauri)中找到或新增您自己的社区模板和框架。 + +{/* TODO: redirect to integrate to existing front-end project specific docs */} +或者,您可以 [将 Tauri 新增到现有的项目中](#使用-tauri-cli-手动创建) 以便快速地将现有代码库转换为 Tauri 应用。 + +## 使用 `create-tauri-app` + +要开始使用 `create-tauri-app`,请在您希望设置项目的文件夹中运行以下其中一个命令。如果您不确定要使用哪个命令,我们建议在 Linux 和 macOS 上使用 Bash 命令,在 Windows 上使用 PowerShell 命令。 + + + +请跟随提示选择您的项目名称、前端语言、包管理器以及前端框架,还有一些前端框架选项(如果有的话)。 + +:::tip[不确定怎么选择?] + +{/* TODO: redirect to integrate to existing front-end project specific docs */} +我们建议从基础模板开始(使用HTML、CSS和JavaScript,不使用前端框架),以便快速入门。随后您可以随时[引入前端框架](/zh-tw/start/create-project/)。 + +- 选择您的前端语言:`TypeScript / JavaScript` +- 选择您的包管理器:`pnpm` +- 选择您的UI模板:`Vanilla` +- 选择您的UI风格:`TypeScript` + +::: + +{/* TODO: Can CTA offer to install the deps? */} + +在 `create-tauri-app` 创建完项目后,您可以进入项目文件夹,安装依赖,然后使用 [Tauri CLI](/zh-tw/reference/cli/) 启动开发服务器: + +import CommandTabs from '@components/CommandTabs.astro'; + + + +您将会看到一个新的窗口被打开,该窗口正在运行您的应用。 + +**恭喜您!** 您已经创建了您自己的 Tauri 应用!🚀 + +## 使用 Tauri CLI 手动创建 + +如果您已经有现有的前端项目或者更愿意自行设置,您可以使用 Tauri CLI 单独初始化您项目的后端部分。 + +:::note +以下示例假设您正在创建一个新项目。如果您已经初始化了应用程序的前端部分,您可以跳过第一步。 +::: + + + + 1. 为您的项目创建一个新的目录,并初始化前端部分。您可以使用纯 HTML、CSS 和 JavaScript,或者任何您喜欢的框架,比如 Next.js、Nuxt、Svelte、Yew 或 Leptos。您只需要一种方式在浏览器中提供应用程序。下面是一个设置简单的 Vite 应用程序的示例: + + + + 2. 接着,使用您选择的包管理器安装 Tauri 的 CLI 工具。如果您使用 `cargo` 来安装 Tauri CLI,您需要全局安装它。 + + + + 3. 确定您的前端开发服务器的 URL。这个 URL 是 Tauri 用来加载您的内容的地址。例如,如果您正在使用 Vite,那么默认的 URL 是 `http://localhost:5173` 。 + + 4. 在您的项目目录下初始化 Tauri: + + + + 在执行这个指令时会显示一个提示框,提示您为不同的选项输入不同的值: + + ```sh frame=none + ✔ What is your app name? tauri-app + ✔ What should the window title be? tauri-app + ✔ Where are your web assets located? .. + ✔ What is the url of your dev server? http://localhost:5173 + ✔ What is your frontend dev command? pnpm run dev + ✔ What is your frontend build command? pnpm run build + ``` + + 这将会在您的项目中创建一个 `src-tauri` 目录,其中包含了重要的 Tauri 配置文件。 + + 5. 通过运行开发服务器来验证您的 Tauri 应用是否正常工作: + + + + 这个指令将会编译 Rust 代码,并打开一个窗口展示您的网页内容。 + + + +**恭喜您!** 您已经通过 Tauri CLI 创建了一个新的 Tauri 项目!🚀 + +## 下一步 + +{/* TODO: Some documents need to be translated. */} + +- [新增和配置前端框架](/zh-tw/start/frontend/) +- [Tauri 命令行(CLI) 参考](/zh-tw/reference/cli/) +- [了解怎样构建您的 Tauri 应用](/zh-tw/develop/) +- [探索扩展 Tauri 的附加功能](/zh-tw/plugin/) diff --git a/src/content/docs/zh-tw/start/frontend/index.mdx b/src/content/docs/zh-tw/start/frontend/index.mdx new file mode 100644 index 0000000000..50100b6139 --- /dev/null +++ b/src/content/docs/zh-tw/start/frontend/index.mdx @@ -0,0 +1,47 @@ +--- +title: 前端配置 +i18nReady: true +--- + +import { LinkCard, CardGrid } from '@astrojs/starlight/components'; + +Tauri 與前端無關,支援大多數開箱即用的前端框架。但是,有時框架需要一些額外的配置才能與 Tauri 整合。以下是具有建議配置的框架清單。 + +如果未列出框架,那麼它可能與Tauri一起使用時無需其他配置,或者可能尚未記錄。歡迎任何新增可能需要額外配置的框架的貢獻,以幫助 Tauri 社群中的其他人。 + +:::tip[未列出的前端框架? ] + +沒有列出框架?可能它可以與 Tauri 一起使用,而無需任何其他配置。閱讀[配置清單](#配置清單),以了解要檢查的任何常見配置。 + +::: + +## JavaScript + + + + + + + + + +## Rust + + + + + + +## 配置清單 + +概念上 Tauri 正如靜態 Web 主機。你需要為 Tauri 提供一個資料夾,其中包含一些 HTML、CSS、Javascript 甚至可能是 WASM,供給 Tauri 的 webview 渲染器顯示。 + +以下是將前端與 Tauri 整合所需的常見場景清單: + +{/* TODO: Link to core concept of SSG/SSR, etc. */} +{/* TODO: Link to mobile development server guide */} +{/* TODO: Concept of how to do a client-server relationship? */} + +- 使用靜態站點產生(SSG)。 Tauri 並沒有正式支援基於伺服器的替代方案(例如 SSR)。 +- 對於行動裝置開發,需要某種開發伺服器,可以在你的內部 IP 上託管前端。 +- 在應用程式和 API 之間使用適當的客戶端-伺服器關係(沒有使用 SSR 的混合解決方案)。 diff --git a/src/content/docs/zh-tw/start/frontend/leptos.mdx b/src/content/docs/zh-tw/start/frontend/leptos.mdx new file mode 100644 index 0000000000..2a95b4ee3e --- /dev/null +++ b/src/content/docs/zh-tw/start/frontend/leptos.mdx @@ -0,0 +1,57 @@ +--- +title: Leptos +tableOfContents: + minHeadingLevel: 2 + maxHeadingLevel: 5 +--- + +import { Tabs, TabItem, Steps } from '@astrojs/starlight/components'; +import CommandTabs from '@components/CommandTabs.astro'; + +Leptos 是一个基于 Rust 的 Web 框架。您可以在他们的[官方网站](https://leptos.dev/)上了解更多关于 Leptos 的資訊。本指南适用于 Leptos 的 0.6 版本。 + +## 检查清单 + +- 使用 SSG,Tauri 不支持基于服务器的解决方案。 +- 使用 `serve.ws_protocol = "ws"` 以便进行移动开发时热重载 websocket 可以正常连接。 +- 启用 `withGlobalTauri` 以确保 Tauri API 在使用 `window.__TAURI__` 变量时可用,并且可以使用 `wasm-bindgen` 导入。 + +## 示例配置 + + + +1. ##### 更新 Tauri 配置 + + ```json + // src-tauri/tauri.conf.json + { + "build": { + "beforeDevCommand": "trunk serve", + "devUrl": "http://localhost:1420", + "beforeBuildCommand": "trunk build", + "frontendDist": "../dist" + }, + "app": { + "withGlobalTauri": true + } + } + ``` + +1. ##### 更新 Trunk 配置 + + ```toml + // Trunk.toml + [build] + target = "./index.html" + + [watch] + ignore = ["./src-tauri"] + + [serve] + port = 1420 + open = false + ws_protocol = "ws" + + ``` + + diff --git a/src/content/docs/zh-tw/start/frontend/nextjs.mdx b/src/content/docs/zh-tw/start/frontend/nextjs.mdx new file mode 100644 index 0000000000..35621a257a --- /dev/null +++ b/src/content/docs/zh-tw/start/frontend/nextjs.mdx @@ -0,0 +1,123 @@ +--- +title: Next.js +i18nReady: true +tableOfContents: + collapseLevel: 1 + minHeadingLevel: 2 + maxHeadingLevel: 5 +--- + +import { Tabs, TabItem, Steps } from '@astrojs/starlight/components'; +import CommandTabs from '@components/CommandTabs.astro'; + +Next.js 是一个基于 React 的元框架。要了解更多关于 Next.js 的資訊,请访问 https://nextjs.org 。本指南适用于 Next.js 14.2.3 版本。 + +## 检查清单 + +- 通过设置 `output: 'export'` 来使用静态导出。Tauri 不支持基于服务器的解决方案。 +- 在 `tauri.conf.json` 中将 `frontendDist` 设置为 `out/`。 + +## 示例配置 + + + + 1. ##### 更新 Tauri 配置 + + + + + ```json + // src-tauri/tauri.conf.json + { + "build": { + "beforeDevCommand": "npm run dev", + "beforeBuildCommand": "npm run build", + "devUrl": "http://localhost:3000", + "frontendDist": "../dist" + } + } + ``` + + + + ```json + // src-tauri/tauri.conf.json + { + "build": { + "beforeDevCommand": "yarn dev", + "beforeBuildCommand": "yarn build", + "devUrl": "http://localhost:3000", + "frontendDist": "../dist" + } + } + ``` + + + + ```json + // src-tauri/tauri.conf.json + { + "build": { + "beforeDevCommand": "pnpm dev", + "beforeBuildCommand": "pnpm build", + "devUrl": "http://localhost:3000", + "frontendDist": "../dist" + } + } + ``` + + + + ```json + // src-tauri/tauri.conf.json + { + "build": { + "beforeDevCommand": "deno task dev", + "beforeBuildCommand": "deno task build", + "devUrl": "http://localhost:3000", + "frontendDist": "../out" + } + } + ``` + + + + + 2. ##### 更新 Next.js 配置 + + ```ts + // next.conf.mjs + const isProd = process.env.NODE_ENV === 'production'; + + const internalHost = process.env.TAURI_DEV_HOST || 'localhost'; + + /** @type {import('next').NextConfig} */ + const nextConfig = { + // 确保 Next.js 使用 SSG 而不是 SSR + // https://nextjs.org/docs/pages/building-your-application/deploying/static-exports + output: 'export', + // 注意:在 SSG 模式下使用 Next.js 的 Image 组件需要此功能。 + // 请参阅 https://nextjs.org/docs/messages/export-image-api 了解不同的解决方法。 + images: { + unoptimized: true, + }, + // 配置 assetPrefix,否则服务器无法正确解析您的资产。 + assetPrefix: isProd ? undefined : `http://${internalHost}:3000`, + }; + + export default nextConfig; + ``` + + 3. ##### 更新 package.json 配置 + + ```json + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "lint": "next lint", + "tauri": "tauri" + } + ``` + + diff --git a/src/content/docs/zh-tw/start/frontend/nuxt.mdx b/src/content/docs/zh-tw/start/frontend/nuxt.mdx new file mode 100644 index 0000000000..56020dfbab --- /dev/null +++ b/src/content/docs/zh-tw/start/frontend/nuxt.mdx @@ -0,0 +1,116 @@ +--- +title: Nuxt +i18nReady: true +tableOfContents: + minHeadingLevel: 2 + maxHeadingLevel: 5 +--- + +import { Tabs, TabItem, Steps } from '@astrojs/starlight/components'; + +Nuxt 是一个基于 Vue 的元框架。要了解更多关于 Nuxt 的資訊,请访问 https://nuxt.com 。本指南适用于 Nuxt 3.11 版本。 + +## 检查清单 + +- 配置 `ssr: false` 以启用 SSG。Tauri 不支持基于服务端的解决方案。 +- 当在 iOS 物理设备上运行时,设置 `process_env_TAURI_DEV_HOST` 作为开发服务器的主机 IP。 +- 在 `tauri.conf.json` 中将 `frontendDist` 设置为 `dist/`。 +- 使用 `nuxi generate` 编译。 +- (可选):在 `nuxt.config.ts` 中使用 `telemetry: false` 禁用遥测。 + +## 示例配置 + + + +1. 更新 Tauri 配置: + + + + + + ```json + // tauri.conf.json + { + "build": { + "beforeDevCommand": "npm run dev", + "beforeBuildCommand": "npm run generate", + "devUrl": "http://localhost:3000", + "frontendDist": "../dist" + } + } + ``` + + + + + + ```json + // tauri.conf.json + { + "build": { + "beforeDevCommand": "yarn dev", + "beforeBuildCommand": "yarn generate", + "devUrl": "http://localhost:3000", + "frontendDist": "../dist" + } + } + ``` + + + + + + ```json + // tauri.conf.json + { + "build": { + "beforeDevCommand": "pnpm dev", + "beforeBuildCommand": "pnpm generate", + "devUrl": "http://localhost:3000", + "frontendDist": "../dist" + } + } + ``` + + + + ```json + // tauri.conf.json + { + "build": { + "beforeDevCommand": "deno task dev", + "beforeBuildCommand": "deno task generate", + "devUrl": "http://localhost:3000", + "frontendDist": "../dist" + } + } + ``` + + + +2. 更新 Nuxt 配置: + + ```ts + export default defineNuxtConfig({ + // (可选) 启用 Nuxt 调试工具 + devtools: { enabled: true }, + // 启用 SSG + ssr: false, + // 使开发服务器能够被其他设备发现,以便在 iOS 物理机运行。 + devServer: { host: process.env.TAURI_DEV_HOST || 'localhost' }, + vite: { + // 为 Tauri 命令输出提供更好的支持 + clearScreen: false, + // 启用环境变量 + // 其他环境变量可以在如下网页中获知: + // https://v2.tauri.app/reference/environment-variables/ + envPrefix: ['VITE_', 'TAURI_'], + server: { + // Tauri需要一个确定的端口 + strictPort: true, + }, + }, + }); + ``` + + diff --git a/src/content/docs/zh-tw/start/frontend/qwik.mdx b/src/content/docs/zh-tw/start/frontend/qwik.mdx new file mode 100644 index 0000000000..e1e2dc97df --- /dev/null +++ b/src/content/docs/zh-tw/start/frontend/qwik.mdx @@ -0,0 +1,140 @@ +--- +title: Qwik +i18nReady: true +tableOfContents: + minHeadingLevel: 2 + maxHeadingLevel: 5 +--- + +import { Steps, TabItem, Tabs } from '@astrojs/starlight/components'; +import CommandTabs from '@components/CommandTabs.astro'; + +本指南将引导您使用 Qwik Web 框架创建 Tauri 应用程序。了解更多关于 Qwik 的資訊,请访问 https://qwik.dev 。 + +## 清单 + +- Tauri 不支持基于服务器的解决方案。请使用 [SSG](https://qwik.dev/docs/guides/static-site-generation/)。 +- 在 `tauri.conf.json` 中将 `frontendDist` 设置为 `dist/` 。 + +## 示例配置 + + + +1. ##### 创建一个新的 Qwik 应用程序 + + `} + yarn={`yarn create qwik@latest +cd `} + pnpm={`pnpm create qwik@latest +cd `} + deno={`deno run -A npm:create-qwik@latest +cd `} + /> + +1. ##### 安装 `static adapter` + + + +1. ##### 将 Tauri CLI 新增到您的项目中 + + + +1. ##### 初始化一个新的 Tauri 项目 + + + +1. ##### Tauri 配置 + + + + + + ```json + // tauri.conf.json + { + "build": { + "devUrl": "http://localhost:5173" + "frontendDist": "../dist", + "beforeDevCommand": "npm run dev", + "beforeBuildCommand": "npm run build" + } + } + ``` + + + + + + ```json + // tauri.conf.json + { + "build": { + "devUrl": "http://localhost:5173" + "frontendDist": "../dist", + "beforeDevCommand": "yarn dev", + "beforeBuildCommand": "yarn build" + } + } + ``` + + + + + + ```json + // tauri.conf.json + { + "build": { + "devUrl": "http://localhost:5173" + "frontendDist": "../dist", + "beforeDevCommand": "pnpm dev", + "beforeBuildCommand": "pnpm build" + } + } + ``` + + + + +```json +// tauri.conf.json +{ + "build": { + "devUrl": "http://localhost:5173", + "frontendDist": "../dist", + "beforeDevCommand": "deno task dev", + "beforeBuildCommand": "deno task build" + } +} +``` + + + + +1. ##### 启动你的 `tauri` 应用 + + + + diff --git a/src/content/docs/zh-tw/start/frontend/sveltekit.mdx b/src/content/docs/zh-tw/start/frontend/sveltekit.mdx new file mode 100644 index 0000000000..ef86a23ee9 --- /dev/null +++ b/src/content/docs/zh-tw/start/frontend/sveltekit.mdx @@ -0,0 +1,133 @@ +--- +title: SvelteKit +i18nReady: true +tableOfContents: + minHeadingLevel: 2 + maxHeadingLevel: 5 +--- + +import { Tabs, TabItem, Steps } from '@astrojs/starlight/components'; +import CommandTabs from '@components/CommandTabs.astro'; + +SvelteKit 是一个用于 Svelte 的元框架。了解更多关于 SvelteKit 的資訊,请访问 https://kit.svelte.dev/ 。本指南适用于 SvelteKit 2.5.7 / Svelte 4.2.15 版本。 + +## 清单 + +- Tauri 不支持基于服务器的解决方案。请通过 `static-adapter` 使用 [SSG](https://kit.svelte.dev/docs/adapter-static) 或者 [SPA](https://kit.svelte.dev/docs/single-page-apps) via `static-adapter`。 +- 在 `tauri.conf.json` 中将 `frontendDist` 设置为 `build/` 。 + +## 示例配置 + + +1. ##### 安装 `@sveltejs/adapter-static` + + + +2. ##### 更新 Tauri 配置 + + + + + + ```json + // tauri.conf.json + { + "build": { + "beforeDevCommand": "npm run dev", + "beforeBuildCommand": "npm run build", + "devUrl": "http://localhost:5173", + "frontendDist": "../build" + } + } + ``` + + + + + + ```json + // tauri.conf.json + { + "build": { + "beforeDevCommand": "yarn dev", + "beforeBuildCommand": "yarn build", + "devUrl": "http://localhost:5173", + "frontendDist": "../build" + } + } + ``` + + + + + + ```json + // tauri.conf.json + { + "build": { + "beforeDevCommand": "pnpm dev", + "beforeBuildCommand": "pnpm build", + "devUrl": "http://localhost:5173", + "frontendDist": "../build" + } + } + ``` + + + + + ```json + // tauri.conf.json + { + "build": { + "beforeDevCommand": "deno task dev", + "beforeBuildCommand": "deno task build", + "devUrl": "http://localhost:5173", + "frontendDist": "../build" + } + } + ``` + + + + +3. ##### 更新 SvelteKit 配置 + + ```js title="svelte.config.js" {1} + import adapter from '@sveltejs/adapter-static'; + import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'; + + /** @type {import('@sveltejs/kit').Config} */ + const config = { + // Consult https://kit.svelte.dev/docs/integrations#preprocessors + // for more information about preprocessors + preprocess: vitePreprocess(), + + kit: { + adapter: adapter(), + }, + }; + + export default config; + ``` + +4. ##### 禁用 SSR + + 最后,我们需要通过新增一个名为 `+layout.ts` 文件(如果您不使用 TypeScript,则为 `+layout.js`)并包含以下内容来禁用 SSR 并启用预渲染。 + + ```ts + // src/routes/+layout.ts + export const prerender = true; + export const ssr = false; + ``` + + 请注意,`static-adapter` 不需要您禁用整个应用程序的 SSR,但它使得使用依赖于全局 window 对象的 API(例如 Tauri 的 API)成为可能,而无需进行[客户端检查](https://kit.svelte.dev/docs/faq#how-do-i-use-x-with-sveltekit-how-do-i-use-a-client-side-only-library-that-depends-on-document-or-window)。 + + 此外,如果您更喜欢单页面应用(SPA)模式而不是 SSG,您可以根据[适配器文档](https://kit.svelte.dev/docs/single-page-apps)更改适配器配置和 `+layout.ts`。 + + diff --git a/src/content/docs/zh-tw/start/frontend/trunk.mdx b/src/content/docs/zh-tw/start/frontend/trunk.mdx new file mode 100644 index 0000000000..978d568595 --- /dev/null +++ b/src/content/docs/zh-tw/start/frontend/trunk.mdx @@ -0,0 +1,51 @@ +--- +title: Trunk +i18nReady: true +tableOfContents: + minHeadingLevel: 2 + maxHeadingLevel: 5 +--- + +import { Tabs, TabItem, Steps } from '@astrojs/starlight/components'; + +Trunk 是一个用于 Rust 的 WASM 网络应用程序打包工具。要了解更多关于 Trunk 的資訊,请访问 https://trunkrs.dev 。本指南适用于 Trunk 0.17.5 版本。 + +## 检查清单 + +- 使用 SSG。Tauri 不支持基于服务端的解决方案。 +- 使用 `ws_protocol = "ws"` 以便进行移动开发时热重载 websocket 可以正常连接。 +- 启用 `withGlobalTauri` 以确保 Tauri API 在使用 `window.__TAURI__` 变量时可用,并且可以使用 `wasm-bindgen` 导入。 + +## 示例配置 + + + +1. 更新 Tauri 配置: + + ```json + // tauri.conf.json + { + "build": { + "beforeDevCommand": "trunk serve", + "beforeBuildCommand": "trunk build", + "devUrl": "http://localhost:8080", + "frontendDist": "../dist" + }, + "app": { + "withGlobalTauri": true + } + } + ``` + +2. 更新 Trunk 配置: + + ```toml + # Trunk.toml + [watch] + ignore = ["./src-tauri"] + + [serve] + ws_protocol = "ws" + ``` + + diff --git a/src/content/docs/zh-tw/start/frontend/vite.mdx b/src/content/docs/zh-tw/start/frontend/vite.mdx new file mode 100644 index 0000000000..a328e04e76 --- /dev/null +++ b/src/content/docs/zh-tw/start/frontend/vite.mdx @@ -0,0 +1,120 @@ +--- +title: Vite +tableOfContents: + minHeadingLevel: 2 + maxHeadingLevel: 5 +--- + +import { Tabs, TabItem, Steps } from '@astrojs/starlight/components'; + +Vite 是为提供更快速,更简洁的现代 Web 项目开发体验而诞生的工具链。 +本教程使用的 Vite 5.4.8。 + +## 检查清单 + +- 在 `tauri.conf.json` 中使用 `dist/` 作为 `frontendDist`。 +- 在真实 iOS 设备上调试时,使用 `process.env.TAURI_DEV_HOST` 环境变量作为开发服务器的 IP 地址。 + +## 示例配置 + + + +1. ##### 更新 Tauri 配置 + + 确保你的 `package.json` 文件中有以下的 `dev` 和 `build` 命令脚本: + + ```json + { + "scripts": { + "dev": "vite dev", + "build": "vite build" + } + } + ``` + + 配置 Tauri 命令行工具,使用钩子(hooks)来自动运行 Vite 脚本,从而使用你配置好的 Vite 开发服务器和生成文件夹: + + + + + + ```json + // tauri.conf.json + { + "build": { + "beforeDevCommand": "npm run dev", + "beforeBuildCommand": "npm run build", + "devUrl": "http://localhost:5173", + "frontendDist": "../dist" + } + } + ``` + + + + + + ```json + // tauri.conf.json + { + "build": { + "beforeDevCommand": "yarn dev", + "beforeBuildCommand": "yarn build", + "devUrl": "http://localhost:5173", + "frontendDist": "../dist" + } + } + ``` + + + + + + ```json + // tauri.conf.json + { + "build": { + "beforeDevCommand": "pnpm dev", + "beforeBuildCommand": "pnpm build", + "devUrl": "http://localhost:5173", + "frontendDist": "../dist" + } + } + ``` + + + + + +1. ##### 更新 Vite 配置: + + ```js title="vite.config.js" + import { defineConfig } from 'vite'; + + export default defineConfig({ + // 防止 Vite 清除 Rust 显示的错误 + clearScreen: false, + server: { + // Tauri 工作于固定端口,如果端口不可用则报错 + strictPort: true, + // 如果设置了 host,Tauri 则会使用 + host: host || false, + port: 5173, + }, + // 新增有关当前构建目标的额外前缀,使这些 CLI 设置的 Tauri 环境变量可以在客户端代码中访问 + envPrefix: ['VITE_', 'TAURI_ENV_*'], + build: { + // Tauri 在 Windows 上使用 Chromium,在 macOS 和 Linux 上使用 WebKit + target: + process.env.TAURI_ENV_PLATFORM == 'windows' + ? 'chrome105' + : 'safari13', + // 在 debug 构建中不使用 minify + minify: !process.env.TAURI_ENV_DEBUG ? 'esbuild' : false, + // 在 debug 构建中生成 sourcemap + sourcemap: !!process.env.TAURI_ENV_DEBUG, + }, + }); + ``` + + diff --git a/src/content/docs/zh-tw/start/index.mdx b/src/content/docs/zh-tw/start/index.mdx new file mode 100644 index 0000000000..77eb2987c7 --- /dev/null +++ b/src/content/docs/zh-tw/start/index.mdx @@ -0,0 +1,48 @@ +--- +title: Tauri 是什么? +i18nReady: true +--- + +Tauri 是一个构建适用于所有主流桌面和移动平台的轻快二进制文件的框架。开发者们可以集成任何用于创建用户界面的可以被编译成 HTML、JavaScript 和 CSS 的前端框架,同时可以在必要时使用 Rust、Swift 和 Kotlin 等语言编写后端逻辑。 + +你可以使用下面的任意一个命令以利用 [`create-tauri-app`](https://github.com/tauri-apps/create-tauri-app) 创建一个新的项目。请务必参考[前置要求文档](/zh-tw/start/prerequisites/)安装所有 Tauri 必须的依赖,并阅读[前端配置指南](/zh-tw/start/frontend/)了解推荐的前端配置方案。 + +import Cta from '../../_fragments/cta.mdx'; + + + +在你成功创建了你的第一个应用后,你可以在[功能及秘诀列表](/zh-tw/plugin/)探索 Tauri 的不同功能及秘诀。 + +## 为什么选用 Tauri? + +对于开发者而言,Tauri 有三个主要优势: + +- 构建应用所需的可靠基础 +- 使用系统原生 webview(网页视图)带来的更小打包体积 +- 使用任何前端技术和多种语言绑定带来的灵活性 + +阅读 [Tauri 1.0 博客文章](/zh-tw/blog/tauri-1-0/)深入了解 Tauri 哲学思想。 + +### 可靠的基础 + +由于 Tauri 是使用 Rust 构建的,它可以利用 Rust 提供的内存、线程和类型安全方面的优势。而使用 Tauri 开发的应用也可以从中受益,甚至无需由 Rust 专家开发这些应用。 + +Tauri 的每一个主要和次要版本都会接受安全审计。这一审计不光涵盖了 Tauri 组织范围内的代码,还包括了 Tauri 所使用的上游依赖。当然,这些举措不能消除所有的风险,但它们能够为开发者提供一个坚实的基础。 + +阅读 [Tauri 安全策略](https://github.com/tauri-apps/tauri/security/policy)和 [Tauri 1.0 审计报告](https://github.com/tauri-apps/tauri/blob/dev/audits/Radically_Open_Security-v1-report.pdf)了解更多資訊。 + +### 更小的体积 + +Tauri 利用了已经存在于每一个用户系统的 webview。Tauri 应用中只包含了该应用专属的代码和资源文件,不需要在每个应用中都打包一个浏览器引擎,这意味着一个最小化的 Tauri 应用体积可能小于 600KB。 + +在[应用体积概念](/zh-tw/concept/size/)中你可以深入学习如何创建一个最优化的应用。 + +### 灵活的架构 + +由于 Tauri 使用了 web 技术,这也意味着几乎所有的前端框架都与 Tauri 兼容。 + +开发者可以在 JavaScript 中使用 `invoke` 函数实现 JavaScript 与 Rust 绑定,而 Swift 和 Kotlin 绑定则是作为 [Tauri 外掛](/zh-tw/develop/plugins/) + +[TAO](https://github.com/tauri-apps/tao) 被用于管理 Tauri 窗口创建,[WRY](https://github.com/tauri-apps/wry) 则被用于管理 webview 渲染。这些库由 Tauri 维护,并且如果需要 Tauri 没有暴露的更深入的系统集成时可以直接使用。 + +除此之外,Tauri 还维护了一些外掛拓展 Tauri 核心暴露的系统能力。你可以在[功能及秘诀章节](/zh-tw/plugin/)同时找到官方和社区提供的外掛。 diff --git a/src/content/docs/zh-tw/start/migrate/from-tauri-1.mdx b/src/content/docs/zh-tw/start/migrate/from-tauri-1.mdx new file mode 100644 index 0000000000..e07f5f81ac --- /dev/null +++ b/src/content/docs/zh-tw/start/migrate/from-tauri-1.mdx @@ -0,0 +1,1204 @@ +--- +title: 從 Tauri 1.0 升级 +i18nReady: true +sidebar: + order: 15 +--- + +import { Tabs, TabItem } from '@astrojs/starlight/components'; +import CommandTabs from '@components/CommandTabs.astro'; + +本指南将会引导你将 Tauri 1.0 应用程序升级到 Tauri 2.0 版本。 + +## 针对移动端开发 + +Tauri 的移动端界面要求你的项目输出链接库(shared library)。如果你的现有应用程序以支持移动端为目标,则必须更改你的 crate 类型,以便在生成桌面端可执行文件的同时也生成链接库。 + +1. 新增下列配置到你的 Cargo 配置文件以生成链接库。 + +```toml +// src-tauri/Cargo.toml +[lib] +name = "app_lib" +crate-type = ["staticlib", "cdylib", "rlib"] +``` + +2. 将 `src-tauri/src/main.rs` 重命名为 `src-tauri/src/lib.rs`。这一文件同时被桌面端和移动端的构建结果共享。 + +3. 将 `lib.rs` 中的 `main` 函数头修改为: + +```rust +// src-tauri/src/lib.rs +#[cfg_attr(mobile, tauri::mobile_entry_point)] +pub fn run() { + // 在这里编写你的代码 +} +``` + +`tauri::mobile_entry_point` 宏会在编译为移动端库时处理你的入口函数。 + +4. 重新创建 `main.rs` 并调用刚刚创建的共享的 `run` 函数: + +```rust +// src-tauri/src/main.rs +#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] + +fn main() { + app_lib::run(); +} +``` + +## 自动迁移 + +Tauri v2 的命令行工具包括一个 `migrate` 命令,可自动执行大部分流程,并帮助你完成迁移: + + + +{/* TODO: 2.0 */} + +在[命令行界面参考](/zh-tw/reference/cli/#migrate)中了解有关 `migrate` 命令的更多資訊。 + +## 变化摘要 + +以下是 Tauri 1.0 到 Tauri 2.0 的变化摘要: + +### Tauri 配置 + +- 移动 `package > productName` 和 `package > version` 至顶层字段。 +- 生成的二进制文件不会根据 `productName` 自动重新命名,所以你需要在配置的顶层增加 `mainBinaryName` 来匹配 `productName`。 +- 移除 `package`。 +- 重命名 `tauri` 键为 `app`。 +- 移除 `tauri > allowlist`。详情参考[迁移授权许可](#迁移授权许可)。 +- 移动 `tauri > allowlist > protocol > assetScope` 至 `app > security > assetProtocol > scope`。 +- 移动 `tauri > cli` 至 `plugins > cli`。 +- 重命名 `tauri > windows > fileDropEnabled` 为 `app > windows > dragDropEnabled`。 +- 移除 `tauri > updater > active`。 +- 移除 `tauri > updater > dialog`。 +- 移动 `tauri > updater` 至 `plugins > updater`。 +- 增加 `bundle > createUpdaterArtifacts`。如果此应用程序使用了更新程序(app updater),则必须设定此值。 + - 当从使用 v1 版本已分发的程序升级时,需设定此值为 `v1Compatible`。详情请参考[升级向导](/zh-tw/plugin/updater/)。 +- 重命名 `tauri > systemTray` 为 `app > trayIcon`。 +- 移动 `tauri > pattern` 至 `app > security > pattern`。 +- 移动 `tauri > bundle` 到顶层。 +- 移动 `tauri > bundle > dmg` 至 `bundle > macOS > dmg`。 +- 移动 `tauri > bundle > deb` 至 `bundle > linux > deb`。 +- 移动 `tauri > bundle > appimage` 至 `bundle > linux > appimage`。 +- 移除 `tauri > bundle > macOS > license`,使用 `bundle > licenseFile` 作为替代。 +- 移除 `tauri > bundle > windows > wix > license`,使用 `bundle > licenseFile` 作为替代。 +- 移除 `tauri > bundle > windows > nsis > license`, 使用 `bundle > licenseFile` 作为替代。 +- 移动 `build > withGlobalTauri` 至 `app > withGlobalTauri`。 +- 重命名 `build > distDir` 为 `frontendDist`。 +- 重命名 `build > devPath` 为 `devUrl`。 + +[Tauri 2.0 配置 API 参考资料](/zh-tw/reference/config/) + +### 全新的 Cargo 功能 + +- linux-protocol-body:启用自定义协议请求体解析,并允许 IPC 使用它。需要 webkit2gtk 2.40。 + +### 移除/修改的 Cargo 功能 + +- reqwest-client:reqwest 现在是唯一受支持的客户端。 +- reqwest-native-tls-vendored:使用 `native-tls-vendored` 作为替代。 +- process-command-api:使用 `shell` 外掛作为替代(见下节说明)。 +- shell-open-api:使用 `shell` 外掛作为替代(见下节说明)。 +- windows7-compat:被移动到 `notification` 外掛。 +- updater:updater 现在是一个外掛。 +- linux-protocol-headers:现在默认启动,因为我们更新了最低 webkit2gtk 版本支持。 +- system-tray:重命名为 `tray-icon`。 + +### Rust Crate 变化 + +- `api` 模块被移除。每个 API 模块都可以在 Tauri 外掛中找到。 +- `api::dialog` 模块被移除。使用 `tauri-plugin-dialog` 作为替代。[查看详情](#对话窗外掛迁移) +- `api::file` 模块被移除。使用 Rust 的 [`std::fs`](https://doc.rust-lang.org/std/fs/) 作为替代。 +- `api::http` 模块被移除。使用 `tauri-plugin-http` 作为替代。[查看详情](#http-外掛迁移) +- `api::ip` 模块被重写并被移动到 `tauri::ipc`。查看新的应用程序接口,特别是 `tauri::ipc::Channel`。 +- `api::path` 模块中的函数和 `tauri::PathResolved` 被移动到 `tauri::Manager::path`。[查看详情](#迁移-path-到-tauri-manager) +- `api::process::Command`、`tauri::api::shell` 和 `tauri::Manager::shell_scope` API 被移除。使用 `tauri-plugin-shell` 作为替代。[查看详情](#shell-外掛迁移) +- `api::process::current_binary` 和 `tauri::api::process::restart` 被移动到 `tauri::process`。 +- `api::version` module has been 被移除。使用 [semver crate](https://docs.rs/semver/latest/semver/) 作为替代。 +- `App::clipboard_manager` 和 `AppHandle::clipboard_manager` 被移除。使用 `tauri-plugin-clipboard` 作为替代。[查看详情](#剪贴板外掛迁移) +- `App::get_cli_matches` 被移除。使用 `tauri-plugin-cli` 作为替代。[查看详情](#命令行工具外掛迁移) +- `App::global_shortcut_manager` 和 `AppHandle::global_shortcut_manager` 被移除。使用 `tauri-plugin-global-shortcut` 作为替代。[查看详情](#全局快捷方式外掛迁移) +- `Manager::fs_scope` 被移除。文件系统范围可通过 `tauri_plugin_fs::FsExt` 访问。 +- `Plugin::PluginApi` 现在会接收一个外掛的配置作为第二个参数。 +- `Plugin::setup_with_config` 被移除。使用更新后的 `tauri::Plugin::PluginApi` 作为替代。 +- `scope::ipc::RemoteDomainAccessScope::enable_tauri_api` 和 `scope::ipc::RemoteDomainAccessScope::enables_tauri_api` 被移除。通过 `scope::ipc::RemoteDomainAccessScope::add_plugin` 单独启用每个核心外掛。 +- `scope::IpcScope` 被移除。使用 `scope::ipc::Scope` 作为替代。 +- `scope::FsScope`、`scope::GlobPattern` 和 `scope::FsScopeEvent` 被移除。分别使用 `scope::fs::Scope`、`scope::fs::Pattern` 和 `scope::fs::Event` 作为替代。 +- `updater` 模块被移除。使用 `tauri-plugin-updater` 作为替代。[查看详情](#更新外掛迁移) +- `Env.args` 字段被移除。使用 `Env.args_os` 字段作为替代。 +- `Menu`、`MenuEvent`、`CustomMenuItem`、`Submenu`、`WindowMenuEvent`、`MenuItem` 和 `Builder::on_menu_event` API 被移除。[查看详情](#托盘菜单迁移) +- `SystemTray`、`SystemTrayHandle`、`SystemTrayMenu`、`SystemTrayMenuItemHandle`、`SystemTraySubmenu`、`MenuEntry` 和 `SystemTrayMenuItem` API 被移除。[查看详情](#托盘图标模块迁移) + +### JavaScript API 变化 + +`@tauri-apps/api` 包不再提供非核心模块。只有先前的 `tauri`(现在的 `core`)、`path`、`event` 和 `window` 模块被导出。 +其他的模块被分离移至外掛中。 + +- `@tauri-apps/api/tauri` 模块被重命名为 `@tauri-apps/api/core`。[查看详情](#core-模块迁移) +- `@tauri-apps/api/cli` 模块被移除。使用 `@tauri-apps/plugin-cli` 作为替代。[查看详情](#命令行工具外掛迁移) +- `@tauri-apps/api/clipboard` 模块被移除。使用 `@tauri-apps/plugin-clipboard` 作为替代。[查看详情](#剪贴板外掛迁移) +- `@tauri-apps/api/dialog` 模块被移除。使用 `@tauri-apps/plugin-dialog` 作为替代。[查看详情](#对话窗外掛迁移) +- `@tauri-apps/api/fs` 模块被移除。使用 `@tauri-apps/plugin-fs` 作为替代。[查看详情](#文件系统外掛迁移) +- `@tauri-apps/api/global-shortcut` 模块被移除。使用 `@tauri-apps/plugin-global-shortcut` 作为替代。[查看详情](#全局快捷方式外掛迁移) +- `@tauri-apps/api/http` 模块被移除。使用 `@tauri-apps/plugin-http` 作为替代。[查看详情](#http-外掛迁移) +- `@tauri-apps/api/os` 模块被移除。使用 `@tauri-apps/plugin-os` 作为替代。[查看详情](#操作系统外掛迁移) +- `@tauri-apps/api/notification` 模块被移除。使用 `@tauri-apps/plugin-notification` 作为替代。[查看详情](#提示資訊外掛迁移) +- `@tauri-apps/api/process` 模块被移除。使用 `@tauri-apps/plugin-process` 作为替代。[查看详情](#进程外掛迁移) +- `@tauri-apps/api/shell` 模块被移除。使用 `@tauri-apps/plugin-shell` 作为替代。[查看详情](#shell-外掛迁移) +- `@tauri-apps/api/updater` 模块被移除。使用 `@tauri-apps/plugin-updater` 作为替代。[查看详情](#更新外掛迁移) +- `@tauri-apps/api/window` 模块被重命名为 `@tauri-apps/api/webviewWindow`。[查看详情](#新的窗口-api-迁移) + +### 环境变量变化 + +Tauri 命令行工具读取和写入的大部分环境变量都重新命名,以保持一致性并防止出错: + +- `TAURI_PRIVATE_KEY` -> `TAURI_SIGNING_PRIVATE_KEY` +- `TAURI_KEY_PASSWORD` -> `TAURI_SIGNING_PRIVATE_KEY_PASSWORD` +- `TAURI_SKIP_DEVSERVER_CHECK` -> `TAURI_CLI_NO_DEV_SERVER_WAIT` +- `TAURI_DEV_SERVER_PORT` -> `TAURI_CLI_PORT` +- `TAURI_PATH_DEPTH` -> `TAURI_CLI_CONFIG_DEPTH` +- `TAURI_FIPS_COMPLIANT` -> `TAURI_BUNDLER_WIX_FIPS_COMPLIANT` +- `TAURI_DEV_WATCHER_IGNORE_FILE` -> `TAURI_CLI_WATCHER_IGNORE_FILENAME` +- `TAURI_TRAY` -> `TAURI_LINUX_AYATANA_APPINDICATOR` +- `TAURI_APPLE_DEVELOPMENT_TEAM` -> `APPLE_DEVELOPMENT_TEAM` +- `TAURI_PLATFORM` -> `TAURI_ENV_PLATFORM` +- `TAURI_ARCH` -> `TAURI_ENV_ARCH` +- `TAURI_FAMILY` -> `TAURI_ENV_FAMILY` +- `TAURI_PLATFORM_VERSION` -> `TAURI_ENV_PLATFORM_VERSION` +- `TAURI_PLATFORM_TYPE` -> `TAURI_ENV_PLATFORM_TYPE` +- `TAURI_DEBUG` -> `TAURI_ENV_DEBUG` + +### 事件系统 + +事件系统经过重新设计,更易于使用。现在,它不再依赖于事件源,而是依赖于事件目标,实现起来更加简单。 + +- `emit` 函数现在会向所有事件侦听器发送事件。 +- 新增一个新的 `emit_to` 函数以向特定目标触发事件。 +- `emit_filter` 现在基于 [`EventTarget`](https://docs.rs/tauri/2.0.0/tauri/event/enum.EventTarget.html) 进行过滤,而不是基于一个视窗。 +- 将 `listen_global` 重命名为 `listen_any`。现在,它可以监听所有事件,无论其过滤器和目标是什么。 + +### 多 webview 支持 + +Tauri v2 引入了多 webview 支持,目前处在 `unstable` feature 标识之后。 +为了支持这一功能,我们将 Rust 的 `Window` 类型重命名为 `WebviewWindow`、`Manager` 的 `get_window` 函数重命名为 `get_webview_window`。 + +`WebviewWindow` JS API 类型现在是从 `@tauri-apps/api/webviewWindow` 中重导出,而不是从 `@tauri-apps/api/window` 中。 + +## 具体迁移细节 + +将 Tauri 1.0 应用程序迁移到 Tauri 2.0 时可能遇到的常见情况。 + +### `core` 模块迁移 + +`@tauri-apps/api/tauri` 模块被重命名为 `@tauri-apps/api/core`。 +只需要修改你的导入路径: + +```diff +- import { invoke } from "@tauri-apps/api/tauri" ++ import { invoke } from "@tauri-apps/api/core" +``` + +### 命令行工具外掛迁移 + +Rust 的 `App::get_cli_matches` 和 JavaScript 的 `@tauri-apps/api/cli` API 被移除。使用 `@tauri-apps/plugin-cli` 外掛作为替代: + +1. 新增 Cargo 依赖项: + +```toml +# Cargo.toml +[dependencies] +tauri-plugin-cli = "2" +``` + +2. 在 JavaScript 或 Rust 项目中使用: + + + + +```rust +fn main() { + tauri::Builder::default() + .plugin(tauri_plugin_cli::init()) +} +``` + +```json +// package.json +{ + "dependencies": { + "@tauri-apps/plugin-cli": "^2.0.0" + } +} +``` + +```javascript +import { getMatches } from '@tauri-apps/plugin-cli'; +const matches = await getMatches(); +``` + + + + +```rust +fn main() { + use tauri_plugin_cli::CliExt; + tauri::Builder::default() + .plugin(tauri_plugin_cli::init()) + .setup(|app| { + let cli_matches = app.cli().matches()?; + Ok(()) + }) +} +``` + + + + +### 剪贴板外掛迁移 + +Rust 的 `App::clipboard_manager` 和 `AppHandle::clipboard_manager` 以及 JavaScript 的 `@tauri-apps/api/clipboard` API 被移除。使用 `@tauri-apps/plugin-clipboard-manager` 外掛作为替代: + +```toml +[dependencies] +tauri-plugin-clipboard-manager = "2" +``` + + + + +```rust +fn main() { + tauri::Builder::default() + .plugin(tauri_plugin_clipboard_manager::init()) +} +``` + +```json +// package.json +{ + "dependencies": { + "@tauri-apps/plugin-clipboard-manager": "^2.0.0" + } +} +``` + +```javascript +import { writeText, readText } from '@tauri-apps/plugin-clipboard-manager'; +await writeText('Tauri is awesome!'); +assert(await readText(), 'Tauri is awesome!'); +``` + + + + +```rust +use tauri_plugin_clipboard::{ClipboardExt, ClipKind}; +tauri::Builder::default() + .plugin(tauri_plugin_clipboard::init()) + .setup(|app| { + app.clipboard().write(ClipKind::PlainText { + label: None, + text: "Tauri is awesome!".into(), + })?; + Ok(()) + }) +``` + + + + +### 对话窗外掛迁移 + +Rust 的 `tauri::api::dialog` 和 JavaScript 的 `@tauri-apps/api/dialog` API 被移除。使用 `@tauri-apps/plugin-dialog` 外掛作为替代: + +1. 新增 Cargo 依赖项: + +```toml +# Cargo.toml +[dependencies] +tauri-plugin-dialog = "2" +``` + +2. 在 JavaScript 或 Rust 项目中使用: + + + + +```rust +fn main() { + tauri::Builder::default() + .plugin(tauri_plugin_dialog::init()) +} +``` + +```json +// package.json +{ + "dependencies": { + "@tauri-apps/plugin-dialog": "^2.0.0" + } +} +``` + +```javascript +import { save } from '@tauri-apps/plugin-dialog'; +const filePath = await save({ + filters: [ + { + name: 'Image', + extensions: ['png', 'jpeg'], + }, + ], +}); +``` + + + + +```rust +use tauri_plugin_dialog::DialogExt; +tauri::Builder::default() + .plugin(tauri_plugin_dialog::init()) + .setup(|app| { + app.dialog().file().pick_file(|file_path| { + // 对此处的可选文件路径进行处理 + // 如果用户关闭了对话框,则文件路径为 `None`。 + }); + + app.dialog().message("Tauri is Awesome!").show(); + Ok(()) + }) +``` + + + + +### 文件系统外掛迁移 + +Rust 的 `App::get_cli_matches` 和 JavaScript 的 `@tauri-apps/api/fs` API 被移除。使用 Rust 的 [`std::fs`](https://doc.rust-lang.org/std/fs/) 或 JavaScript 的 `@tauri-apps/plugin-fs` 外掛作为替代: + +1. 新增 Cargo 依赖项: + +```toml +# Cargo.toml +[dependencies] +tauri-plugin-fs = "2" +``` + +2. 在 JavaScript 或 Rust 项目中使用: + + + + +```rust +fn main() { + tauri::Builder::default() + .plugin(tauri_plugin_fs::init()) +} +``` + +```json +// package.json +{ + "dependencies": { + "@tauri-apps/plugin-fs": "^2.0.0" + } +} +``` + +```javascript +import { mkdir, BaseDirectory } from '@tauri-apps/plugin-fs'; +await mkdir('db', { baseDir: BaseDirectory.AppLocalData }); +``` + +一些函数和类型被重命名或移除: + +- `Dir` 枚举别名(enum alias)被移除。使用 `BaseDirectory`。 +- `FileEntry`、`FsBinaryFileOption`、`FsDirOptions`、`FsOptions`、`FsTextFileOption` 和 `BinaryFileContents` 接口和类型别名被移除,并被与每个对应的函数相匹配的接口取代。 +- `createDir` 被重命名为 `mkdir`。 +- `readBinaryFile` 被重命名为 `readFile`。 +- `removeDir` 被移除并被 `remove` 取代。 +- `removeFile` 被移除并被 `remove` 取代。 +- `renameFile` 被移除并被 `rename` 取代。 +- `writeBinaryFile` 被重命名为 `writeFile`。 + + + + +使用 Rust [`std::fs`](https://doc.rust-lang.org/std/fs/) 中的函数。 + + + + +### 全局快捷方式外掛迁移 + +Rust 的 `App::global_shortcut_manager` 和 `AppHandle::global_shortcut_manager` 以及 JavaScript 的 `@tauri-apps/api/global-shortcut` API 被移除。使用 `@tauri-apps/plugin-global-shortcut` 外掛作为替代: + +1. 新增 Cargo 依赖项: + +```toml +# Cargo.toml +[dependencies] +[target."cfg(not(any(target_os = \"android\", target_os = \"ios\")))".dependencies] +tauri-plugin-global-shortcut = "2" +``` + +2. 在 JavaScript 或 Rust 项目中使用: + + + + +```rust +fn main() { + tauri::Builder::default() + .plugin(tauri_plugin_global_shortcut::Builder::default().build()) +} +``` + +```json +// package.json +{ + "dependencies": { + "@tauri-apps/plugin-global-shortcut": "^2.0.0" + } +} +``` + +```javascript +import { register } from '@tauri-apps/plugin-global-shortcut'; +await register('CommandOrControl+Shift+C', () => { + console.log('Shortcut triggered'); +}); +``` + + + + +```rust +use tauri_plugin_global_shortcut::GlobalShortcutExt; + +tauri::Builder::default() + .plugin( + tauri_plugin_global_shortcut::Builder::new().with_handler(|app, shortcut| { + println!("Shortcut triggered: {:?}", shortcut); + }) + .build(), + ) + .setup(|app| { + // 注册全局快捷方式 + // 在 macOS 上使用 Cmd 键 + // 在 Windows 和 Linux 系统中,使用 Ctrl 键 + app.global_shortcut().register("CmdOrCtrl+Y")?; + Ok(()) + }) +``` + + + + +### HTTP 外掛迁移 + +Rust 的 `tauri::api::http` 和 JavaScript 的 `@tauri-apps/api/http` API 被移除。使用 `@tauri-apps/plugin-http` 外掛作为替代: + +1. 新增 Cargo 依赖项: + +```toml +# Cargo.toml +[dependencies] +tauri-plugin-http = "2" +``` + +2. 在 JavaScript 或 Rust 项目中使用: + + + + +```rust +fn main() { + tauri::Builder::default() + .plugin(tauri_plugin_http::init()) +} +``` + +```json +// package.json +{ + "dependencies": { + "@tauri-apps/plugin-http": "^2.0.0" + } +} +``` + +```javascript +import { fetch } from '@tauri-apps/plugin-http'; +const response = await fetch( + 'https://raw.githubusercontent.com/tauri-apps/tauri/dev/package.json' +); +``` + + + + +```rust +use tauri_plugin_http::reqwest; + +tauri::Builder::default() + .plugin(tauri_plugin_http::init()) + .setup(|app| { + let response_data = tauri::async_runtime::block_on(async { + let response = reqwest::get( + "https://raw.githubusercontent.com/tauri-apps/tauri/dev/package.json", + ) + .await + .unwrap(); + response.text().await + })?; + Ok(()) + }) +``` + +HTTP 外掛重导出了 [reqwest](https://docs.rs/reqwest/latest/reqwest/)。所以你可以查阅它的文档以获取更多資訊。 + + + + +### 提示資訊外掛迁移 + +Rust 的 `tauri::api::notification` 和 JavaScript 的 `@tauri-apps/api/notification` API 被移除。使用 `@tauri-apps/plugin-notification` 外掛作为替代: + +1. 新增 Cargo 依赖项: + +```toml +# Cargo.toml +[dependencies] +tauri-plugin-notification = "2" +``` + +2. 在 JavaScript 或 Rust 项目中使用: + + + + +```rust +fn main() { + tauri::Builder::default() + .plugin(tauri_plugin_notification::init()) +} +``` + +```json +// package.json +{ + "dependencies": { + "@tauri-apps/plugin-notification": "^2.0.0" + } +} +``` + +```javascript +import { sendNotification } from '@tauri-apps/plugin-notification'; +sendNotification('Tauri is awesome!'); +``` + + + + +```rust +use tauri_plugin_notification::NotificationExt; +use tauri::plugin::PermissionState; + +fn main() { + tauri::Builder::default() + .plugin(tauri_plugin_notification::init()) + .setup(|app| { + if app.notification().permission_state()? == PermissionState::Unknown { + app.notification().request_permission()?; + } + if app.notification().permission_state()? == PermissionState::Granted { + app.notification() + .builder() + .body("Tauri is awesome!") + .show()?; + } + Ok(()) + }) +} +``` + + + + +### 菜单模块迁移 + +Rust 的 `Menu` API 被移动到 `tauri::menu` 模块,并使用 [muda crate](https://github.com/tauri-apps/muda) 重构。 + +#### 使用 `tauri::menu::MenuBuilder` + +使用 `tauri::menu::MenuBuilder` 以替换 `tauri::Menu`。 +注意到它的构造器接收一个 `Manager` 实例(`App`、`AppHandle` 或 `WebviewWindow` 中的一个)作为入参: + +```rust +use tauri::menu::MenuBuilder; + +tauri::Builder::default() + .setup(|app| { + let menu = MenuBuilder::new(app) + .copy() + .paste() + .separator() + .undo() + .redo() + .text("open-url", "Open URL") + .check("toggle", "Toggle") + .icon("show-app", "Show App", app.default_window_icon().cloned().unwrap()) + .build()?; + Ok(()) + }) +``` + +#### 使用 `tauri::menu::PredefinedMenuItem` + +使用 `tauri::menu::PredefinedMenuItem` 以替换 `tauri::MenuItem`: + +```rust +use tauri::menu::{MenuBuilder, PredefinedMenuItem}; + +tauri::Builder::default() + .setup(|app| { + let menu = MenuBuilder::new(app).item(&PredefinedMenuItem::copy(app)?).build()?; + Ok(()) + }) +``` + +:::tip + +`Menu` 构造器有专门的方法来新增每个预定义的菜单项,因此您可以调用 `.copy()` 以替换 `.item(&PredefinedMenuItem::copy(app,None)?)`。 + +::: + +#### 使用 `tauri::menu::MenuItemBuilder` + +使用 `tauri::menu::MenuItemBuilder` 以替换 `tauri::CustomMenuItem`: + +```rust +use tauri::menu::MenuItemBuilder; + +tauri::Builder::default() + .setup(|app| { + let toggle = MenuItemBuilder::new("Toggle").accelerator("Ctrl+Shift+T").build(app)?; + Ok(()) + }) +``` + +#### 使用 `tauri::menu::SubmenuBuilder` + +使用 `tauri::menu::SubmenuBuilder` 以替换 `tauri::Submenu`: + +```rust +use tauri::menu::{MenuBuilder, SubmenuBuilder}; + +tauri::Builder::default() + .setup(|app| { + let submenu = SubmenuBuilder::new(app, "Sub") + .text("Tauri") + .separator() + .check("Is Awesome") + .build()?; + let menu = MenuBuilder::new(app).item(&submenu).build()?; + Ok(()) + }) +``` + +`tauri::Builder::menu` 现在接收一个闭包,因为菜单需要一个 `Manager` 实例来构造。参考[相关文档](https://docs.rs/tauri/2.0.0/tauri/struct.Builder.html#method.menu)以获取更多資訊。 + +#### 菜单触发事件迁移 + +Rust 的 `tauri::Builder::on_menu_event` API 被移除。使用 `tauri::App::on_menu_event` 或 `tauri::AppHandle::on_menu_event` 作为替代: + +```rust +use tauri::menu::{CheckMenuItemBuilder, MenuBuilder, MenuItemBuilder}; + +tauri::Builder::default() + .setup(|app| { + let toggle = MenuItemBuilder::with_id("toggle", "Toggle").build(app)?; + let check = CheckMenuItemBuilder::new("Mark").build(app)?; + let menu = MenuBuilder::new(app).items(&[&toggle, &check]).build()?; + + app.set_menu(menu)?; + + app.on_menu_event(move |app, event| { + if event.id() == check.id() { + println!("`check` triggered, do something! is checked? {}", check.is_checked().unwrap()); + } else if event.id() == "toggle" { + println!("toggle triggered!"); + } + }); + Ok(()) + }) +``` + +请注意,有两种方法可以检查哪个菜单项被选中:将项目移至事件处理程序闭包并比较 ID,或通过 `with_id` 构造函数为项目定义自定义 ID,并使用该 ID 字符串进行比较。 + +:::tip + +菜单项可以跨菜单共享,菜单事件绑定到菜单项而不是菜单或窗口。 + +如果不想在选中菜单项时触发所有监听器,请不要共享菜单项,而使用可以 move 到 `tauri::WebviewWindow/WebviewWindowBuilder::on_menu_event` 的闭包中的专有实例。 + +::: + +### 操作系统外掛迁移 + +Rust 的 `tauri::api::os` 和 JavaScript 的 `@tauri-apps/api/os` API 被移除。使用 `@tauri-apps/plugin-os` 外掛作为替代: + +1. 新增 Cargo 依赖项: + +```toml +# Cargo.toml +[dependencies] +tauri-plugin-os = "2" +``` + +2. 在 JavaScript 或 Rust 项目中使用: + + + + +```rust +fn main() { + tauri::Builder::default() + .plugin(tauri_plugin_os::init()) +} +``` + +```json +// package.json +{ + "dependencies": { + "@tauri-apps/plugin-os": "^2.0.0" + } +} +``` + +```javascript +import { arch } from '@tauri-apps/plugin-os'; +const architecture = await arch(); +``` + + + + +```rust +fn main() { + tauri::Builder::default() + .plugin(tauri_plugin_os::init()) + .setup(|app| { + let os_arch = tauri_plugin_os::arch(); + Ok(()) + }) +} +``` + + + + +### 进程外掛迁移 + +Rust 的 `tauri::api::process` 和 JavaScript 的 `@tauri-apps/api/process` API 被移除。使用 `@tauri-apps/plugin-process` 外掛作为替代: + +1. 新增到 Cargo 依赖项: + +```toml +# Cargo.toml +[dependencies] +tauri-plugin-process = "2" +``` + +2. 在 JavaScript 或 Rust 项目中使用: + + + + +```rust +fn main() { + tauri::Builder::default() + .plugin(tauri_plugin_process::init()) +} +``` + +```json +// package.json +{ + "dependencies": { + "@tauri-apps/plugin-process": "^2.0.0" + } +} +``` + +```javascript +import { exit, relaunch } from '@tauri-apps/plugin-process'; +await exit(0); +await relaunch(); +``` + + + + +```rust +fn main() { + tauri::Builder::default() + .plugin(tauri_plugin_process::init()) + .setup(|app| { + // 以给定的状态码退出应用程序 + app.handle().exit(1); + // 重新启动应用程序 + app.handle().restart(); + Ok(()) + }) +} +``` + + + + +### Shell 外掛迁移 + +Rust 的 `tauri::api::shell` 和 JavaScript 的 `@tauri-apps/api/shell` API 被移除。使用 `@tauri-apps/plugin-shell` 外掛作为替代: + +1. 新增 Cargo 依赖项: + +```toml +# Cargo.toml +[dependencies] +tauri-plugin-shell = "2" +``` + +2. 在 JavaScript 或 Rust 项目中使用: + + + + +```rust +fn main() { + tauri::Builder::default() + .plugin(tauri_plugin_shell::init()) +} +``` + +```json +// package.json +{ + "dependencies": { + "@tauri-apps/plugin-shell": "^2.0.0" + } +} +``` + +```javascript +import { Command, open } from '@tauri-apps/plugin-shell'; +const output = await Command.create('echo', 'message').execute(); + +await open('https://github.com/tauri-apps/tauri'); +``` + + + + +- 打开一个 URL: + +```rust +use tauri_plugin_shell::ShellExt; + +fn main() { + tauri::Builder::default() + .plugin(tauri_plugin_shell::init()) + .setup(|app| { + app.shell().open("https://github.com/tauri-apps/tauri", None)?; + Ok(()) + }) +} +``` + +- 生成子进程并获取状态码: + +```rust +use tauri_plugin_shell::ShellExt; + +fn main() { + tauri::Builder::default() + .plugin(tauri_plugin_shell::init()) + .setup(|app| { + let status = tauri::async_runtime::block_on(async move { app.shell().command("which").args(["ls"]).status().await.unwrap() }); + println!("`which` finished with status: {:?}", status.code()); + Ok(()) + }) +} +``` + +- 生成子进程并捕获其输出: + +```rust +use tauri_plugin_shell::ShellExt; + +fn main() { + tauri::Builder::default() + .plugin(tauri_plugin_shell::init()) + .setup(|app| { + let output = tauri::async_runtime::block_on(async move { app.shell().command("echo").args(["TAURI"]).output().await.unwrap() }); + assert!(output.status.success()); + assert_eq!(String::from_utf8(output.stdout).unwrap(), "TAURI"); + Ok(()) + }) +} +``` + +- 生成一个子进程并异步读取其事件: + +```rust +use tauri_plugin_shell::{ShellExt, process::CommandEvent}; + +fn main() { + tauri::Builder::default() + .plugin(tauri_plugin_shell::init()) + .setup(|app| { + let handle = app.handle().clone(); + tauri::async_runtime::spawn(async move { + let (mut rx, mut child) = handle.shell().command("cargo") + .args(["tauri", "dev"]) + .spawn() + .expect("Failed to spawn cargo"); + + let mut i = 0; + while let Some(event) = rx.recv().await { + if let CommandEvent::Stdout(line) = event { + println!("got: {}", String::from_utf8(line).unwrap()); + i += 1; + if i == 4 { + child.write("message from Rust\n".as_bytes()).unwrap(); + i = 0; + } + } + } + }); + Ok(()) + }) +} +``` + + + + +### 托盘图标模块迁移 + +Rust 的 `SystemTray` API 被重命名为 `TrayIcon` 以确保一致性。新的 API 可以在 Rust 的 `tray` 模块中找到。 + +#### 使用 `tauri::tray::TrayIconBuilder` + +使用 `tauri::tray::TrayIconBuilder` 以替换 `tauri::SystemTray`: + +```rust +let tray = tauri::tray::TrayIconBuilder::with_id("my-tray").build(app)?; +``` + +查阅 [`TrayIconBuilder`](https://docs.rs/tauri/2.0.0/tauri/tray/struct.TrayIconBuilder.html) 以获取更多資訊。 + +#### 托盘菜单迁移 + +使用 `tauri::menu::Menu` 以替换 `tauri::SystemTrayMenu`、`tauri::menu::Submenu` 以替换 `tauri::SystemTraySubmenu` 和 `tauri::menu::PredefinedMenuItem` 以替换 `tauri::SystemTrayMenuItem`。 + +#### 托盘事件迁移 + +`tauri::SystemTray::on_event` 被分割为 `tauri::tray::TrayIconBuilder::on_menu_event` 和 `tauri::tray::TrayIconBuilder::on_tray_icon_event`: + +```rust +use tauri::{ + menu::{MenuBuilder, MenuItemBuilder}, + tray::{MouseButton, MouseButtonState, TrayIconBuilder, TrayIconEvent}, +}; + +tauri::Builder::default() + .setup(|app| { + let toggle = MenuItemBuilder::with_id("toggle", "Toggle").build(app)?; + let menu = MenuBuilder::new(app).items(&[&toggle]).build()?; + let tray = TrayIconBuilder::new() + .menu(&menu) + .on_menu_event(move |app, event| match event.id().as_ref() { + "toggle" => { + println!("toggle clicked"); + } + _ => (), + }) + .on_tray_icon_event(|tray, event| { + if let TrayIconEvent::Click { + button: MouseButton::Left, + button_state: MouseButtonState::Up, + .. + } = event + { + let app = tray.app_handle(); + if let Some(webview_window) = app.get_webview_window("main") { + let _ = webview_window.show(); + let _ = webview_window.set_focus(); + } + } + }) + .build(app)?; + + Ok(()) + }) +``` + +### 更新外掛迁移 + +内置的自动更新的提示窗被移除。作为代替,使用 Rust 和 JS API 以检查和安装更新。 + +Rust 的 `tauri::updater` 和 JavaScript 的 `@tauri-apps/api-updater` API 被移除。 +使用 `@tauri-apps/plugin-updater` 设置一个自定义的更新器: + +1. 新增 Cargo 依赖项: + +```toml +[dependencies] +tauri-plugin-updater = "2" +``` + +2. 在 JavaScript 或 Rust 项目中使用: + + + + +```rust +fn main() { + tauri::Builder::default() + .plugin(tauri_plugin_updater::Builder::new().build()) +} +``` + +```json +// package.json +{ + "dependencies": { + "@tauri-apps/plugin-updater": "^2.0.0" + } +} +``` + +```javascript +import { check } from '@tauri-apps/plugin-updater'; +import { relaunch } from '@tauri-apps/plugin-process'; + +const update = await check(); +if (update?.available) { + console.log(`Update to ${update.version} available! Date: ${update.date}`); + console.log(`Release notes: ${update.body}`); + await update.downloadAndInstall(); + // 需要 `process` 外掛 + await relaunch(); +} +``` + + + + +检查更新: + +```rust +use tauri_plugin_updater::UpdaterExt; + +fn main() { + tauri::Builder::default() + .plugin(tauri_plugin_updater::Builder::new().build()) + .setup(|app| { + let handle = app.handle(); + tauri::async_runtime::spawn(async move { + let response = handle.updater().check().await; + }); + Ok(()) + }) +} +``` + +设置自定义更新目标: + +```rust +fn main() { + let mut updater = tauri_plugin_updater::Builder::new(); + #[cfg(target_os = "macos")] + { + updater = updater.target("darwin-universal"); + } + tauri::Builder::default() + .plugin(updater.build()) +} +``` + + + + +### 迁移 `Path` 到 Tauri `Manager` + +Rust 的 `tauri::api::path` 模块的函数和 `tauri::PathResolver` 被移动到 `tauri::Manager::path`: + +```rust +use tauri::{path::BaseDirectory, Manager}; + +tauri::Builder::default() + .setup(|app| { + let home_dir_path = app.path().home_dir().expect("failed to get home dir"); + + let path = app.path().resolve("path/to/something", BaseDirectory::Config)?; + + Ok(()) + }) +``` + +### 新的窗口 API 迁移 + +在 Rust 侧,`Window` 被重命名为 `WebviewWindow`,它的构建器 `WindowBuilder` 被重命名为 `WebviewWindowBuilder`。 + +另外,`Manager::get_window` 函数被重命名为 `get_webview_window`,窗口的 `parent_window` API 被重命名为 `parent_raw` 以支持高级窗口父 API。 + +在 JavaScript 侧,`WebviewWindow` 类现在从 `@tauri-apps/api/webviewWindow` 中重导出。 + +`onMenuClicked` 函数已被移除。你可以在 JavaScript 中创建菜单时拦截菜单事件。 + +### 迁移嵌入的附加文件 (Resources) + +在 JavaScript 侧,请确保[迁移文件系统外掛](#文件系统外掛迁移)。 + +此外,请注意[迁移授权许可](#迁移授权许可)中对 v1 的授权许可列表所作的更改。 + +在 Rust 侧,请确保[将 Path 迁移到 Tauri Manager](#迁移-path-到-tauri-manager). + +### 迁移嵌入的外部二进制文档 (Sidecar) + +在 Tauri v1 中,外部的二进制文件和其参数在许可列表中被定义。而在 v2 中,使用了新的权限系统。有关详细資訊,请阅读[迁移授权许可](#迁移授权许可)。 + +在 JavaScript 侧,请确保[迁移 Shell 外掛](#shell-外掛迁移)。 + +在 Rust 侧,`tauri::api::process` API 已经被移除,使用 `tauri_plugin_shell::ShellExt` 和 `tauri_plugin_shell::process::CommandEvent` 作为替代。[嵌入的外部二进制文档](/zh-tw/develop/sidecar/#从-rust-运行)将指导你如何迁移。 + +在 v2 中移除了 "process-command-api" 特性。因此,运行外部的二进制文件不需要再在 Tauri 配置文件中配置。 + +### 迁移授权许可 + +授权许可列表 v1 已被重写为一个全新的权限系统,可用于单个外掛,并可为多窗口和远程 URL 支持进行更多配置。 +这个新系统的工作原理类似于访问控制列表(ACL),你可以允许或拒绝命令、将权限分配给一组特定的窗口和域,并定义访问范围。 + +要为应用程序启用权限,您必须在 `src-tauri/capabilities` 文件夹内创建许可配置文件,随后 Tauri 会自动为您配置其他一切。 + +`migrate` 命令行工具命令会自动解析你的授权许可列表 v1 并生成相关的许可配置文件。 + +要了解有关权限和功能的更多資訊,请参阅[安全文档](/zh-tw/security/)。 diff --git a/src/content/docs/zh-tw/start/migrate/from-tauri-2-beta.mdx b/src/content/docs/zh-tw/start/migrate/from-tauri-2-beta.mdx new file mode 100644 index 0000000000..c51e3e0d18 --- /dev/null +++ b/src/content/docs/zh-tw/start/migrate/from-tauri-2-beta.mdx @@ -0,0 +1,150 @@ +--- +title: 从 Tauri 2.0 Beta 升级 +i18nReady: false +sidebar: + order: 16 +--- + +import { Tabs, TabItem } from '@astrojs/starlight/components'; +import CommandTabs from '@components/CommandTabs.astro'; + +本指南将引导您将 Tauri 2.0 Beta 应用程序升级到 Tauri 2.0 RC 版本。 + +## 自动迁移 + +Tauri v2 CLI 包含一个 `migrate` 命令,它自动化了大部分过程,并帮助您完成迁移。 + + + +有关 `migrate` 命令的更多資訊,请参阅[命令行接口参考](/zh-tw/reference/cli/#migrate) + +## 破坏性变更 + +从 Beta 版到发布 RC 版,我们有几个重大变化。这些可以自动迁移(见上文),也可以手动执行。 + +### Tauri 核心外掛 + +我们在功能中改变了 Tauri 内置外掛的处理方式 [PR #10390](https://github.com/tauri-apps/tauri/pull/10390)。 + +要从最新的 Beta 版本迁移,您需要在您的能力中新增所有核心权限标识符 `core:`,或者切换到 `core:default` 权限并删除旧的核心外掛标识符。 + +```json +... +"permissions": [ + "path:default", + "event:default", + "window:default", + "app:default", + "image:default", + "resources:default", + "menu:default", + "tray:default", +] +... +``` + +```json +... +"permissions": [ + "core:path:default", + "core:event:default", + "core:window:default", + "core:app:default", + "core:image:default", + "core:resources:default", + "core:menu:default", + "core:tray:default", +] +... +``` + +我们还新增了一个新的特殊权限集 `core:default`,其中包含所有核心外掛的默认权限,这样您就可以简化在能力配置中的权限模板。 + +```json +... +"permissions": [ + "core:default" +] +... +``` + +### 内置开发服务器 + +我们对内置开发服务器的网络公开在 [PR #10437](https://github.com/tauri-apps/tauri/pull/10437) 和 [PR #10456](https://github.com/tauri-apps/tauri/pull/10456) 进行了更改。 + +内置的移动开发服务器不再公开网络范围,并且将本地机器上的流量直接隧道传输到设备。 + +目前,在 iOS 设备上运行时(无论是直接运行还是通过 Xcode),此改进不会自动应用。 +在这种情况下,我们默认使用开发服务器的公共网络地址,但有一种方法可以绕过这个问题,即打开 Xcode 以自动建立您的 macOS 机器与连接的 iOS 设备之间的连接,然后运行 `tauri ios dev --force-ip-prompt` 来选择 iOS 设备的 TUN 地址(以 **::2** 结尾)。 + +如果打算在物理 iOS 设备上运行,您的开发服务器配置需要适应此更改。 +以前我们建议检查 `TAURI_ENV_PLATFORM` 环境变量是否与 `android` 或 `ios` 匹配, +但是现在除非使用 iOS 设备,否则我们可以连接到本地主机,您应该检查 `TAURI_DEV_HOST` 环境变量。 +以下是一个 Vite 配置迁移的示例。 + +- 2.0.0-beta: + +```js +import { defineConfig } from 'vite'; +import { svelte } from '@sveltejs/vite-plugin-svelte'; +import { internalIpV4Sync } from 'internal-ip'; + +const mobile = !!/android|ios/.exec(process.env.TAURI_ENV_PLATFORM); + +export default defineConfig({ + plugins: [svelte()], + clearScreen: false, + server: { + host: mobile ? '0.0.0.0' : false, + port: 1420, + strictPort: true, + hmr: mobile + ? { + protocol: 'ws', + host: internalIpV4Sync(), + port: 1421, + } + : undefined, + }, +}); +``` + +- 2.0.0: + +```js +import { defineConfig } from 'vite'; +import Unocss from 'unocss/vite'; +import { svelte } from '@sveltejs/vite-plugin-svelte'; + +const host = process.env.TAURI_DEV_HOST; + +export default defineConfig({ + plugins: [svelte()], + clearScreen: false, + server: { + host: host || false, + port: 1420, + strictPort: true, + hmr: host + ? { + protocol: 'ws', + host: host, + port: 1430, + } + : undefined, + }, +}); +``` + +:::note +不再需要使用 `internal-ip` NPM 包,您可以直接使用 TAURI_DEV_HOST 值替代。 +::: diff --git a/src/content/docs/zh-tw/start/migrate/index.mdx b/src/content/docs/zh-tw/start/migrate/index.mdx new file mode 100644 index 0000000000..a5bcf2c7fa --- /dev/null +++ b/src/content/docs/zh-tw/start/migrate/index.mdx @@ -0,0 +1,23 @@ +--- +title: 更新和迁移 +sidebar: + label: 概要 + order: 10 +--- + +了解從 Tauri 1.0 升級或從其他框架遷移的常見情況和步驟。 + +import { LinkCard, CardGrid } from '@astrojs/starlight/components'; + + + + + diff --git a/src/content/docs/zh-tw/start/prerequisites.mdx b/src/content/docs/zh-tw/start/prerequisites.mdx new file mode 100644 index 0000000000..5601436399 --- /dev/null +++ b/src/content/docs/zh-tw/start/prerequisites.mdx @@ -0,0 +1,411 @@ +--- +title: 前置要求 +i18nReady: true +--- + +import { Tabs, TabItem, Card } from '@astrojs/starlight/components'; + +为了开始使用 Tauri 构建项目,你首先需要安装一些依赖项: + +1. [系统依赖项](#系统依赖项) +2. [Rust](#rust) +3. [移动端配置](#移动端配置) (仅在针对移动设备进行开发时才需要) + +## 系统依赖项 + +点击链接开始配置,适用于你使用的操作系统: + +- [Linux](#linux) (特定发行版请参考下文) +- [macOS Catalina (10.15) 或更新](#macos) +- [Windows 7 或更新](#windows) + +### Linux + +Tauri 在 Linux 上进行开发需要各种系统依赖项。这些可能会有所不同,具体取决于你的发行版,但我们在下面提供了一些流行的发行版来帮助你进行设置。 + + + + +```sh +sudo apt update +sudo apt install libwebkit2gtk-4.1-dev \ + build-essential \ + curl \ + wget \ + file \ + libxdo-dev \ + libssl-dev \ + libayatana-appindicator3-dev \ + librsvg2-dev +``` + + + + +```sh +sudo pacman -Syu +sudo pacman -S --needed \ + webkit2gtk-4.1 \ + base-devel \ + curl \ + wget \ + file \ + openssl \ + appmenu-gtk-module \ + libappindicator-gtk3 \ + librsvg +``` + + + + +```sh +sudo dnf check-update +sudo dnf install webkit2gtk4.1-devel \ + openssl-devel \ + curl \ + wget \ + file \ + libappindicator-gtk3-devel \ + librsvg2-devel +sudo dnf group install "c-development" +``` + + + + +```sh +sudo emerge --ask \ + net-libs/webkit-gtk:4.1 \ + dev-libs/libappindicator \ + net-misc/curl \ + net-misc/wget \ + sys-apps/file +``` + + + + +```sh +sudo zypper up +sudo zypper in webkit2gtk3-devel \ + libopenssl-devel \ + curl \ + wget \ + file \ + libappindicator3-1 \ + librsvg-devel +sudo zypper in -t pattern devel_basis +``` + + + +```sh +sudo apk add \ + build-base \ + webkit2gtk \ + curl \ + wget \ + file \ + openssl \ + libayatana-appindicator-dev \ + librsvg +``` + + + +:::note +这也会为你安装 Rust 和 Node.js 以及 `cargo-tauri` CLI,因此你可以跳过下面的步骤。 +::: + +使用 `nix-shell`: + +```nix +let + pkgs = import { }; +in +pkgs.mkShell { + nativeBuildInputs = with pkgs; [ + pkg-config + gobject-introspection + cargo + cargo-tauri + nodejs + ]; + + buildInputs = with pkgs;[ + at-spi2-atk + atkmm + cairo + gdk-pixbuf + glib + gtk3 + harfbuzz + librsvg + libsoup_3 + pango + webkitgtk_4_1 + openssl + ]; +} +``` + + + + +如果你的发行版未包含在上面,那么你可能需要查阅 [Awesome Tauri on GitHub](https://github.com/tauri-apps/awesome-tauri#guides) 以获知是否已有指南被创建。 + +下一步:[下载并安装 Rust](#rust) + +### macOS + +Tauri 使用 [Xcode](https://developer.apple.com/cn/xcode/resources/) 以及各种 macOS 和 iOS 开发依赖项。 + +从以下位置之一下载并安装 Xcode: + +- [Mac App Store](https://apps.apple.com/cn/app/xcode/id497799835?mt=12) +- [Apple Developer 网站](https://developer.apple.com/cn/xcode/resources/). + +请务必在安装后启动 Xcode,以使它完成设置。 + +
+仅针对桌面目标进行开发? +如果你只打算开发桌面应用程序而不针对 iOS,那么你可以改为安装 Xcode 命令行工具: + +```sh +xcode-select --install +``` + +
+ +下一步:[下载并安装 Rust](#rust) + +### Windows + +Tauri 使用 Microsoft C++ 生成工具进行开发以及 Microsoft Edge WebView2。这两者都是在 Windows 上进行开发所必需的。 + +按照以下步骤安装所需的依赖项。 + +#### Microsoft C++ 生成工具 + +1. 下载 [Microsoft C++ 生成工具](https://visualstudio.microsoft.com/zh-hans/visual-cpp-build-tools/) 安装程序并打开它以开始安装。 +2. 在安装过程中,选中“使用 C++ 的桌面开发”选项。 + +![Visual Studio C++ 生成工具 安装程序 截图](./visual-studio-build-tools-installer.png) + +下一步:[下载并安装 WebView2](#webview2). + +#### WebView2 + +:::tip +WebView 2 已安装在 Windows 10(从版本 1803 开始)和更高版本的 Windows 上。如果你正在这些版本之一上进行开发,则可以跳过此步骤,并直接转到 [下载并安装 Rust](#rust)。 +::: + +Tauri 使用 Microsoft Edge WebView2 在 Windows 上呈现内容。 + +通过访问 [下载 WebView2 运行时](https://developer.microsoft.com/zh-tw/microsoft-edge/webview2/#download) 安装 WebView2。下载并安装“常青独立安装程序(Evergreen Bootstrapper)”。 + +下一步:[下载并安装 Rust](#rust) + +## Rust + +Tauri 使用 [Rust](https://www.rust-lang.org/zh-tw/) 构建并需要它进行开发。使用以下方法之一安装 Rust。你可以在 https://www.rust-lang.org/zh-tw/tools/install 查看更多安装方法。 + + + + +使用 [`rustup`](https://github.com/rust-lang/rustup) 安装: + +```sh +curl --proto '=https' --tlsv1.2 https://sh.rustup.rs -sSf | sh +``` + +:::tip[安全提示] +我们已经审核了这个 bash 脚本,它做了它所说的应该做的事情。尽管如此,在盲目地使用脚本之前,先看一看总是明智的。 + +以下是作为纯文本的脚本文件:[rustup.sh](https://sh.rustup.rs/) +::: + + + + +前往 https://www.rust-lang.org/zh-tw/tools/install 下载 `rustup`。 + +或者,你可以在 PowerShell 中使用 `winget` 安装 rustup: + +```powershell +winget install --id Rustlang.Rustup +``` + +:::caution[默认使用 MSVC 工具链] + +为了完全支持 Tauri 和 [`trunk`](https://trunkrs.dev/) 等工具,请确保在安装程序对话框中的 `default host triple` 选择 MSVC Rust 工具链。根据你的系统,它应该是 `x86_64-pc-windows-msvc`、`i686-pc-windows-msvc` 或 `aarch64-pc-windows-msvc`。 + +如果你已安装 Rust,你可以通过运行以下命令来确保安装正确的工具链: + +```powershell +rustup default stable-msvc +``` + +::: + + + + +**请务必重新启动终端(在某些情况下重新启动系统)以使更改生效。** + +下一步:如果你想要在 Android 或 iOS 上开发应用,前往[移动端配置](#移动端配置)。或者,如果你想使用 JavaScript 前端框架,前往[安装 Node](#nodejs)。否则,前往[创建新项目](/zh-tw/start/create-project/)。 + +## Node.js + +:::note[JavaScript 生态系统] +仅当你打算使用 JavaScript 前端框架时 +::: + +1. 访问 [Node.js 网站](https://nodejs.org/zh-tw),下载并安装长期支持版本(LTS)。 + +2. 运行以下命令以检查 Node 是否成功安装: + +```sh +node -v +# v20.10.0 +npm -v +# 10.2.3 +``` + +重要的是,重新启动终端以确保它能够识别新安装的内容。在某些情况下,您可能需要重新启动计算机。 + +虽然 npm 是 Node.js 的默认包管理器,但你也可以使用其他包管理器,比如 pnpm 或 yarn。如果你想启用这些包管理器,可以在终端中运行 `corepack enable`。这一步是可选的,只有在您想使用 npm 以外的包管理器时才需要。 + +下一步:[移动端配置](#移动端配置)或者[创建新项目](/zh-tw/start/create-project/)。 + +## 移动端配置 + +如果你想将应用适配到 Android 或 iOS,则需要安装一些其他依赖项: + +- [Android](#android) +- [iOS](#ios) + +### Android + +1. 从 Android Developers 网站下载并安装 [Android Studio](https://developer.android.com/studio?hl=zh-tw)。 +2. 设置 `JAVA_HOME` 环境变量: + +{/* TODO: Can this be done in the 4th step? */} + + + + +```sh +export JAVA_HOME=/opt/android-studio/jbr +``` + + + + +```sh +export JAVA_HOME="/Applications/Android Studio.app/Contents/jbr/Contents/Home" +``` + + + + +```ps +[System.Environment]::SetEnvironmentVariable("JAVA_HOME", "C:\Program Files\Android\Android Studio\jbr", "User") +``` + + + +3. 使用 Android Studio 中的 SDK Manager 安装以下内容: + +- Android SDK Platform +- Android SDK Platform-Tools +- NDK (Side by side) +- Android SDK Build-Tools +- Android SDK Command-line Tools + +在 SDK Manager 中选择“Show Package Details”可以安装旧版本软件包。非必要时不要安装旧版本,因为它们可能引入兼容性问题或安全风险。 + +4. 配置 `ANDROID_HOME` 和 `NDK_HOME` 环境变量: + + + + +```sh +export ANDROID_HOME="$HOME/Android/Sdk" +export NDK_HOME="$ANDROID_HOME/ndk/$(ls -1 $ANDROID_HOME/ndk)" +``` + + + + +```sh +export ANDROID_HOME="$HOME/Library/Android/sdk" +export NDK_HOME="$ANDROID_HOME/ndk/$(ls -1 $ANDROID_HOME/ndk)" +``` + + + + +```ps +[System.Environment]::SetEnvironmentVariable("ANDROID_HOME", "$env:LocalAppData\Android\Sdk", "User") +$VERSION = Get-ChildItem -Name "$env:LocalAppData\Android\Sdk\ndk" +[System.Environment]::SetEnvironmentVariable("NDK_HOME", "$env:LocalAppData\Android\Sdk\ndk\$VERSION", "User") +``` + +:::tip +PowerShell 在重新启动或注销之前不会应用新设置的环境变量,但是你可以通过运行以下命令来刷新当前会话窗口: + +```ps +[System.Environment]::GetEnvironmentVariables("User").GetEnumerator() | % { Set-Item -Path "Env:\$($_.key)" -Value $_.value } +``` + +::: + + + + + +5. 使用 `rustup` 新增 Android 编译目标: + +```sh +rustup target add aarch64-linux-android armv7-linux-androideabi i686-linux-android x86_64-linux-android +``` + +下一步:[配置 iOS](#ios)或[创建新项目](/zh-tw/start/create-project/)。 + +### iOS + +:::caution[仅 macOS] +iOS 开发需要 Xcode,并且仅在 macOS 上可用。确保你在 [macOS 系统依赖项部分](#macos)中安装了 Xcode 而不是 Xcode 命令行工具。 +::: + +1. 在终端中使用 `rustup` 将 iOS 新增为编译目标: + +```sh +rustup target add aarch64-apple-ios x86_64-apple-ios aarch64-apple-ios-sim +``` + +2. 安装 [Homebrew](https://brew.sh/zh-tw/): + +```sh +/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" +``` + +3. 使用 Homebrew 安装 [Cocoapods](https://cocoapods.org): + +```sh +brew install cocoapods +``` + +下一步:[创建新项目](/zh-tw/start/create-project/)。 + +## 故障排除 + +如果你在安装过程中遇到任何问题,请务必查看[故障诊断指南](/zh-tw/develop/debug/)或联系 [Tauri Discord](https://discord.com/invite/tauri) 以寻求帮助。 + + + +现在,你已经安装了所有前置要求,你可以准备好[创建你的第一个 Tauri 应用程序](/zh-tw/start/create-project/)! + + diff --git a/src/content/docs/zh-tw/start/visual-studio-build-tools-installer.png b/src/content/docs/zh-tw/start/visual-studio-build-tools-installer.png new file mode 100644 index 0000000000..75f7f8745d Binary files /dev/null and b/src/content/docs/zh-tw/start/visual-studio-build-tools-installer.png differ diff --git a/src/styles/custom.scss b/src/styles/custom.scss index c2e43fd617..a48d109551 100644 --- a/src/styles/custom.scss +++ b/src/styles/custom.scss @@ -50,7 +50,8 @@ z-index: -1; opacity: 0.7; overflow: hidden; - background: linear-gradient(-90deg, var(--sl-color-gray-6) 1px, transparent 1px), + background: + linear-gradient(-90deg, var(--sl-color-gray-6) 1px, transparent 1px), linear-gradient(var(--sl-color-gray-6) 1px, transparent 1px), linear-gradient(-90deg, var(--sl-color-gray-6) 1px, transparent 1px), linear-gradient(var(--sl-color-gray-6) 1px, transparent 1px), @@ -118,7 +119,8 @@ z-index: -1; opacity: 0.4; overflow: hidden; - background: linear-gradient(-90deg, var(--sl-color-gray-4) 1px, transparent 1px), + background: + linear-gradient(-90deg, var(--sl-color-gray-4) 1px, transparent 1px), linear-gradient(var(--sl-color-gray-4) 1px, transparent 1px), linear-gradient(-90deg, var(--sl-color-gray-4) 1px, transparent 1px), linear-gradient(var(--sl-color-gray-4) 1px, transparent 1px),