diff --git a/plugins/ztooldeveloperbox/.gitignore b/plugins/ztooldeveloperbox/.gitignore
new file mode 100644
index 00000000..a547bf36
--- /dev/null
+++ b/plugins/ztooldeveloperbox/.gitignore
@@ -0,0 +1,24 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+node_modules
+dist
+dist-ssr
+*.local
+
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+.idea
+.DS_Store
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
diff --git a/plugins/ztooldeveloperbox/README.md b/plugins/ztooldeveloperbox/README.md
new file mode 100644
index 00000000..9b88193e
--- /dev/null
+++ b/plugins/ztooldeveloperbox/README.md
@@ -0,0 +1,281 @@
+# {{PLUGIN_NAME}}
+
+> {{DESCRIPTION}}
+
+这是一个使用 **Vue 3 + Vite + TypeScript** 构建的 ZTools 插件。
+
+## ✨ 功能特性
+
+### 📌 已包含的示例功能
+
+- **Hello** - 基础功能指令示例
+ - 触发指令:`你好` / `hello`
+ - 展示简单的 Vue 组件界面
+
+- **读文件** - 文件读取功能示例
+ - 功能指令:`读文件`
+ - 匹配指令:支持拖拽文件触发
+ - 演示如何使用 Node.js 能力读取文件内容
+
+- **保存为文件** - 文件写入功能示例
+ - 匹配指令:任意文本/图片 → `保存为文件`
+ - 演示如何将剪贴板内容保存为文件
+
+## 📁 项目结构
+
+```
+.
+├── public/
+│ ├── logo.png # 插件图标
+│ ├── plugin.json # 插件配置文件
+│ └── preload/ # Preload 脚本目录
+│ ├── package.json # Preload 依赖配置
+│ └── services.js # Node.js 能力扩展
+├── src/
+│ ├── main.ts # 入口文件
+│ ├── main.css # 全局样式
+│ ├── App.vue # 根组件
+│ ├── env.d.ts # 类型声明
+│ ├── Hello/ # Hello 功能组件
+│ │ └── index.vue
+│ ├── Read/ # 读文件功能组件
+│ │ └── index.vue
+│ └── Write/ # 写文件功能组件
+│ └── index.vue
+├── index.html # HTML 模板
+├── vite.config.js # Vite 配置
+├── tsconfig.json # TypeScript 配置
+├── package.json # 项目依赖
+└── README.md # 项目文档
+```
+
+## 🚀 快速开始
+
+### 安装依赖
+
+```bash
+npm install
+```
+
+### 开发模式
+
+```bash
+npm run dev
+```
+
+开发服务器将在 `http://localhost:5173` 启动。ZTools 会自动加载开发版本。
+
+### 构建生产版本
+
+```bash
+npm run build
+```
+
+构建产物将输出到 `dist/` 目录。
+
+## 📖 开发指南
+
+### 1. 修改插件配置
+
+编辑 `public/plugin.json` 文件:
+
+```json
+{
+ "name": "你的插件名称",
+ "description": "插件描述",
+ "author": "作者名称",
+ "version": "1.0.0",
+ "features": [
+ // 添加你的功能配置
+ ]
+}
+```
+
+### 2. 创建新功能
+
+#### 步骤 1: 创建 Vue 组件
+
+在 `src/` 目录下创建新的功能组件:
+
+```vue
+
+
+
+
{{ title }}
+
+
+
+
+
+
+
+```
+
+#### 步骤 2: 注册路由
+
+在 `src/App.vue` 中添加路由:
+
+```vue
+
+```
+
+#### 步骤 3: 配置功能
+
+在 `plugin.json` 中添加功能配置:
+
+```json
+{
+ "code": "myfeature",
+ "explain": "我的新功能",
+ "icon": "logo.png",
+ "cmds": ["触发指令"]
+}
+```
+
+### 3. 使用 Node.js 能力
+
+#### 扩展 Preload 服务
+
+编辑 `public/preload/services.js`:
+
+```javascript
+const fs = require('fs')
+const path = require('path')
+
+module.exports = {
+ // 示例:读取文件
+ readFile: (filePath) => {
+ return fs.readFileSync(filePath, 'utf-8')
+ },
+
+ // 添加你的服务
+ myService: (params) => {
+ // 实现你的逻辑
+ return result
+ }
+}
+```
+
+#### 在 Vue 组件中调用
+
+```vue
+
+```
+
+### 4. 使用 ZTools API
+
+```vue
+
+```
+
+## 🎨 样式开发
+
+### 使用 CSS 变量
+
+ZTools 提供了一套 CSS 变量用于主题适配:
+
+```css
+.my-component {
+ background: var(--bg-color);
+ color: var(--text-color);
+ border: 1px solid var(--border-color);
+}
+```
+
+### 暗色模式支持
+
+```css
+@media (prefers-color-scheme: dark) {
+ .my-component {
+ /* 暗色模式样式 */
+ }
+}
+```
+
+## 📦 构建与发布
+
+### 1. 构建插件
+
+```bash
+npm run build
+```
+
+### 2. 测试构建产物
+
+将 `dist/` 目录中的所有文件复制到 ZTools 插件目录进行测试。
+
+### 3. 发布到插件市场
+
+1. 确保 `plugin.json` 中的信息完整准确
+2. 准备好插件截图和详细说明
+3. 访问 ZTools 插件市场提交插件
+
+## 📚 相关资源
+
+- [ZTools 官方文档](https://github.com/ztool-center/ztools)
+- [ZTools API 文档](https://github.com/ztool-center/ztools-api-types)
+- [Vue 3 文档](https://vuejs.org/)
+- [Vite 文档](https://vitejs.dev/)
+
+## ❓ 常见问题
+
+### Q: 如何调试插件?
+
+A: 使用 `npm run dev` 启动开发服务器,在插件界面中点击插件头像图标,在弹出的菜单中选择"打开开发者工具"进行调试。
+
+### Q: 如何访问 Node.js 能力?
+
+A: 通过 `public/preload/services.js` 文件扩展服务,然后在组件中使用 `window.services` 调用。
+
+### Q: 插件图标不显示?
+
+A: 确保 `public/logo.png` 文件存在,且在 `plugin.json` 中正确配置了 `logo` 字段。
+
+### Q: 如何处理大文件上传?
+
+A: 建议使用 Node.js 流式处理,在 preload 脚本中实现文件分块处理逻辑。
+
+## 📄 开源协议
+
+MIT License
+
+---
+
+**祝你开发愉快!** 🎉
diff --git a/plugins/ztooldeveloperbox/index.html b/plugins/ztooldeveloperbox/index.html
new file mode 100644
index 00000000..eaa17316
--- /dev/null
+++ b/plugins/ztooldeveloperbox/index.html
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/plugins/ztooldeveloperbox/package-lock.json b/plugins/ztooldeveloperbox/package-lock.json
new file mode 100644
index 00000000..3a1807aa
--- /dev/null
+++ b/plugins/ztooldeveloperbox/package-lock.json
@@ -0,0 +1,1512 @@
+{
+ "name": "ztooldeveloperbox",
+ "version": "1.0.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "ztooldeveloperbox",
+ "version": "1.0.0",
+ "dependencies": {
+ "vue": "^3.5.13"
+ },
+ "devDependencies": {
+ "@vitejs/plugin-vue": "^5.2.1",
+ "@ztools-center/ztools-api-types": "^1.0.1",
+ "typescript": "^5.3.0",
+ "vite": "^6.0.11",
+ "vue-tsc": "^2.0.0"
+ }
+ },
+ "node_modules/@babel/helper-string-parser": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz",
+ "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-identifier": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz",
+ "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/parser": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.7.tgz",
+ "integrity": "sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.29.7"
+ },
+ "bin": {
+ "parser": "bin/babel-parser.js"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/types": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.7.tgz",
+ "integrity": "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-string-parser": "^7.29.7",
+ "@babel/helper-validator-identifier": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@esbuild/aix-ppc64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz",
+ "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "aix"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-arm": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz",
+ "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz",
+ "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz",
+ "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/darwin-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz",
+ "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/darwin-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz",
+ "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/freebsd-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz",
+ "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/freebsd-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz",
+ "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-arm": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz",
+ "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz",
+ "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-ia32": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz",
+ "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-loong64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz",
+ "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-mips64el": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz",
+ "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==",
+ "cpu": [
+ "mips64el"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-ppc64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz",
+ "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-riscv64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz",
+ "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-s390x": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz",
+ "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz",
+ "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/netbsd-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz",
+ "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/netbsd-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz",
+ "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openbsd-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz",
+ "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openbsd-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz",
+ "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openharmony-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz",
+ "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openharmony"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/sunos-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz",
+ "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-arm64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz",
+ "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-ia32": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz",
+ "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-x64": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz",
+ "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.5.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
+ "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
+ "license": "MIT"
+ },
+ "node_modules/@rollup/rollup-android-arm-eabi": {
+ "version": "4.62.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.62.2.tgz",
+ "integrity": "sha512-6o7ZLZK+BeenkZCFNDXqpbjw9bD6nuWonvS/lwQJp7NoVVxm6p3qE7qQ5jGuBjiFsgvqjD8mZAU5oWxTmbOeOg==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@rollup/rollup-android-arm64": {
+ "version": "4.62.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.62.2.tgz",
+ "integrity": "sha512-BaH7BllCACHoH1LguOU56UItGfUWjujlO65kS9LAodViaN4bwIKd7oeW/ZHJ/4ljr/7MIiENnNy3HJ0zXv8Zkw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@rollup/rollup-darwin-arm64": {
+ "version": "4.62.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.62.2.tgz",
+ "integrity": "sha512-v39RCCvj4He82I9sFmk+M1VZ0PLM9sfsLVikjfx2hYBNALhrrOR2D3JjQA6AhlaSOgcR+RzrKY7e1+bT6SUO/A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@rollup/rollup-darwin-x64": {
+ "version": "4.62.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.62.2.tgz",
+ "integrity": "sha512-yl0y2vq3S3lHeuXhEdss6TWfKW8vkujImO12tn4ZkG/4oghr09LvdYm2RElVjokTQiUvDUGXLGsYeLqUMCKpGA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@rollup/rollup-freebsd-arm64": {
+ "version": "4.62.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.62.2.tgz",
+ "integrity": "sha512-tT4pvt4qXD+vEoezupCWi+a1F0vvDiksiHc+PxRlYTOH1I6/X4id9jPxTP+Fg+545euaFT1jJVs4CEdHZAU1vw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ]
+ },
+ "node_modules/@rollup/rollup-freebsd-x64": {
+ "version": "4.62.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.62.2.tgz",
+ "integrity": "sha512-6nU5F2wCW+qvCBhTn1pdIU3bzsIoF7EUwsCDRxilWGprQR6yd508YnH9+OKFCwpfS8pjZqDUmnCAr7exax0XCg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
+ "version": "4.62.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.62.2.tgz",
+ "integrity": "sha512-n1GJHPOvpIfhi3TmrCeh6S6URt9BFCt0KQE3qvexyGCTAKpR4Lg+eWvNZEqu7epxwus/8ElT3hacYEucm49SZg==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm-musleabihf": {
+ "version": "4.62.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.62.2.tgz",
+ "integrity": "sha512-JqgflS8wEB+UXV/vS1RpRbifGBeN4D5lz8D8oOFbFZw4vedvdOgCFAjfBmIMdW3yL10XpQQ0Ambepw6MXrhOnA==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm64-gnu": {
+ "version": "4.62.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.62.2.tgz",
+ "integrity": "sha512-wnFJkogWvN4jm/hQRF2UBaeUmk20j5+DmHvoyWii2b8HJDyvz1MF2OU/6ynXt2KR63rbZLWkFpoytpdc/yBuSA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm64-musl": {
+ "version": "4.62.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.62.2.tgz",
+ "integrity": "sha512-HVu2bp0zhvJ8xHEV9+UUs7S90VadmBSY3LcIMvozbPo4AuMGDWlz3ymHLHZPX4hR67TKTt8Qp5PJ5RBg/i+RMQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-loong64-gnu": {
+ "version": "4.62.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.62.2.tgz",
+ "integrity": "sha512-mQqqAV8QaoSgr9I2fKDLY2BAVvmKjWoGiu/cSYQonsLvtqwEn1E4QYfnCOcp5zoEqNhsDYin1s6jx/VJmrxlZg==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-loong64-musl": {
+ "version": "4.62.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.62.2.tgz",
+ "integrity": "sha512-IxKLoxCQ2IWi6bT2akyDUBGsOImDKB+sPp4EsTmwFQ/fMwpCKm8uLSSgP/Kx/QYUgKis6SEZ5/Nlhup0DIA0PQ==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-ppc64-gnu": {
+ "version": "4.62.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.62.2.tgz",
+ "integrity": "sha512-Mk5ha2RQSgyFfmYYLkBpPnUk8D8FriBxesO1u9O75X0mHgXL1UQcH5Itl2lurWL2tj0RxV9b9tJgipac0hRY9A==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-ppc64-musl": {
+ "version": "4.62.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.62.2.tgz",
+ "integrity": "sha512-CjvEnqJL/0/TQ3TXX3OPIJ/kmBellrWd4heXUmHeJlTnmwjKpSJzoehLaL6Xk0ZnMHBu9dZuFADNOrtjF4v+2w==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-riscv64-gnu": {
+ "version": "4.62.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.62.2.tgz",
+ "integrity": "sha512-1SiZbzwdkaDURsew/tSOrooKiYy7EQGT6m8ufavAi9NEyQb/6VuIxFXAL1fqa4iZe3g4NbNk4P7J32z2tw5Mgg==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-riscv64-musl": {
+ "version": "4.62.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.62.2.tgz",
+ "integrity": "sha512-nQts12zJ3NQRoE6uYljOH89v7szzLDvG2JD/vsX+vGXU8w/At1GowTZ5/7qeFQ8m7L55rpR8Okugnuo5bgjy2Q==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-s390x-gnu": {
+ "version": "4.62.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.62.2.tgz",
+ "integrity": "sha512-E9/ll019jhPIJgpzfZoIkBGhcz+kKNgVWYRY0zr9srBdPPFVpvOKW8VaJKUbeK+eZXyQF9ltME+Kk6affeaPgg==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-x64-gnu": {
+ "version": "4.62.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.62.2.tgz",
+ "integrity": "sha512-5BqxR/pshjey51iliyzTD5Xi3EN0aLmQ2lZ3lvefVV9c82BvrLo2/6OT55iifpWBufs6kdwWbuOKS841DrmK9A==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-x64-musl": {
+ "version": "4.62.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.62.2.tgz",
+ "integrity": "sha512-uNN83XxQrRAh/w0/pmAfibcwyb6YWt4gP+dpnQKPVJshAloQ785ii8CT8ZCIxkGg9opVsvAlGhFitSm6D1Jjpg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-openbsd-x64": {
+ "version": "4.62.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.62.2.tgz",
+ "integrity": "sha512-srjEIxSH3LRnJN6THczDHWQplqEMFiAJrTab0msUryh9kwNpkICf3Ea6q6MN/2cZwRFUNx5w+h6Hpi4QuHS6Zg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ]
+ },
+ "node_modules/@rollup/rollup-openharmony-arm64": {
+ "version": "4.62.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.62.2.tgz",
+ "integrity": "sha512-8hOJnxgbyObnCm5AlRA3A931xX19xq80RjVTKgJOvEKWqJruP/Uf12IbAOaDjjEXYRewwHLfmF0YRIdK3OwKWA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openharmony"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-arm64-msvc": {
+ "version": "4.62.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.62.2.tgz",
+ "integrity": "sha512-mmF4AY1i0hG/bLWUctUq59gtmgaSIRa3cu/A3JFRp/sCNEme2bgDEiDS22P9FbnJB8NJNF4jPJiSP5RHQpUTDg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-ia32-msvc": {
+ "version": "4.62.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.62.2.tgz",
+ "integrity": "sha512-DZgkknc6jhHrk46V25vbAM0zZkyP0nSDkJB8/dRkLTxv470dOmWDqGoEJl/9A0dFfS7yE3REOwNDxpHwSLSt0Q==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-x64-gnu": {
+ "version": "4.62.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.62.2.tgz",
+ "integrity": "sha512-T6xr6ucWSFto+VGajA8YH26LdpHRuP4YLHEKAtCWvJDOlnmWcDZVCI2Jmjr+IFHDlt2zRaTAKE4tfjTaWLgJBg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-x64-msvc": {
+ "version": "4.62.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.62.2.tgz",
+ "integrity": "sha512-BfzEnDJOt9T8M989/lA37EcJgat01wLRnoi5dQf3QzOH7jzpqTAzdDbVfRljVr5r+jzKqpbHeyOfAaXxAd0PAA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@types/estree": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz",
+ "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@vitejs/plugin-vue": {
+ "version": "5.2.4",
+ "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.2.4.tgz",
+ "integrity": "sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.0.0 || >=20.0.0"
+ },
+ "peerDependencies": {
+ "vite": "^5.0.0 || ^6.0.0",
+ "vue": "^3.2.25"
+ }
+ },
+ "node_modules/@volar/language-core": {
+ "version": "2.4.15",
+ "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-2.4.15.tgz",
+ "integrity": "sha512-3VHw+QZU0ZG9IuQmzT68IyN4hZNd9GchGPhbD9+pa8CVv7rnoOZwo7T8weIbrRmihqy3ATpdfXFnqRrfPVK6CA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@volar/source-map": "2.4.15"
+ }
+ },
+ "node_modules/@volar/source-map": {
+ "version": "2.4.15",
+ "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-2.4.15.tgz",
+ "integrity": "sha512-CPbMWlUN6hVZJYGcU/GSoHu4EnCHiLaXI9n8c9la6RaI9W5JHX+NqG+GSQcB0JdC2FIBLdZJwGsfKyBB71VlTg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@volar/typescript": {
+ "version": "2.4.15",
+ "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-2.4.15.tgz",
+ "integrity": "sha512-2aZ8i0cqPGjXb4BhkMsPYDkkuc2ZQ6yOpqwAuNwUoncELqoy5fRgOQtLR9gB0g902iS0NAkvpIzs27geVyVdPg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@volar/language-core": "2.4.15",
+ "path-browserify": "^1.0.1",
+ "vscode-uri": "^3.0.8"
+ }
+ },
+ "node_modules/@vue/compiler-core": {
+ "version": "3.5.38",
+ "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.38.tgz",
+ "integrity": "sha512-s99aGxWYig9ErHbct27KXEGhrBYlRI6c4MwAgXErOAbX9xiW37/uMa+XUDO69zLz83dng8UUZ70CTOJrLrYrEQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.29.7",
+ "@vue/shared": "3.5.38",
+ "entities": "^7.0.1",
+ "estree-walker": "^2.0.2",
+ "source-map-js": "^1.2.1"
+ }
+ },
+ "node_modules/@vue/compiler-dom": {
+ "version": "3.5.38",
+ "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.38.tgz",
+ "integrity": "sha512-JTqp25l8aFfJYF7/KmsXZjAxJz7T+SjmTJLoXVjHtc2BrSgSiW2n9Aem/cWq1OPe68A8JL06B3eVdhlP0H4TVw==",
+ "license": "MIT",
+ "dependencies": {
+ "@vue/compiler-core": "3.5.38",
+ "@vue/shared": "3.5.38"
+ }
+ },
+ "node_modules/@vue/compiler-sfc": {
+ "version": "3.5.38",
+ "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.38.tgz",
+ "integrity": "sha512-DuA2GiZawSEW442iw/9+Fkol8hTgb4Ke5KkhmSry65QA7YuyMbIdy8p0XZRMvNwJdgRz307W8g1CSzdvS4nuNg==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.29.7",
+ "@vue/compiler-core": "3.5.38",
+ "@vue/compiler-dom": "3.5.38",
+ "@vue/compiler-ssr": "3.5.38",
+ "@vue/shared": "3.5.38",
+ "estree-walker": "^2.0.2",
+ "magic-string": "^0.30.21",
+ "postcss": "^8.5.15",
+ "source-map-js": "^1.2.1"
+ }
+ },
+ "node_modules/@vue/compiler-ssr": {
+ "version": "3.5.38",
+ "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.38.tgz",
+ "integrity": "sha512-7s+W5Gc42FGxZMcuwl8H5B29T8BJPMdBT7KHFE+BbAuZ/iTEdTtv7z2XiMjiaUUw4w3ZcCEdHs36RuYJ2VA7bA==",
+ "license": "MIT",
+ "dependencies": {
+ "@vue/compiler-dom": "3.5.38",
+ "@vue/shared": "3.5.38"
+ }
+ },
+ "node_modules/@vue/compiler-vue2": {
+ "version": "2.7.16",
+ "resolved": "https://registry.npmjs.org/@vue/compiler-vue2/-/compiler-vue2-2.7.16.tgz",
+ "integrity": "sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "de-indent": "^1.0.2",
+ "he": "^1.2.0"
+ }
+ },
+ "node_modules/@vue/language-core": {
+ "version": "2.2.12",
+ "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-2.2.12.tgz",
+ "integrity": "sha512-IsGljWbKGU1MZpBPN+BvPAdr55YPkj2nB/TBNGNC32Vy2qLG25DYu/NBN2vNtZqdRbTRjaoYrahLrToim2NanA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@volar/language-core": "2.4.15",
+ "@vue/compiler-dom": "^3.5.0",
+ "@vue/compiler-vue2": "^2.7.16",
+ "@vue/shared": "^3.5.0",
+ "alien-signals": "^1.0.3",
+ "minimatch": "^9.0.3",
+ "muggle-string": "^0.4.1",
+ "path-browserify": "^1.0.1"
+ },
+ "peerDependencies": {
+ "typescript": "*"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@vue/reactivity": {
+ "version": "3.5.38",
+ "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.38.tgz",
+ "integrity": "sha512-pG6LV/NDNRbKizcUjFFLAfjaL8mcv4DmR9avNcUw2gDHBzZneuS2TWCmp633ynzxz9YYKNeEPK2I8Wraqy2HUQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@vue/shared": "3.5.38"
+ }
+ },
+ "node_modules/@vue/runtime-core": {
+ "version": "3.5.38",
+ "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.38.tgz",
+ "integrity": "sha512-iyW8WVfF1CpCXxncZY5Ei6rSd6oZr5DgEom//fUjRBRl56AXPD+s9ATvukRt77ZFTuYlnVA1bxY+dJB94tWVYw==",
+ "license": "MIT",
+ "dependencies": {
+ "@vue/reactivity": "3.5.38",
+ "@vue/shared": "3.5.38"
+ }
+ },
+ "node_modules/@vue/runtime-dom": {
+ "version": "3.5.38",
+ "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.38.tgz",
+ "integrity": "sha512-apX2wt9sdfDshS+a2xueFZLVpt0GkRJZSoPmrW/SA4yzXTznhfcMVW59gr7h4YQeY0vJhdJkk2rsIDwgfFgC5A==",
+ "license": "MIT",
+ "dependencies": {
+ "@vue/reactivity": "3.5.38",
+ "@vue/runtime-core": "3.5.38",
+ "@vue/shared": "3.5.38",
+ "csstype": "^3.2.3"
+ }
+ },
+ "node_modules/@vue/server-renderer": {
+ "version": "3.5.38",
+ "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.38.tgz",
+ "integrity": "sha512-vue8vbf2QlV4quHqzwmJy6dWfmRhP1J8l4wtZg60CL6VoKqcPY2oe7may3+1d9qfpedjK5PRLFqd5k3Isj9mUw==",
+ "license": "MIT",
+ "dependencies": {
+ "@vue/compiler-ssr": "3.5.38",
+ "@vue/shared": "3.5.38"
+ },
+ "peerDependencies": {
+ "vue": "3.5.38"
+ }
+ },
+ "node_modules/@vue/shared": {
+ "version": "3.5.38",
+ "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.38.tgz",
+ "integrity": "sha512-FTW0AFZNaK5/mOqvGBwVfUlNLU38TiQn4+DQgIFUnrBBJQ1crMJ82yeGQLV5jyKFsO8yRukpbuP7x+nRbH6aug==",
+ "license": "MIT"
+ },
+ "node_modules/@ztools-center/ztools-api-types": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@ztools-center/ztools-api-types/-/ztools-api-types-1.0.3.tgz",
+ "integrity": "sha512-dv1eOAIasAupqKaQL/gESk1i2+RebdM/1gvZhrvH2D/bo3enCUsAGJ8nrHnlCLBSOGB81eC/SU0IH8BNsUlmvA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/alien-signals": {
+ "version": "1.0.13",
+ "resolved": "https://registry.npmjs.org/alien-signals/-/alien-signals-1.0.13.tgz",
+ "integrity": "sha512-OGj9yyTnJEttvzhTUWuscOvtqxq5vrhF7vL9oS0xJ2mK0ItPYP1/y+vCFebfxoEyAz0++1AIwJ5CMr+Fk3nDmg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/brace-expansion": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.1.tgz",
+ "integrity": "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/csstype": {
+ "version": "3.2.3",
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
+ "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
+ "license": "MIT"
+ },
+ "node_modules/de-indent": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz",
+ "integrity": "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/entities": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz",
+ "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==",
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=0.12"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/entities?sponsor=1"
+ }
+ },
+ "node_modules/esbuild": {
+ "version": "0.25.12",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz",
+ "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "optionalDependencies": {
+ "@esbuild/aix-ppc64": "0.25.12",
+ "@esbuild/android-arm": "0.25.12",
+ "@esbuild/android-arm64": "0.25.12",
+ "@esbuild/android-x64": "0.25.12",
+ "@esbuild/darwin-arm64": "0.25.12",
+ "@esbuild/darwin-x64": "0.25.12",
+ "@esbuild/freebsd-arm64": "0.25.12",
+ "@esbuild/freebsd-x64": "0.25.12",
+ "@esbuild/linux-arm": "0.25.12",
+ "@esbuild/linux-arm64": "0.25.12",
+ "@esbuild/linux-ia32": "0.25.12",
+ "@esbuild/linux-loong64": "0.25.12",
+ "@esbuild/linux-mips64el": "0.25.12",
+ "@esbuild/linux-ppc64": "0.25.12",
+ "@esbuild/linux-riscv64": "0.25.12",
+ "@esbuild/linux-s390x": "0.25.12",
+ "@esbuild/linux-x64": "0.25.12",
+ "@esbuild/netbsd-arm64": "0.25.12",
+ "@esbuild/netbsd-x64": "0.25.12",
+ "@esbuild/openbsd-arm64": "0.25.12",
+ "@esbuild/openbsd-x64": "0.25.12",
+ "@esbuild/openharmony-arm64": "0.25.12",
+ "@esbuild/sunos-x64": "0.25.12",
+ "@esbuild/win32-arm64": "0.25.12",
+ "@esbuild/win32-ia32": "0.25.12",
+ "@esbuild/win32-x64": "0.25.12"
+ }
+ },
+ "node_modules/estree-walker": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
+ "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
+ "license": "MIT"
+ },
+ "node_modules/fdir": {
+ "version": "6.5.0",
+ "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
+ "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "peerDependencies": {
+ "picomatch": "^3 || ^4"
+ },
+ "peerDependenciesMeta": {
+ "picomatch": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/he": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
+ "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "he": "bin/he"
+ }
+ },
+ "node_modules/magic-string": {
+ "version": "0.30.21",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
+ "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.5.5"
+ }
+ },
+ "node_modules/minimatch": {
+ "version": "9.0.9",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz",
+ "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/muggle-string": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/muggle-string/-/muggle-string-0.4.1.tgz",
+ "integrity": "sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/nanoid": {
+ "version": "3.3.15",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.15.tgz",
+ "integrity": "sha512-y7Wygv/7mEOvxTuEQDB8StXdMRBWf1kR/tlhAzBRUFkB2jfcLOAxO/SHmOO2zgz1pVgK29/kyupn059/bCHdjA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
+ "engines": {
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ }
+ },
+ "node_modules/path-browserify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz",
+ "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/picocolors": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
+ "license": "ISC"
+ },
+ "node_modules/picomatch": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
+ "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/postcss": {
+ "version": "8.5.15",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz",
+ "integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "nanoid": "^3.3.12",
+ "picocolors": "^1.1.1",
+ "source-map-js": "^1.2.1"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
+ "node_modules/rollup": {
+ "version": "4.62.2",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.62.2.tgz",
+ "integrity": "sha512-RFnrW4lhXA3s3eqHDZvN654g8OTjzRfqpIRJYczCGB6HzphckVAi/Qh4tbPUbRuDi7s1Llv8g/NspLkttY3gTA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "1.0.9"
+ },
+ "bin": {
+ "rollup": "dist/bin/rollup"
+ },
+ "engines": {
+ "node": ">=18.0.0",
+ "npm": ">=8.0.0"
+ },
+ "optionalDependencies": {
+ "@rollup/rollup-android-arm-eabi": "4.62.2",
+ "@rollup/rollup-android-arm64": "4.62.2",
+ "@rollup/rollup-darwin-arm64": "4.62.2",
+ "@rollup/rollup-darwin-x64": "4.62.2",
+ "@rollup/rollup-freebsd-arm64": "4.62.2",
+ "@rollup/rollup-freebsd-x64": "4.62.2",
+ "@rollup/rollup-linux-arm-gnueabihf": "4.62.2",
+ "@rollup/rollup-linux-arm-musleabihf": "4.62.2",
+ "@rollup/rollup-linux-arm64-gnu": "4.62.2",
+ "@rollup/rollup-linux-arm64-musl": "4.62.2",
+ "@rollup/rollup-linux-loong64-gnu": "4.62.2",
+ "@rollup/rollup-linux-loong64-musl": "4.62.2",
+ "@rollup/rollup-linux-ppc64-gnu": "4.62.2",
+ "@rollup/rollup-linux-ppc64-musl": "4.62.2",
+ "@rollup/rollup-linux-riscv64-gnu": "4.62.2",
+ "@rollup/rollup-linux-riscv64-musl": "4.62.2",
+ "@rollup/rollup-linux-s390x-gnu": "4.62.2",
+ "@rollup/rollup-linux-x64-gnu": "4.62.2",
+ "@rollup/rollup-linux-x64-musl": "4.62.2",
+ "@rollup/rollup-openbsd-x64": "4.62.2",
+ "@rollup/rollup-openharmony-arm64": "4.62.2",
+ "@rollup/rollup-win32-arm64-msvc": "4.62.2",
+ "@rollup/rollup-win32-ia32-msvc": "4.62.2",
+ "@rollup/rollup-win32-x64-gnu": "4.62.2",
+ "@rollup/rollup-win32-x64-msvc": "4.62.2",
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/source-map-js": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
+ "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/tinyglobby": {
+ "version": "0.2.17",
+ "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz",
+ "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fdir": "^6.5.0",
+ "picomatch": "^4.0.4"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/SuperchupuDev"
+ }
+ },
+ "node_modules/typescript": {
+ "version": "5.9.3",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
+ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
+ "devOptional": true,
+ "license": "Apache-2.0",
+ "peer": true,
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=14.17"
+ }
+ },
+ "node_modules/vite": {
+ "version": "6.4.3",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.3.tgz",
+ "integrity": "sha512-NTKlcQjlAK7MlQoyb6LgaqHc8sso/pVyUJYWMws3jg21uTJw/LddqIFPcPqP6PzpgbIcZyKI85sFE4HBrQDA8A==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "esbuild": "^0.25.0",
+ "fdir": "^6.4.4",
+ "picomatch": "^4.0.2",
+ "postcss": "^8.5.3",
+ "rollup": "^4.34.9",
+ "tinyglobby": "^0.2.13"
+ },
+ "bin": {
+ "vite": "bin/vite.js"
+ },
+ "engines": {
+ "node": "^18.0.0 || ^20.0.0 || >=22.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/vitejs/vite?sponsor=1"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.3"
+ },
+ "peerDependencies": {
+ "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0",
+ "jiti": ">=1.21.0",
+ "less": "*",
+ "lightningcss": "^1.21.0",
+ "sass": "*",
+ "sass-embedded": "*",
+ "stylus": "*",
+ "sugarss": "*",
+ "terser": "^5.16.0",
+ "tsx": "^4.8.1",
+ "yaml": "^2.4.2"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ },
+ "jiti": {
+ "optional": true
+ },
+ "less": {
+ "optional": true
+ },
+ "lightningcss": {
+ "optional": true
+ },
+ "sass": {
+ "optional": true
+ },
+ "sass-embedded": {
+ "optional": true
+ },
+ "stylus": {
+ "optional": true
+ },
+ "sugarss": {
+ "optional": true
+ },
+ "terser": {
+ "optional": true
+ },
+ "tsx": {
+ "optional": true
+ },
+ "yaml": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/vscode-uri": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.1.0.tgz",
+ "integrity": "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/vue": {
+ "version": "3.5.38",
+ "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.38.tgz",
+ "integrity": "sha512-vAMKHfImQlYSy0C+PBue4s3ERZ2xGKfgZg5GXAsLInq1dyh2H78ILVP5sK0KPFPVW4kv+OGCIvBEondcjpZp7A==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@vue/compiler-dom": "3.5.38",
+ "@vue/compiler-sfc": "3.5.38",
+ "@vue/runtime-dom": "3.5.38",
+ "@vue/server-renderer": "3.5.38",
+ "@vue/shared": "3.5.38"
+ },
+ "peerDependencies": {
+ "typescript": "*"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/vue-tsc": {
+ "version": "2.2.12",
+ "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-2.2.12.tgz",
+ "integrity": "sha512-P7OP77b2h/Pmk+lZdJ0YWs+5tJ6J2+uOQPo7tlBnY44QqQSPYvS0qVT4wqDJgwrZaLe47etJLLQRFia71GYITw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@volar/typescript": "2.4.15",
+ "@vue/language-core": "2.2.12"
+ },
+ "bin": {
+ "vue-tsc": "bin/vue-tsc.js"
+ },
+ "peerDependencies": {
+ "typescript": ">=5.0.0"
+ }
+ }
+ }
+}
diff --git a/plugins/ztooldeveloperbox/package.json b/plugins/ztooldeveloperbox/package.json
new file mode 100644
index 00000000..0d59d72f
--- /dev/null
+++ b/plugins/ztooldeveloperbox/package.json
@@ -0,0 +1,20 @@
+{
+ "name": "ztooldeveloperbox",
+ "version": "1.0.0",
+ "description": "开发工具箱",
+ "type": "module",
+ "scripts": {
+ "dev": "vite",
+ "build": "vue-tsc && vite build"
+ },
+ "dependencies": {
+ "vue": "^3.5.13"
+ },
+ "devDependencies": {
+ "@vitejs/plugin-vue": "^5.2.1",
+ "@ztools-center/ztools-api-types": "^1.0.1",
+ "typescript": "^5.3.0",
+ "vite": "^6.0.11",
+ "vue-tsc": "^2.0.0"
+ }
+}
diff --git a/plugins/ztooldeveloperbox/public/logo.png b/plugins/ztooldeveloperbox/public/logo.png
new file mode 100644
index 00000000..f195f877
Binary files /dev/null and b/plugins/ztooldeveloperbox/public/logo.png differ
diff --git a/plugins/ztooldeveloperbox/public/plugin.json b/plugins/ztooldeveloperbox/public/plugin.json
new file mode 100644
index 00000000..9352c5b4
--- /dev/null
+++ b/plugins/ztooldeveloperbox/public/plugin.json
@@ -0,0 +1,94 @@
+{
+ "$schema": "node_modules/@ztools-center/ztools-api-types/resource/ztools.schema.json",
+ "name": "ztooldeveloperbox",
+ "title": "ztool_developer_box",
+ "description": "开发工具箱",
+ "author": "shikeke",
+ "version": "1.0.0",
+ "main": "index.html",
+ "preload": "preload/services.js",
+ "logo": "logo.png",
+ "development": {
+ "main": "http://localhost:5173"
+ },
+ "features": [
+ {
+ "code": "random",
+ "explain": "生成指定范围内的随机数,支持整数和小数",
+ "icon": "logo.png",
+ "cmds": [
+ "随机数",
+ "random",
+ "生成随机数"
+ ]
+ },
+ {
+ "code": "randomstring",
+ "explain": "生成随机字符串,可选数字、大小写字母和特殊字符",
+ "icon": "logo.png",
+ "cmds": [
+ "随机字符串",
+ "randomstring",
+ "生成随机字符串"
+ ]
+ },
+ {
+ "code": "xml",
+ "explain": "XML 格式化与压缩",
+ "icon": "logo.png",
+ "cmds": [
+ "xml",
+ "xml格式化",
+ "xml压缩",
+ {
+ "type": "over",
+ "label": "XML 格式化"
+ }
+ ]
+ },
+ {
+ "code": "hello",
+ "explain": "这是插件应用的第一个功能",
+ "icon": "logo.png",
+ "cmds": [
+ "你好",
+ "hello"
+ ]
+ },
+ {
+ "code": "read",
+ "explain": "功能指令+匹配指令示例,使用 node.js 能力读文件",
+ "icon": "logo.png",
+ "cmds": [
+ "读文件",
+ {
+ "type": "files",
+ "fileType": "file",
+ "maxLength": 1,
+ "label": "读文件"
+ }
+ ]
+ },
+ {
+ "code": "write",
+ "explain": "匹配指令示例,使用 node.js 能力写文件",
+ "icon": "logo.png",
+ "mainHide": true,
+ "cmds": [
+ {
+ "type": "over",
+ "label": "保存为文件"
+ },
+ {
+ "type": "img",
+ "label": "保存为文件"
+ }
+ ]
+ }
+ ],
+ "platform": [
+ "darwin",
+ "win32",
+ "linux"
+ ]
+}
\ No newline at end of file
diff --git a/plugins/ztooldeveloperbox/public/preload/package.json b/plugins/ztooldeveloperbox/public/preload/package.json
new file mode 100644
index 00000000..5bbefffb
--- /dev/null
+++ b/plugins/ztooldeveloperbox/public/preload/package.json
@@ -0,0 +1,3 @@
+{
+ "type": "commonjs"
+}
diff --git a/plugins/ztooldeveloperbox/public/preload/services.js b/plugins/ztooldeveloperbox/public/preload/services.js
new file mode 100644
index 00000000..83c3ef1f
--- /dev/null
+++ b/plugins/ztooldeveloperbox/public/preload/services.js
@@ -0,0 +1,27 @@
+const fs = require('node:fs')
+const path = require('node:path')
+
+// 通过 window 对象向渲染进程注入 nodejs 能力
+window.services = {
+ // 读文件
+ readFile(file) {
+ return fs.readFileSync(file, { encoding: 'utf-8' })
+ },
+ // 文本写入到下载目录
+ writeTextFile(text) {
+ const filePath = path.join(window.ztools.getPath('downloads'), Date.now().toString() + '.txt')
+ fs.writeFileSync(filePath, text, { encoding: 'utf-8' })
+ return filePath
+ },
+ // 图片写入到下载目录
+ writeImageFile(base64Url) {
+ const matchs = /^data:image\/([a-z]{1,20});base64,/i.exec(base64Url)
+ if (!matchs) return
+ const filePath = path.join(
+ window.ztools.getPath('downloads'),
+ Date.now().toString() + '.' + matchs[1]
+ )
+ fs.writeFileSync(filePath, base64Url.substring(matchs[0].length), { encoding: 'base64' })
+ return filePath
+ }
+}
diff --git a/plugins/ztooldeveloperbox/src/App.vue b/plugins/ztooldeveloperbox/src/App.vue
new file mode 100644
index 00000000..a18d7e2e
--- /dev/null
+++ b/plugins/ztooldeveloperbox/src/App.vue
@@ -0,0 +1,131 @@
+
+
+
+
+
插件加载失败
+
未检测到 ZTools 运行环境,请在 ZTools 中安装并打开此插件。
+
+
+
+
开发工具箱
+
浏览器预览模式:选择功能进行测试。
+
选择功能开始使用,或在 ZTools 搜索框输入对应指令。
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/plugins/ztooldeveloperbox/src/Hello/index.vue b/plugins/ztooldeveloperbox/src/Hello/index.vue
new file mode 100644
index 00000000..8fc58146
--- /dev/null
+++ b/plugins/ztooldeveloperbox/src/Hello/index.vue
@@ -0,0 +1,25 @@
+
+
+
+
+
你好,Hello
+
插件应用进入参数
+
+ {{ JSON.stringify(enterAction, undefined, 2) }}
+
+
+
+
+
diff --git a/plugins/ztooldeveloperbox/src/Random/index.vue b/plugins/ztooldeveloperbox/src/Random/index.vue
new file mode 100644
index 00000000..35f03e9a
--- /dev/null
+++ b/plugins/ztooldeveloperbox/src/Random/index.vue
@@ -0,0 +1,186 @@
+
+
+
+
+
+
+
diff --git a/plugins/ztooldeveloperbox/src/RandomString/index.vue b/plugins/ztooldeveloperbox/src/RandomString/index.vue
new file mode 100644
index 00000000..40da4b37
--- /dev/null
+++ b/plugins/ztooldeveloperbox/src/RandomString/index.vue
@@ -0,0 +1,236 @@
+
+
+
+
+
+
+
diff --git a/plugins/ztooldeveloperbox/src/Read/index.vue b/plugins/ztooldeveloperbox/src/Read/index.vue
new file mode 100644
index 00000000..903fea36
--- /dev/null
+++ b/plugins/ztooldeveloperbox/src/Read/index.vue
@@ -0,0 +1,105 @@
+
+
+
+
+
+
{{ filePath }}
+
+
+ {{ fileContent }}
+
+
+
+
+ {{ error }}
+
+
+
+
+
+
diff --git a/plugins/ztooldeveloperbox/src/Write/index.vue b/plugins/ztooldeveloperbox/src/Write/index.vue
new file mode 100644
index 00000000..9eb172bc
--- /dev/null
+++ b/plugins/ztooldeveloperbox/src/Write/index.vue
@@ -0,0 +1,40 @@
+
+
+
+
+
diff --git a/plugins/ztooldeveloperbox/src/Xml/index.vue b/plugins/ztooldeveloperbox/src/Xml/index.vue
new file mode 100644
index 00000000..1a9bc538
--- /dev/null
+++ b/plugins/ztooldeveloperbox/src/Xml/index.vue
@@ -0,0 +1,507 @@
+
+
+
+
+
+
+
diff --git a/plugins/ztooldeveloperbox/src/components/EditorFindWidget.vue b/plugins/ztooldeveloperbox/src/components/EditorFindWidget.vue
new file mode 100644
index 00000000..06655627
--- /dev/null
+++ b/plugins/ztooldeveloperbox/src/components/EditorFindWidget.vue
@@ -0,0 +1,277 @@
+
+
+
+
+
+
+
diff --git a/plugins/ztooldeveloperbox/src/components/XmlEditorPanel.vue b/plugins/ztooldeveloperbox/src/components/XmlEditorPanel.vue
new file mode 100644
index 00000000..85a64488
--- /dev/null
+++ b/plugins/ztooldeveloperbox/src/components/XmlEditorPanel.vue
@@ -0,0 +1,212 @@
+
+
+
+
+
+
+
diff --git a/plugins/ztooldeveloperbox/src/dev/ztools-mock.ts b/plugins/ztooldeveloperbox/src/dev/ztools-mock.ts
new file mode 100644
index 00000000..e17f6e26
--- /dev/null
+++ b/plugins/ztooldeveloperbox/src/dev/ztools-mock.ts
@@ -0,0 +1,67 @@
+type EnterAction = {
+ code: string
+ type: string
+ payload: unknown
+ option: unknown
+}
+
+const enterCallbacks: Array<(action: EnterAction) => void> = []
+const outCallbacks: Array<(processExit: boolean) => void> = []
+
+export let isZtoolsMocked = false
+
+export function setupZtoolsFallback() {
+ if (window.ztools) return
+
+ isZtoolsMocked = true
+
+ window.ztools = {
+ onPluginEnter(callback) {
+ enterCallbacks.push(callback)
+ },
+ onPluginOut(callback) {
+ outCallbacks.push(callback)
+ },
+ copyText(text) {
+ void navigator.clipboard.writeText(text)
+ return true
+ },
+ showNotification(body) {
+ console.log('[ztools mock]', body)
+ },
+ showOpenDialog() {
+ console.warn('[ztools mock] showOpenDialog 仅在 ZTools 中可用')
+ return null
+ }
+ } as unknown as typeof window.ztools
+
+ window.services = {
+ readFile() {
+ throw new Error('readFile 仅在 ZTools 中可用')
+ },
+ writeTextFile() {
+ throw new Error('writeTextFile 仅在 ZTools 中可用')
+ },
+ writeImageFile() {
+ throw new Error('writeImageFile 仅在 ZTools 中可用')
+ }
+ }
+}
+
+export function enterFeature(code: string) {
+ const action = { code, type: 'text', payload: null, option: null }
+ enterCallbacks.forEach((callback) => callback(action))
+}
+
+export function exitFeature() {
+ outCallbacks.forEach((callback) => callback(false))
+}
+
+export function getDevRouteFromUrl(): string | null {
+ return new URLSearchParams(window.location.search).get('code')
+}
+
+// 兼容旧命名
+export const devEnterFeature = enterFeature
+export const devExitFeature = exitFeature
+export const setupDevZtoolsMock = setupZtoolsFallback
diff --git a/plugins/ztooldeveloperbox/src/env.d.ts b/plugins/ztooldeveloperbox/src/env.d.ts
new file mode 100644
index 00000000..94ae981d
--- /dev/null
+++ b/plugins/ztooldeveloperbox/src/env.d.ts
@@ -0,0 +1,23 @@
+///
+///
+
+declare module '*.vue' {
+ import type { DefineComponent } from 'vue'
+ const component: DefineComponent, Record, unknown>
+ export default component
+}
+
+// Preload services 类型声明(对应 public/preload/services.js)
+interface Services {
+ readFile: (file: string) => string
+ writeTextFile: (text: string) => string
+ writeImageFile: (base64Url: string) => string | undefined
+}
+
+declare global {
+ interface Window {
+ services: Services
+ }
+}
+
+export {}
diff --git a/plugins/ztooldeveloperbox/src/main.css b/plugins/ztooldeveloperbox/src/main.css
new file mode 100644
index 00000000..4a393b2e
--- /dev/null
+++ b/plugins/ztooldeveloperbox/src/main.css
@@ -0,0 +1,68 @@
+:root {
+ --blue: rgb(88, 164, 246);
+ --light: #fff;
+}
+
+html,
+body {
+ margin: 0;
+ padding: 0;
+ height: 100%;
+}
+
+#app {
+ height: 100%;
+}
+
+button {
+ border: none;
+ background: none var(--blue);
+ color: var(--light);
+ line-height: 2.5;
+ cursor: pointer;
+ transition: opacity 0.2s;
+}
+
+button:disabled {
+ filter: grayscale(1);
+ cursor: not-allowed;
+}
+
+button:not(:disabled):active {
+ opacity: 0.6;
+}
+
+textarea {
+ display: block;
+ margin: 0;
+}
+
+@media (prefers-color-scheme: light) {
+ body {
+ background-color: #f4f4f4;
+ }
+
+ ::-webkit-scrollbar-track-piece {
+ background-color: #f4f4f4;
+ }
+
+ ::-webkit-scrollbar-thumb {
+ border-color: #f4f4f4;
+ }
+}
+
+@media (prefers-color-scheme: dark) {
+ &::-webkit-scrollbar-track-piece {
+ background-color: #303133;
+ }
+
+ &::-webkit-scrollbar-thumb {
+ background-color: #666;
+ border-color: #303133;
+ }
+
+ body {
+ background-color: #303133;
+ color: #fff;
+ }
+}
diff --git a/plugins/ztooldeveloperbox/src/main.ts b/plugins/ztooldeveloperbox/src/main.ts
new file mode 100644
index 00000000..21e20703
--- /dev/null
+++ b/plugins/ztooldeveloperbox/src/main.ts
@@ -0,0 +1,8 @@
+import { createApp } from 'vue'
+import './main.css'
+import { setupZtoolsFallback } from './dev/ztools-mock'
+import App from './App.vue'
+
+setupZtoolsFallback()
+
+createApp(App).mount('#app')
diff --git a/plugins/ztooldeveloperbox/src/utils/text-search.ts b/plugins/ztooldeveloperbox/src/utils/text-search.ts
new file mode 100644
index 00000000..957b5479
--- /dev/null
+++ b/plugins/ztooldeveloperbox/src/utils/text-search.ts
@@ -0,0 +1,215 @@
+export type TextMatch = {
+ start: number
+ end: number
+}
+
+export type SearchOptions = {
+ caseSensitive: boolean
+ wholeWord: boolean
+ useRegex: boolean
+}
+
+const WORD_CHAR = /[\w-]/
+
+function isWholeWord(text: string, start: number, end: number) {
+ const before = start > 0 ? text[start - 1] : ''
+ const after = end < text.length ? text[end] : ''
+ return !WORD_CHAR.test(before) && !WORD_CHAR.test(after)
+}
+
+function collectRegexMatches(text: string, query: string, options: SearchOptions): TextMatch[] {
+ try {
+ const flags = options.caseSensitive ? 'g' : 'gi'
+ const regex = new RegExp(query, flags)
+ const result: TextMatch[] = []
+ let match: RegExpExecArray | null
+
+ while ((match = regex.exec(text)) !== null) {
+ const start = match.index
+ const end = start + match[0].length
+
+ if (options.wholeWord && !isWholeWord(text, start, end)) {
+ if (match[0].length === 0) regex.lastIndex++
+ continue
+ }
+
+ result.push({ start, end })
+ if (match[0].length === 0) regex.lastIndex++
+ }
+
+ return result
+ } catch {
+ return []
+ }
+}
+
+function collectPlainMatches(text: string, query: string, options: SearchOptions): TextMatch[] {
+ const result: TextMatch[] = []
+ const source = options.caseSensitive ? text : text.toLowerCase()
+ const target = options.caseSensitive ? query : query.toLowerCase()
+ let start = 0
+
+ while (start <= source.length - target.length) {
+ const index = source.indexOf(target, start)
+ if (index === -1) break
+
+ const end = index + target.length
+ if (!options.wholeWord || isWholeWord(text, index, end)) {
+ result.push({ start: index, end })
+ }
+ start = index + 1
+ }
+
+ return result
+}
+
+export function collectMatches(text: string, query: string, options: SearchOptions): TextMatch[] {
+ if (!query) return []
+ if (options.useRegex) return collectRegexMatches(text, query, options)
+ return collectPlainMatches(text, query, options)
+}
+
+export function replaceAllText(
+ text: string,
+ query: string,
+ replacement: string,
+ options: SearchOptions
+): string {
+ const matches = collectMatches(text, query, options)
+ if (!matches.length) return text
+
+ let result = ''
+ let last = 0
+
+ for (const match of matches) {
+ result += text.slice(last, match.start) + replacement
+ last = match.end
+ }
+
+ return result + text.slice(last)
+}
+
+export function escapeHtml(text: string): string {
+ return text
+ .replace(/&/g, '&')
+ .replace(//g, '>')
+ .replace(/"/g, '"')
+}
+
+export function buildHighlightHtml(
+ text: string,
+ matches: TextMatch[],
+ currentIndex: number
+): string {
+ if (!matches.length) {
+ return `${escapeHtml(text)}\n`
+ }
+
+ let html = ''
+ let last = 0
+
+ matches.forEach((match, index) => {
+ html += escapeHtml(text.slice(last, match.start))
+ const className = index === currentIndex ? 'editor-mark editor-mark--current' : 'editor-mark'
+ html += `${escapeHtml(text.slice(match.start, match.end))}`
+ last = match.end
+ })
+
+ html += escapeHtml(text.slice(last))
+ return `${html}\n`
+}
+
+export type ScrollToMatchOptions = {
+ focusEditor?: boolean
+}
+
+export function scrollTextareaToMatch(
+ textarea: HTMLTextAreaElement,
+ match: TextMatch,
+ highlightRoot?: HTMLElement | null,
+ options: ScrollToMatchOptions = {}
+) {
+ const focusEditor = options.focusEditor ?? true
+
+ if (highlightRoot) {
+ const mark = highlightRoot.querySelector('.editor-mark--current')
+ if (mark instanceof HTMLElement) {
+ scrollContainerToElement(highlightRoot, mark)
+ textarea.scrollTop = highlightRoot.scrollTop
+ textarea.scrollLeft = highlightRoot.scrollLeft
+ if (focusEditor) {
+ textarea.focus()
+ textarea.setSelectionRange(match.start, match.end)
+ }
+ return
+ }
+ }
+
+ scrollTextareaToMatchByMirror(textarea, match)
+ if (focusEditor) {
+ textarea.focus()
+ textarea.setSelectionRange(match.start, match.end)
+ }
+}
+
+function scrollContainerToElement(container: HTMLElement, element: HTMLElement) {
+ const containerRect = container.getBoundingClientRect()
+ const elementRect = element.getBoundingClientRect()
+
+ const offsetTop = elementRect.top - containerRect.top + container.scrollTop
+ const offsetLeft = elementRect.left - containerRect.left + container.scrollLeft
+
+ const targetTop = offsetTop - container.clientHeight / 2 + elementRect.height / 2
+ const targetLeft = offsetLeft - container.clientWidth / 2 + elementRect.width / 2
+
+ container.scrollTop = Math.max(0, targetTop)
+ container.scrollLeft = Math.max(0, targetLeft)
+}
+
+function scrollTextareaToMatchByMirror(textarea: HTMLTextAreaElement, match: TextMatch) {
+ const style = window.getComputedStyle(textarea)
+ const mirror = document.createElement('div')
+ const text = textarea.value
+ const before = text.slice(0, match.start)
+ const matched = text.slice(match.start, match.end) || ' '
+ const after = text.slice(match.end)
+
+ mirror.style.position = 'absolute'
+ mirror.style.visibility = 'hidden'
+ mirror.style.top = '0'
+ mirror.style.left = '-99999px'
+ mirror.style.overflow = 'hidden'
+ mirror.style.width = `${textarea.clientWidth}px`
+ mirror.style.fontFamily = style.fontFamily
+ mirror.style.fontSize = style.fontSize
+ mirror.style.fontWeight = style.fontWeight
+ mirror.style.fontStyle = style.fontStyle
+ mirror.style.lineHeight = style.lineHeight
+ mirror.style.letterSpacing = style.letterSpacing
+ mirror.style.padding = style.padding
+ mirror.style.border = style.border
+ mirror.style.boxSizing = style.boxSizing
+ mirror.style.whiteSpace = style.whiteSpace
+ mirror.style.wordBreak = style.wordBreak
+ mirror.style.overflowWrap = style.overflowWrap
+
+ mirror.textContent = ''
+ mirror.append(document.createTextNode(before))
+ const marker = document.createElement('span')
+ marker.textContent = matched
+ mirror.append(marker)
+ mirror.append(document.createTextNode(after))
+
+ document.body.appendChild(mirror)
+
+ const markerTop = marker.offsetTop
+ const markerLeft = marker.offsetLeft
+ const markerHeight = marker.offsetHeight || parseFloat(style.lineHeight) || 19.5
+ const markerWidth = marker.offsetWidth || 8
+
+ document.body.removeChild(mirror)
+
+ textarea.scrollTop = Math.max(0, markerTop - textarea.clientHeight / 2 + markerHeight / 2)
+ textarea.scrollLeft = Math.max(0, markerLeft - textarea.clientWidth / 2 + markerWidth / 2)
+}
diff --git a/plugins/ztooldeveloperbox/src/utils/xml.ts b/plugins/ztooldeveloperbox/src/utils/xml.ts
new file mode 100644
index 00000000..90962c3a
--- /dev/null
+++ b/plugins/ztooldeveloperbox/src/utils/xml.ts
@@ -0,0 +1,241 @@
+function getParseError(doc: Document): string | null {
+ const errorNode = doc.querySelector('parsererror')
+ if (!errorNode) return null
+ return errorNode.textContent?.trim() || 'XML 解析失败'
+}
+
+function escapeAttribute(value: string): string {
+ return value
+ .replace(/&/g, '&')
+ .replace(/"/g, '"')
+ .replace(//g, '>')
+}
+
+function getXmlDeclaration(xml: string): string | null {
+ const match = xml.trim().match(/^<\?xml[\s\S]*?\?>/)
+ return match ? match[0] : null
+}
+
+function buildOpenTag(el: Element, selfClosing = false): string {
+ const attrs = Array.from(el.attributes)
+ .map((attr) => ` ${attr.name}="${escapeAttribute(attr.value)}"`)
+ .join('')
+ return selfClosing ? `<${el.tagName}${attrs} />` : `<${el.tagName}${attrs}>`
+}
+
+function getMeaningfulChildNodes(node: Node): ChildNode[] {
+ return Array.from(node.childNodes).filter((child) => {
+ if (child.nodeType !== Node.TEXT_NODE) return true
+ return Boolean(child.textContent?.trim())
+ })
+}
+
+function formatNode(node: Node, depth: number, lines: string[], indent: string): void {
+ const prefix = indent.repeat(depth)
+
+ if (node.nodeType === Node.DOCUMENT_NODE) {
+ for (const child of Array.from(node.childNodes)) {
+ formatNode(child, depth, lines, indent)
+ }
+ return
+ }
+
+ if (node.nodeType === Node.DOCUMENT_TYPE_NODE) {
+ const docType = node as DocumentType
+ let declaration = ``)
+ return
+ }
+
+ if (node.nodeType === Node.COMMENT_NODE) {
+ lines.push(`${prefix}`)
+ return
+ }
+
+ if (node.nodeType === Node.PROCESSING_INSTRUCTION_NODE) {
+ const pi = node as ProcessingInstruction
+ const data = pi.data ? ` ${pi.data}` : ''
+ lines.push(`${prefix}${pi.target}${data}?>`)
+ return
+ }
+
+ if (node.nodeType === Node.CDATA_SECTION_NODE) {
+ lines.push(`${prefix}`)
+ return
+ }
+
+ if (node.nodeType === Node.TEXT_NODE) {
+ const text = node.textContent ?? ''
+ if (text.trim()) {
+ lines.push(`${prefix}${escapeText(text)}`)
+ }
+ return
+ }
+
+ if (node.nodeType !== Node.ELEMENT_NODE) return
+
+ const element = node as Element
+ const children = getMeaningfulChildNodes(element)
+
+ if (children.length === 0) {
+ lines.push(`${prefix}${buildOpenTag(element, true)}`)
+ return
+ }
+
+ if (children.length === 1 && children[0].nodeType === Node.TEXT_NODE) {
+ const text = children[0].textContent ?? ''
+ lines.push(`${prefix}${buildOpenTag(element)}${escapeText(text)}${element.tagName}>`)
+ return
+ }
+
+ if (children.length === 1 && children[0].nodeType === Node.CDATA_SECTION_NODE) {
+ lines.push(`${prefix}${buildOpenTag(element)}${element.tagName}>`)
+ return
+ }
+
+ lines.push(`${prefix}${buildOpenTag(element)}`)
+ for (const child of children) {
+ formatNode(child, depth + 1, lines, indent)
+ }
+ lines.push(`${prefix}${element.tagName}>`)
+}
+
+function compressNode(node: Node, parts: string[]): void {
+ if (node.nodeType === Node.DOCUMENT_NODE) {
+ for (const child of Array.from(node.childNodes)) {
+ compressNode(child, parts)
+ }
+ return
+ }
+
+ if (node.nodeType === Node.DOCUMENT_TYPE_NODE) {
+ const docType = node as DocumentType
+ let declaration = ``)
+ return
+ }
+
+ if (node.nodeType === Node.COMMENT_NODE) {
+ parts.push(``)
+ return
+ }
+
+ if (node.nodeType === Node.PROCESSING_INSTRUCTION_NODE) {
+ const pi = node as ProcessingInstruction
+ const data = pi.data ? ` ${pi.data}` : ''
+ parts.push(`${pi.target}${data}?>`)
+ return
+ }
+
+ if (node.nodeType === Node.CDATA_SECTION_NODE) {
+ parts.push(``)
+ return
+ }
+
+ if (node.nodeType === Node.TEXT_NODE) {
+ parts.push(escapeText(node.textContent ?? ''))
+ return
+ }
+
+ if (node.nodeType !== Node.ELEMENT_NODE) return
+
+ const element = node as Element
+ const children = getMeaningfulChildNodes(element)
+
+ if (children.length === 0) {
+ parts.push(buildOpenTag(element, true))
+ return
+ }
+
+ parts.push(buildOpenTag(element))
+ for (const child of children) {
+ compressNode(child, parts)
+ }
+ parts.push(`${element.tagName}>`)
+}
+
+function parseXml(xml: string): Document {
+ const trimmed = xml.trim()
+ if (!trimmed) {
+ throw new Error('请输入 XML 内容')
+ }
+
+ const doc = new DOMParser().parseFromString(trimmed, 'application/xml')
+ const parseError = getParseError(doc)
+ if (parseError) {
+ throw new Error(parseError)
+ }
+ return doc
+}
+
+export function formatXml(xml: string, indent = ' '): string {
+ const doc = parseXml(xml)
+ const lines: string[] = []
+ const declaration = getXmlDeclaration(xml)
+
+ if (declaration) {
+ lines.push(declaration)
+ }
+
+ for (const child of Array.from(doc.childNodes)) {
+ if (child.nodeType === Node.ELEMENT_NODE) {
+ formatNode(child, 0, lines, indent)
+ continue
+ }
+ if (
+ child.nodeType === Node.COMMENT_NODE ||
+ child.nodeType === Node.PROCESSING_INSTRUCTION_NODE ||
+ child.nodeType === Node.DOCUMENT_TYPE_NODE
+ ) {
+ formatNode(child, 0, lines, indent)
+ }
+ }
+
+ return lines.join('\n')
+}
+
+export function compressXml(xml: string): string {
+ const doc = parseXml(xml)
+ const parts: string[] = []
+ const declaration = getXmlDeclaration(xml)
+
+ if (declaration) {
+ parts.push(declaration)
+ }
+
+ for (const child of Array.from(doc.childNodes)) {
+ if (child.nodeType === Node.ELEMENT_NODE) {
+ compressNode(child, parts)
+ continue
+ }
+ if (
+ child.nodeType === Node.COMMENT_NODE ||
+ child.nodeType === Node.PROCESSING_INSTRUCTION_NODE ||
+ child.nodeType === Node.DOCUMENT_TYPE_NODE
+ ) {
+ compressNode(child, parts)
+ }
+ }
+
+ return parts.join('')
+}
diff --git a/plugins/ztooldeveloperbox/tsconfig.json b/plugins/ztooldeveloperbox/tsconfig.json
new file mode 100644
index 00000000..39b73bc6
--- /dev/null
+++ b/plugins/ztooldeveloperbox/tsconfig.json
@@ -0,0 +1,19 @@
+{
+ "compilerOptions": {
+ "target": "ES2020",
+ "useDefineForClassFields": true,
+ "module": "ESNext",
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
+ "skipLibCheck": true,
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "noEmit": true,
+ "jsx": "preserve",
+ "strict": false,
+ "noImplicitAny": false,
+ "types": ["@ztools-center/ztools-api-types"]
+ },
+ "include": ["src"]
+}
diff --git a/plugins/ztooldeveloperbox/vite.config.js b/plugins/ztooldeveloperbox/vite.config.js
new file mode 100644
index 00000000..7bfab103
--- /dev/null
+++ b/plugins/ztooldeveloperbox/vite.config.js
@@ -0,0 +1,8 @@
+import { defineConfig } from 'vite'
+import vue from '@vitejs/plugin-vue'
+
+// https://vitejs.dev/config/
+export default defineConfig({
+ plugins: [vue()],
+ base: './'
+})