From 58dcd15e1e7124247cb89758d82d641427adb758 Mon Sep 17 00:00:00 2001 From: ysysyss Date: Wed, 30 Sep 2026 16:51:30 +0800 Subject: [PATCH] =?UTF-8?q?Add=20plugin=20Y=E5=89=AA=E8=B4=B4=E6=9D=BF=20v?= =?UTF-8?q?1.0.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Initial commit - 初始化项目 - 剪切板开发完成提交 - 修改logo --- plugins/y-clipboard/CHANGELOG.md | 15 + plugins/y-clipboard/README.md | 45 + plugins/y-clipboard/design/index.html | 134 ++ plugins/y-clipboard/design/logo-a.png | Bin 0 -> 13937 bytes plugins/y-clipboard/design/logo-b.png | Bin 0 -> 17406 bytes plugins/y-clipboard/design/logo-c.png | Bin 0 -> 13041 bytes plugins/y-clipboard/design/preview.png | Bin 0 -> 67732 bytes plugins/y-clipboard/design/render.cjs | 292 ++++ plugins/y-clipboard/index.html | 11 + plugins/y-clipboard/package-lock.json | 1524 +++++++++++++++++ plugins/y-clipboard/package.json | 20 + plugins/y-clipboard/src-ztools/logo.png | Bin 0 -> 13041 bytes plugins/y-clipboard/src-ztools/plugin.json | 22 + .../src-ztools/preload/package.json | 3 + .../src-ztools/preload/services.js | 14 + plugins/y-clipboard/src/App.vue | 142 ++ plugins/y-clipboard/src/api.ts | 371 ++++ .../src/components/ClipboardItem.vue | 205 +++ .../y-clipboard/src/components/Sidebar.vue | 108 ++ .../y-clipboard/src/components/Toolbar.vue | 114 ++ .../src/components/VirtualList.vue | 118 ++ .../y-clipboard/src/composables/useStore.ts | 299 ++++ plugins/y-clipboard/src/env.d.ts | 21 + plugins/y-clipboard/src/main.css | 102 ++ plugins/y-clipboard/src/main.ts | 5 + plugins/y-clipboard/src/types.ts | 36 + plugins/y-clipboard/src/utils/format.ts | 71 + plugins/y-clipboard/tsconfig.json | 19 + plugins/y-clipboard/vite.config.js | 12 + 29 files changed, 3703 insertions(+) create mode 100644 plugins/y-clipboard/CHANGELOG.md create mode 100644 plugins/y-clipboard/README.md create mode 100644 plugins/y-clipboard/design/index.html create mode 100644 plugins/y-clipboard/design/logo-a.png create mode 100644 plugins/y-clipboard/design/logo-b.png create mode 100644 plugins/y-clipboard/design/logo-c.png create mode 100644 plugins/y-clipboard/design/preview.png create mode 100644 plugins/y-clipboard/design/render.cjs create mode 100644 plugins/y-clipboard/index.html create mode 100644 plugins/y-clipboard/package-lock.json create mode 100644 plugins/y-clipboard/package.json create mode 100644 plugins/y-clipboard/src-ztools/logo.png create mode 100644 plugins/y-clipboard/src-ztools/plugin.json create mode 100644 plugins/y-clipboard/src-ztools/preload/package.json create mode 100644 plugins/y-clipboard/src-ztools/preload/services.js create mode 100644 plugins/y-clipboard/src/App.vue create mode 100644 plugins/y-clipboard/src/api.ts create mode 100644 plugins/y-clipboard/src/components/ClipboardItem.vue create mode 100644 plugins/y-clipboard/src/components/Sidebar.vue create mode 100644 plugins/y-clipboard/src/components/Toolbar.vue create mode 100644 plugins/y-clipboard/src/components/VirtualList.vue create mode 100644 plugins/y-clipboard/src/composables/useStore.ts create mode 100644 plugins/y-clipboard/src/env.d.ts create mode 100644 plugins/y-clipboard/src/main.css create mode 100644 plugins/y-clipboard/src/main.ts create mode 100644 plugins/y-clipboard/src/types.ts create mode 100644 plugins/y-clipboard/src/utils/format.ts create mode 100644 plugins/y-clipboard/tsconfig.json create mode 100644 plugins/y-clipboard/vite.config.js diff --git a/plugins/y-clipboard/CHANGELOG.md b/plugins/y-clipboard/CHANGELOG.md new file mode 100644 index 000000000..02c68a52e --- /dev/null +++ b/plugins/y-clipboard/CHANGELOG.md @@ -0,0 +1,15 @@ +# Changelog + +## 0.1.0 - 2026-09-30 + +- 重写为剪贴板历史管理插件:文本 / 链接 / 代码 / 颜色值 / 图片 / 文件 六类自动分类 +- 本地即时过滤 + 宿主端补充搜索 +- 收藏:以快照形式独立持久化,清空历史后不丢 +- 键盘流:↑↓ 选择 / Enter 复制并粘贴 / Delete 删除 / Esc 退出 +- 虚拟滚动,千条记录保持流畅 +- 跟随 ZTools 深浅色主题与主题强调色 +- 新增插件 logo(闪电 + 剪贴板) + +## 1.0.0 - 2026-09-30 + +- 初次发布,将插件提交至 ZTools 插件仓库。 diff --git a/plugins/y-clipboard/README.md b/plugins/y-clipboard/README.md new file mode 100644 index 000000000..48de706f8 --- /dev/null +++ b/plugins/y-clipboard/README.md @@ -0,0 +1,45 @@ +# Y剪贴板 + +> ZTools 剪贴板历史管理插件 · Vue 3 + TypeScript + Vite + +分类清晰、响应飞快的剪贴板管理:文本 / 链接 / 代码 / 颜色 / 图片 / 文件自动分类,支持收藏、搜索与全键盘操作。 + +## 功能 + +- **自动分类**:复制的内容按 文本 / 链接 / 代码 / 颜色值 / 图片 / 文件 自动归类,侧栏一键切换 +- **即搜即得**:本地过滤即时出结果,同时防抖调用宿主搜索补充全量历史 +- **收藏**:星标记录存入插件独立存储(dbStorage),原历史被清空也不丢 +- **键盘流**:`↑` `↓` 选择 · `Enter` 复制并粘贴到原窗口 · `Delete` 删除 · `Esc` 退出 +- **主题适配**:跟随 ZTools 浅色 / 深色主题与主题强调色 +- **虚拟滚动**:固定行高窗口化渲染,千条记录依然流畅 + +## 开发 + +```bash +npm install +npm run dev # 浏览器打开 http://localhost:5173(自动使用 mock 数据) +npm run build # 构建到 src-ztools/dist/ +``` + +- 真实环境:ZTools 主窗口输入 `剪贴板` / `clipboard` / `clip` 触发 +- 开发模式:`plugin.json` 的 `development.main` 指向 dev server,改代码即时热更新 + +## 结构 + +``` +├── plugin.json # 插件配置(功能入口、触发指令) +├── preload/services.js # 预加载脚本(CommonJS,不可打包压缩) +└── src/ + ├── api.ts # 宿主 API 封装 + 字段归一化 + 开发 mock + ├── types.ts # 类型定义 + ├── utils/format.ts # 分类判定、时间格式化 + ├── composables/useStore.ts # 状态:分页加载 / 搜索 / 收藏 / 键盘导航 + └── components/ # Sidebar / Toolbar / VirtualList / ClipboardItem +``` + +## 发布 + +```bash +git add . && git commit -m "feat: clipboard plugin" +ztools publish +``` diff --git a/plugins/y-clipboard/design/index.html b/plugins/y-clipboard/design/index.html new file mode 100644 index 000000000..b7d1ad831 --- /dev/null +++ b/plugins/y-clipboard/design/index.html @@ -0,0 +1,134 @@ + + + + +y-clipboard logo design + + + +
+ + + diff --git a/plugins/y-clipboard/design/logo-a.png b/plugins/y-clipboard/design/logo-a.png new file mode 100644 index 0000000000000000000000000000000000000000..6d1985d6490b177a6cc39eb3b4dedaf2066333e6 GIT binary patch literal 13937 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 literal 0 HcmV?d00001 diff --git a/plugins/y-clipboard/design/logo-b.png b/plugins/y-clipboard/design/logo-b.png new file mode 100644 index 0000000000000000000000000000000000000000..67d613a07fd872fcb470539d2b1d754a2c76a91d GIT binary patch literal 17406 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 literal 0 HcmV?d00001 diff --git a/plugins/y-clipboard/design/preview.png b/plugins/y-clipboard/design/preview.png new file mode 100644 index 0000000000000000000000000000000000000000..c752b525f1f44e0cb8d3a712c6fb4e069c1025e7 GIT binary patch literal 67732 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 a + (b - a) * t + +function grad(p, stops) { + // userSpaceOnUse: (40,24) -> (472,488),与 SVG 定义一致 + const x0 = 40, y0 = 24, x1 = 472, y1 = 488 + const dx = x1 - x0, dy = y1 - y0 + let t = ((p[0] - x0) * dx + (p[1] - y0) * dy) / (dx * dx + dy * dy) + t = Math.max(0, Math.min(1, t)) + return [ + lerp(stops[0][0], stops[1][0], t), + lerp(stops[0][1], stops[1][1], t), + lerp(stops[0][2], stops[1][2], t) + ] +} + +function inRect(p, x, y, w, h, r) { + r = r || 0 + const dx = Math.abs(p[0] - (x + w / 2)) - (w / 2 - r) + const dy = Math.abs(p[1] - (y + h / 2)) - (h / 2 - r) + const mx = Math.max(dx, 0), my = Math.max(dy, 0) + return mx * mx + my * my <= r * r +} + +function inPoly(p, pts) { + let inside = false + for (let i = 0, j = pts.length - 1; i < pts.length; j = i++) { + const xi = pts[i][0], yi = pts[i][1], xj = pts[j][0], yj = pts[j][1] + if ((yi > p[1]) !== (yj > p[1]) && p[0] < ((xj - xi) * (p[1] - yi)) / (yj - yi) + xi) { + inside = !inside + } + } + return inside +} + +function rot(p, deg, c) { + const a = (deg * Math.PI) / 180, s = Math.sin(a), co = Math.cos(a) + const dx = p[0] - c[0], dy = p[1] - c[1] + return [c[0] + dx * co - dy * s, c[1] + dx * s + dy * co] +} + +function over(dst, r, g, b, a) { + if (a <= 0) return dst + const da = dst[3] + const oa = a + da * (1 - a) + if (oa <= 0) { dst[0] = dst[1] = dst[2] = dst[3] = 0; return dst } + for (let i = 0; i < 3; i++) { + const s = [r, g, b][i] + dst[i] = (s * a + dst[i] * da * (1 - a)) / oa + } + dst[3] = oa + return dst +} + +const white = () => [255, 255, 255, 1] + +/* ---------------- 三个方案 ---------------- */ + +const STOPS = { + a: [[78, 141, 247], [47, 91, 232]], + b: [[56, 189, 248], [37, 99, 235]], + c: [[42, 59, 95], [20, 30, 56]] +} + +const BOLT_A = [[265, 167], [170, 281], [256, 281], [246, 357], [341, 243], [256, 243]] +const BOLT_C = [[272, 112], [232, 158], [252, 158], [236, 194], [284, 146], [262, 146]] + +function sceneA(p) { + let out = [0, 0, 0, 0] + if (inRect(p, 0, 0, 512, 512, 116)) { + const c = grad(p, STOPS.a); over(out, c[0], c[1], c[2], 1) + } + if (inRect(p, 158, 118, 196, 282, 30)) { const w = white(); over(out, w[0], w[1], w[2], 1) } + if (inRect(p, 222, 92, 68, 52, 16)) { const w = white(); over(out, w[0], w[1], w[2], 1) } + if (inPoly(p, BOLT_A)) { const c = grad(p, STOPS.a); over(out, c[0], c[1], c[2], 1) } + return out +} + +function sceneB(p) { + let out = [0, 0, 0, 0] + if (inRect(p, 0, 0, 512, 512, 116)) { + const c = grad(p, STOPS.b); over(out, c[0], c[1], c[2], 1) + } + const m = rot(p, 10, [268, 256]) // 逆变换:SVG 里是 rotate(-10 268 256) + if (inRect(m, 180, 112, 180, 258, 26)) { const w = white(); over(out, w[0], w[1], w[2], 1) } + for (const l of [[206, 176, 128], [206, 210, 128], [206, 244, 86]]) { + if (inRect(m, l[0], l[1], l[2], 13, 6.5)) { + const c = grad(m, STOPS.b); over(out, c[0], c[1], c[2], 1) + } + } + if (inRect(m, 238, 88, 64, 48, 14)) { const w = white(); over(out, w[0], w[1], w[2], 1) } + for (const s of [[44, 176, 72, 0.95], [28, 230, 104, 0.8], [52, 284, 64, 0.65]]) { + if (inRect(p, s[0], s[1], s[2], 15, 7.5)) over(out, 255, 255, 255, s[3]) + } + return out +} + +function sceneC(p) { + let out = [0, 0, 0, 0] + if (inRect(p, 0, 0, 512, 512, 116)) { + const c = grad(p, STOPS.c); over(out, c[0], c[1], c[2], 1) + } + if (inRect(p, 160, 140, 192, 268, 28)) { const w = white(); over(out, w[0], w[1], w[2], 1) } + for (const l of [[194, 204, 124], [194, 238, 124], [194, 272, 82]]) { + if (inRect(p, l[0], l[1], l[2], 13, 6.5)) { + const c = grad(p, STOPS.c); over(out, c[0], c[1], c[2], 1) + } + } + if (inPoly(p, BOLT_C)) over(out, 255, 176, 32, 1) + return out +} + +const SCENES = { a: sceneA, b: sceneB, c: sceneC } + +/* ---------------- 渲染 ---------------- */ + +function render(scene) { + const buf = Buffer.alloc(W * H * 4) + for (let y = 0; y < H; y++) { + for (let x = 0; x < W; x++) { + let r = 0, g = 0, b = 0, a = 0 + for (let sy = 0; sy < SS; sy++) { + for (let sx = 0; sx < SS; sx++) { + const c = scene([x + (sx + 0.5) / SS, y + (sy + 0.5) / SS]) + r += c[0]; g += c[1]; b += c[2]; a += c[3] + } + } + const n = SS * SS + const i = (y * W + x) * 4 + buf[i] = Math.round(r / n) + buf[i + 1] = Math.round(g / n) + buf[i + 2] = Math.round(b / n) + buf[i + 3] = Math.round((a / n) * 255) + } + } + return buf +} + +/* ---------------- PNG 编码 ---------------- */ + +const CRC_TABLE = (() => { + const t = new Int32Array(256) + for (let n = 0; n < 256; n++) { + let c = n + for (let k = 0; k < 8; k++) c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1 + t[n] = c + } + return t +})() + +function crc32(buf) { + let c = 0xffffffff + for (let i = 0; i < buf.length; i++) c = CRC_TABLE[(c ^ buf[i]) & 0xff] ^ (c >>> 8) + return (c ^ 0xffffffff) >>> 0 +} + +function chunk(type, data) { + const len = Buffer.alloc(4) + len.writeUInt32BE(data.length) + const body = Buffer.concat([Buffer.from(type, 'ascii'), data]) + const crc = Buffer.alloc(4) + crc.writeUInt32BE(crc32(body)) + return Buffer.concat([len, body, crc]) +} + +function writePng(path, buf) { + const ihdr = Buffer.alloc(13) + ihdr.writeUInt32BE(W, 0) + ihdr.writeUInt32BE(H, 4) + ihdr[8] = 8 // bit depth + ihdr[9] = 6 // RGBA + ihdr[10] = 0 + ihdr[11] = 0 + ihdr[12] = 0 + const raw = Buffer.alloc((W * 4 + 1) * H) + for (let y = 0; y < H; y++) { + raw[y * (W * 4 + 1)] = 0 // filter: none + buf.copy(raw, y * (W * 4 + 1) + 1, y * W * 4, (y + 1) * W * 4) + } + const png = Buffer.concat([ + Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]), + chunk('IHDR', ihdr), + chunk('IDAT', zlib.deflateSync(raw, { level: 9 })), + chunk('IEND', Buffer.alloc(0)) + ]) + fs.writeFileSync(path, png) + return png.length +} + +/* ---------------- 自检:ASCII 预览 + 像素探针 ---------------- */ + +function ascii(buf) { + const step = 16 + let s = '' + for (let y = 8; y < H; y += step) { + for (let x = 8; x < W; x += step) { + const i = (y * W + x) * 4 + const a = buf[i + 3] + if (a < 96) { s += ' '; continue } + const lum = 0.299 * buf[i] + 0.587 * buf[i + 1] + 0.114 * buf[i + 2] + const warm = buf[i] - buf[i + 2] + if (warm > 60) s += 'o' // 琥珀 + else if (lum > 210) s += '#' // 白 + else s += '.' // 蓝/深底 + } + s += '\n' + } + return s +} + +function probe(buf, label, points) { + const out = [] + for (const [name, x, y] of points) { + const i = (y * W + x) * 4 + out.push(`${name}(${x},${y})=rgba(${buf[i]},${buf[i + 1]},${buf[i + 2]},${buf[i + 3]})`) + } + console.log(` ${label}: ${out.join(' ')}`) +} + +const POINTS = [ + ['corner', 4, 4], + ['bgTopL', 60, 40], + ['board', 200, 160], + ['boltMid', 240, 280], + ['clip', 256, 110] +] + +/* ---------------- PNG 结构校验 ---------------- */ + +function verifyPng(path) { + const b = fs.readFileSync(path) + const sigOk = Buffer.compare(b.slice(0, 8), Buffer.from([137, 80, 78, 71, 13, 10, 26, 10])) === 0 + let off = 8 + let idat = null + const types = [] + while (off < b.length) { + const len = b.readUInt32BE(off) + const type = b.slice(off + 4, off + 8).toString('ascii') + const body = b.slice(off + 4, off + 8 + len) + const stored = b.readUInt32BE(off + 8 + len) + if (crc32(body) !== stored) return { ok: false, why: `CRC 错误 @ ${type}` } + types.push(type) + if (type === 'IHDR') { + if (b.readUInt32BE(off + 8) !== W || b.readUInt32BE(off + 12) !== H) { + return { ok: false, why: 'IHDR 尺寸不符' } + } + } + if (type === 'IDAT') idat = b.slice(off + 8, off + 8 + len) + off += 12 + len + } + const raw = zlib.inflateSync(idat) + const stride = W * 4 + 1 // 每行 1 字节过滤器 + const px = (x, y) => y * stride + 1 + x * 4 + return { + ok: true, + sigOk, + chunks: types.join(','), + rawSize: raw.length === stride * H, + cornerAlpha: raw[px(4, 4) + 3], + centerAlpha: raw[px(256, 256) + 3], + centerRGB: [raw[px(256, 256)], raw[px(256, 256) + 1], raw[px(256, 256) + 2]] + } +} + +const dir = __dirname +for (const key of Object.keys(SCENES)) { + const buf = render(SCENES[key]) + const size = writePng(require('path').join(dir, `logo-${key}.png`), buf) + console.log(`\n=== Logo ${key.toUpperCase()} === ${size} bytes`) + console.log(ascii(buf)) + probe(buf, 'probe', POINTS) + const v = verifyPng(require('path').join(dir, `logo-${key}.png`)) + console.log( + ` png: ok=${v.ok} sig=${v.sigOk} chunks=${v.chunks} rawOK=${v.rawSize} ` + + `cornerA=${v.cornerAlpha} centerA=${v.centerAlpha}${v.why ? ' ' + v.why : ''}` + ) +} diff --git a/plugins/y-clipboard/index.html b/plugins/y-clipboard/index.html new file mode 100644 index 000000000..eaa17316c --- /dev/null +++ b/plugins/y-clipboard/index.html @@ -0,0 +1,11 @@ + + + + + + + +
+ + + diff --git a/plugins/y-clipboard/package-lock.json b/plugins/y-clipboard/package-lock.json new file mode 100644 index 000000000..ba8065751 --- /dev/null +++ b/plugins/y-clipboard/package-lock.json @@ -0,0 +1,1524 @@ +{ + "name": "y-clipboard", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "y-clipboard", + "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.npmmirror.com/@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.npmmirror.com/@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.9", + "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.29.9.tgz", + "integrity": "sha512-CjXrNHTnvqBVqHgdBysY3vk2T8tpJHb5/RMeHJBTyVa9xgugCB0CJTx/3oO8RV2QRQP391RWpB7D6hLjm8V9uA==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.8" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.8", + "resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.29.8.tgz", + "integrity": "sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==", + "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.npmmirror.com/@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.npmmirror.com/@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.npmmirror.com/@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.npmmirror.com/@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.npmmirror.com/@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.npmmirror.com/@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.npmmirror.com/@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.npmmirror.com/@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.npmmirror.com/@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.npmmirror.com/@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.npmmirror.com/@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.npmmirror.com/@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.npmmirror.com/@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.npmmirror.com/@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.npmmirror.com/@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.npmmirror.com/@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.npmmirror.com/@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.npmmirror.com/@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.npmmirror.com/@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.npmmirror.com/@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.npmmirror.com/@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.npmmirror.com/@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.npmmirror.com/@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.npmmirror.com/@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.npmmirror.com/@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.npmmirror.com/@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.6.0", + "resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.6.0.tgz", + "integrity": "sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==", + "license": "MIT" + }, + "node_modules/@napi-rs/lzma-linux-x64-gnu": { + "version": "1.5.1", + "resolved": "https://registry.npmmirror.com/@napi-rs/lzma-linux-x64-gnu/-/lzma-linux-x64-gnu-1.5.1.tgz", + "integrity": "sha512-oTXEIha4SsuXdTA4Iyskj0kpdx2yVXdhd75c2v3xGrHFfVMsbhTPZU/nMPL4sWKo4pBHm3aucLaqGlF696dTyQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^22.20 || ^24.12 || >=25" + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.63.5", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.63.5.tgz", + "integrity": "sha512-J25QJU+B78T4FhhBsNpLJyVWOi31mwtpcMwywHmOKH65Q9IWGA81gPj+dnwlhU8wktVriYE+tFAaQgrnJRzAZg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.63.5", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.63.5.tgz", + "integrity": "sha512-LDopB3zuZM5Ux9TT2luNEBJW/tYbGU2g1d+VpKk6I+gSKDb+/7sYE6M225gRQt4RbMX6MSwMsVR/phdjVUgRLg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.63.5", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.63.5.tgz", + "integrity": "sha512-wlJEERGfeuHeBavCL2qVnNacOK43NDoZM4sjkeRPymd04OAE9T1zBqDJgmZ+CIsPTYKwdzpUC8vmOw84dwY4Tg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.63.5", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.63.5.tgz", + "integrity": "sha512-4nJJGg5jbo2wwPP4JP+LfEBA3bvP8rU9CLuhp7jWvq9sxEyhjQFTFdrqi+/dHEin/pd8jpT0vcehIpnZtmEdcQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.63.5", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.63.5.tgz", + "integrity": "sha512-DrZbyCDF1hneuO6jRbvZ2D7+PIBM6yIwYnJpg2vIk58T+wuFpiaGZrfUr59lDWw45bg+IrpTGLPiNi/Fk4w3Cg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.63.5", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.63.5.tgz", + "integrity": "sha512-gqfUVMJMB3mehqywxp6hTBFfgtMQykZY19+cfiaYP0toIJLb/1DZRJHVkQQGP13W4TAwfZDWeg1qBcheTRioXQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.63.5", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.63.5.tgz", + "integrity": "sha512-CFmhpvAwzSaWMlN3VN7UtmoTihlZNzoP0juQib5TQRnYUyDV8dXeWOp29sobWAT6gXl/hQgAClLlEiYozQG3OQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.63.5", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.63.5.tgz", + "integrity": "sha512-Uc9H8eXCOayV6JLTH5bXKMId6qbhNHa818/BgYjm4jrlq3vZquC9cqyvHBw17xy5Mnj5f+I3gFK5JcEf3hSqrw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.63.5", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.63.5.tgz", + "integrity": "sha512-VcPr/szv/1BFw112Kt//fxulXt/JPqzzidU84iW68L2DdjnOO8QFUv2zTSYBEPHD6movBD4z+bbr5y60GYM7Jw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.63.5", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.63.5.tgz", + "integrity": "sha512-BnxtJ5/91BrIHYIkGrmjz/lbMhqEHt1dPFqIxIFR+jPn0xVc/oUSCtIT089zfp5ufwGDlYz2UC+Fe1SRBpYFbQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.63.5", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.63.5.tgz", + "integrity": "sha512-LrYcHZwF+fAMNKHYTOQ5osWM4AZF7YF6D+XtsjDyEvljtt11twc+zHVXBLNEjxVSUnKYsOhvVz4Z213eW02COQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.63.5", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.63.5.tgz", + "integrity": "sha512-nj7QKQePAAUpCpJHtg0pR0W/b92A9NO17JS3BAQmHDn/yhmkir2p8llrKY9TOhleKIaSzy1JhxS3T9FVld6coA==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.63.5", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.63.5.tgz", + "integrity": "sha512-5ylkX6dWMeBKge9nTU+Rxfb+ZfaCIJ9lRqIFaK0eAMcWp7OJbYnLveLgXmm0VrvuLKb8qIK+mHyH0qu88RM+iA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.63.5", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.63.5.tgz", + "integrity": "sha512-oHK4ZHYFDKjZviK34I+NwgfbGxgI7ztrNxj2hPTSSNFgeq1a/lEd7dHV2fdGAuTH4Iym3RHJg+vAbWaWG4B7Zg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.63.5", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.63.5.tgz", + "integrity": "sha512-UcetmHZ6XOXuUByiKZyQmb55ZPr0LABr3Ec/HB9wKZn6CEAFWZkE+hsJErJ9hbPBC7nI0dKuELx7CoV6IM7TMg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.63.5", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.63.5.tgz", + "integrity": "sha512-C5CmDPQBtvjVo8cgQsBs+w6WB0JLkiixhgi6hVLV11hERWdn/p0XcPU2OUcZzac9BPOFq7SbaHFa8r3SWEysCQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.63.5", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.63.5.tgz", + "integrity": "sha512-lHVQHJFKsuuxLMi3MQO9XVL8Tje3JR82CzB+QDKC5NWBcsIWuwsn9uIM5e3lBhI+fF1/s63qnyYqsg65+8rV/w==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.63.5", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.63.5.tgz", + "integrity": "sha512-3W9bTFcQNJn71cSJVM9RKIiZOy8DO/XLDii8Uv/Pm6WKqDRj7JV3ZfuXIEfyuy5LXpIzAbB/1M4Ukp9GKNa7nA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.63.5", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.63.5.tgz", + "integrity": "sha512-VDC7rRJlee/scpki96GZ27Omf6yU87s1YXwVTpjE5841faVlDYYT565rgfmoR1U0sqL7z5ivQSDjcsF6VRXyBA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.63.5", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.63.5.tgz", + "integrity": "sha512-z86Ok2p4pTdv5xqCKZsTooO7yBEiaJR/HzU3Wx8RmWsPoLppnMKROhJusQob8B3IE1ghC343kUW9rC2r+Wf3ig==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.63.5", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.63.5.tgz", + "integrity": "sha512-IzQmj+xXwQFGhMAMKMQVXkMwMZN3TqkJgAE0nSsqvVwWWciP4AIPMmWRqOQ2GfX7TUDZr+xqGFcBS36CRPGw0g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.63.5", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.63.5.tgz", + "integrity": "sha512-F6qpTaPc9bwBH85kjy0/BLmLSW1uv7AoOXCoRIkg2arlgCYlWYcAbiMkvZuAcaWk9TpCRG//okznLAqLGshkMw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.63.5", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.63.5.tgz", + "integrity": "sha512-igoDsTFhhwECBeGbUuLeIk7t8Y1apa+cs6mDWpx2EZ0ch7oEQgzHbFUXN9euoHekCAQzXdXApAGkV6jznS7tWw==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.63.5", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.63.5.tgz", + "integrity": "sha512-U3teMeMbXFmaM5D+OTJpsOXd+wV/qftIeYF9kBKL4v73641qyJmoXFtA28DQLsnmlyayEsTe72xpLHrArq6vHw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.63.5", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.63.5.tgz", + "integrity": "sha512-ypfC34F3RKXvCXBglGqGMsUSMKlgwd1HX9AOAlx9RoZZ6GaI42YHVeKpzg3JG+wpBUJYTG+NNZhqbDWL8tBZkw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@types/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmmirror.com/@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.npmmirror.com/@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.npmmirror.com/@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.npmmirror.com/@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.npmmirror.com/@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.43", + "resolved": "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.5.43.tgz", + "integrity": "sha512-zdiLhnbe1QQqgDT8xZMpNmyqZ3qlI+/Q/FHQco57Kwl/b05HhCzN6eVGN9QU9rbga4CrS0H5SYY8VGHZCt/1Hg==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.8", + "@vue/shared": "3.5.43", + "entities": "^7.0.1", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-dom": { + "version": "3.5.43", + "resolved": "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.5.43.tgz", + "integrity": "sha512-PEZoAk3NQmsn/ejMzSOCyTYqwGqczrWm70PuhBKjjv1+TCoQAaO/zOqNwjV+honlNstT5ILxtc+8r8UUfj+iEQ==", + "license": "MIT", + "dependencies": { + "@vue/compiler-core": "3.5.43", + "@vue/shared": "3.5.43" + } + }, + "node_modules/@vue/compiler-sfc": { + "version": "3.5.43", + "resolved": "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.5.43.tgz", + "integrity": "sha512-FCbrG3XNCRl+js3huuKx4IVHBLTvMkJhVepjbxSPu1gn4yWLaYtGNQdjJGZaMytXB6qb76qQDDmDSLy/vkmleQ==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.8", + "@vue/compiler-core": "3.5.43", + "@vue/compiler-dom": "3.5.43", + "@vue/compiler-ssr": "3.5.43", + "@vue/shared": "3.5.43", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.21", + "postcss": "^8.5.28", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-ssr": { + "version": "3.5.43", + "resolved": "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.5.43.tgz", + "integrity": "sha512-GF62orf7KiJX9RqrHNGrYBudsQGD0OhJ5nDs90O8UiDuS40+YMYomiXu6w6EuvtXuRDc3MSNis3EaaSKAVSWpg==", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.43", + "@vue/shared": "3.5.43" + } + }, + "node_modules/@vue/compiler-vue2": { + "version": "2.7.16", + "resolved": "https://registry.npmmirror.com/@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.npmmirror.com/@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.43", + "resolved": "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.5.43.tgz", + "integrity": "sha512-G/c9GyOZNI2jVaaS6OX1EF1SSFSv7H0ERqNTl4+DTFMlZmB5eVAB53aLQNam/7NL2NPtaDD7RdVrzf8uJzMuOA==", + "license": "MIT", + "dependencies": { + "@vue/shared": "3.5.43" + } + }, + "node_modules/@vue/runtime-core": { + "version": "3.5.43", + "resolved": "https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.5.43.tgz", + "integrity": "sha512-hU6U6VnVhBGQDpvlnnDlIB8ZGJBiOcgk2lh/0InltHiz3D8oSkluvuvY+do1G2H3+udeKFsmaBlgVYP7gXQzEw==", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.43", + "@vue/shared": "3.5.43" + } + }, + "node_modules/@vue/runtime-dom": { + "version": "3.5.43", + "resolved": "https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.5.43.tgz", + "integrity": "sha512-Bb2Jc0YjjJdMt1SJmb9b2L/IWd3I8lIT9x9eS/xvvP9CiVgna0ffua74xKRmt4/uSJ+0r4iN8ex1jrqkhQGWQw==", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.43", + "@vue/runtime-core": "3.5.43", + "@vue/shared": "3.5.43", + "csstype": "^3.2.3" + } + }, + "node_modules/@vue/server-renderer": { + "version": "3.5.43", + "resolved": "https://registry.npmmirror.com/@vue/server-renderer/-/server-renderer-3.5.43.tgz", + "integrity": "sha512-l2Ygjv9NehV94PSBxNWsAHC0j/eIIKbn92mBuWXAPGLnn6HfJ6MH5ubsd+Nk0YoZ5FRuxWI1P2VSoh+dbPQhCQ==", + "license": "MIT", + "dependencies": { + "@vue/compiler-ssr": "3.5.43", + "@vue/runtime-dom": "3.5.43", + "@vue/shared": "3.5.43" + } + }, + "node_modules/@vue/shared": { + "version": "3.5.43", + "resolved": "https://registry.npmmirror.com/@vue/shared/-/shared-3.5.43.tgz", + "integrity": "sha512-uksS7YGMR5NZyr4JNq0Rp+QyLns0ueaz20KwzIPW9R0LH1Vnt4E+XUM29PNseEbf1www2gOuhuDi5AKOIXag9Q==", + "license": "MIT" + }, + "node_modules/@ztools-center/ztools-api-types": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/@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.npmmirror.com/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.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "2.1.7", + "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.1.7.tgz", + "integrity": "sha512-uZbew1NqdmPDTMJ8ah1y+b+9QEJrfkXFk3RcTQw3X0jW/xRUvFKsg1CfQdSYGdTbXZWExtU3J3ccxtnfw1Fi0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmmirror.com/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.npmmirror.com/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.npmmirror.com/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.npmmirror.com/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.npmmirror.com/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.npmmirror.com/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.npmmirror.com/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.npmmirror.com/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.npmmirror.com/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.npmmirror.com/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.npmmirror.com/muggle-string/-/muggle-string-0.4.1.tgz", + "integrity": "sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.19", + "resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.19.tgz", + "integrity": "sha512-Y2tUNy4ouw6tq5oDSKeQYGOyhkUBhNOcGV/02KC+6kd9eDGqdZd++mjMiIDilrBYvjEnCYvVtsuHCuP+okSfug==", + "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.npmmirror.com/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.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.7", + "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-4.0.7.tgz", + "integrity": "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.5.28", + "resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.5.28.tgz", + "integrity": "sha512-RRuzqDtt5Y9h3quz5hWhK+TPnsmVs6WwSU6LkJMeY4HstUEDuYTG8UJSdawMRzmzAtV+KEoG8N3Qg2qLy5vM/A==", + "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.18", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/rollup": { + "version": "4.63.5", + "resolved": "https://registry.npmmirror.com/rollup/-/rollup-4.63.5.tgz", + "integrity": "sha512-KRWwmNLlPw5M7HcdYfm15oBv9n9LPtjzpzCIxS/phwqvPyxHSoKX6Y2YU3pxSPfy0CLquVgsx/j/hBi6OvH1Nw==", + "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": { + "@napi-rs/lzma-linux-x64-gnu": "1.5.1", + "@rollup/rollup-android-arm-eabi": "4.63.5", + "@rollup/rollup-android-arm64": "4.63.5", + "@rollup/rollup-darwin-arm64": "4.63.5", + "@rollup/rollup-darwin-x64": "4.63.5", + "@rollup/rollup-freebsd-arm64": "4.63.5", + "@rollup/rollup-freebsd-x64": "4.63.5", + "@rollup/rollup-linux-arm-gnueabihf": "4.63.5", + "@rollup/rollup-linux-arm-musleabihf": "4.63.5", + "@rollup/rollup-linux-arm64-gnu": "4.63.5", + "@rollup/rollup-linux-arm64-musl": "4.63.5", + "@rollup/rollup-linux-loong64-gnu": "4.63.5", + "@rollup/rollup-linux-loong64-musl": "4.63.5", + "@rollup/rollup-linux-ppc64-gnu": "4.63.5", + "@rollup/rollup-linux-ppc64-musl": "4.63.5", + "@rollup/rollup-linux-riscv64-gnu": "4.63.5", + "@rollup/rollup-linux-riscv64-musl": "4.63.5", + "@rollup/rollup-linux-s390x-gnu": "4.63.5", + "@rollup/rollup-linux-x64-gnu": "4.63.5", + "@rollup/rollup-linux-x64-musl": "4.63.5", + "@rollup/rollup-openbsd-x64": "4.63.5", + "@rollup/rollup-openharmony-arm64": "4.63.5", + "@rollup/rollup-win32-arm64-msvc": "4.63.5", + "@rollup/rollup-win32-ia32-msvc": "4.63.5", + "@rollup/rollup-win32-x64-gnu": "4.63.5", + "@rollup/rollup-win32-x64-msvc": "4.63.5", + "fsevents": "~2.3.2" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmmirror.com/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.npmmirror.com/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.npmmirror.com/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "devOptional": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/vite": { + "version": "6.4.3", + "resolved": "https://registry.npmmirror.com/vite/-/vite-6.4.3.tgz", + "integrity": "sha512-NTKlcQjlAK7MlQoyb6LgaqHc8sso/pVyUJYWMws3jg21uTJw/LddqIFPcPqP6PzpgbIcZyKI85sFE4HBrQDA8A==", + "dev": true, + "license": "MIT", + "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.2.0", + "resolved": "https://registry.npmmirror.com/vscode-uri/-/vscode-uri-3.2.0.tgz", + "integrity": "sha512-m2gXo3bn0G1kT9InzMf07fTbqMbGtyckj3bH5ktLO+1Ssv+yiATZ4dhwaQv9UZWxJh6E9IFGnQyjgWVDWVBDrg==", + "dev": true, + "license": "MIT" + }, + "node_modules/vue": { + "version": "3.5.43", + "resolved": "https://registry.npmmirror.com/vue/-/vue-3.5.43.tgz", + "integrity": "sha512-o5qZoksdnjIKvW1srZ3ab7pcDNYAerBjRe54D0LBLfRdCYFrSgBHVXokMas35czQc0//lmx4/tuY4ZNQ+Rf2Ng==", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.43", + "@vue/compiler-sfc": "3.5.43", + "@vue/runtime-dom": "3.5.43", + "@vue/server-renderer": "3.5.43", + "@vue/shared": "3.5.43" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/vue-tsc": { + "version": "2.2.12", + "resolved": "https://registry.npmmirror.com/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/y-clipboard/package.json b/plugins/y-clipboard/package.json new file mode 100644 index 000000000..f78a0dec4 --- /dev/null +++ b/plugins/y-clipboard/package.json @@ -0,0 +1,20 @@ +{ + "name": "y-clipboard", + "version": "1.0.0", + "description": "A ZTools plugin", + "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/y-clipboard/src-ztools/logo.png b/plugins/y-clipboard/src-ztools/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..0c7f6c5e4d3031578f903566146f26386948e9e3 GIT binary patch literal 13041 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 literal 0 HcmV?d00001 diff --git a/plugins/y-clipboard/src-ztools/plugin.json b/plugins/y-clipboard/src-ztools/plugin.json new file mode 100644 index 000000000..8c3fca0ab --- /dev/null +++ b/plugins/y-clipboard/src-ztools/plugin.json @@ -0,0 +1,22 @@ +{ + "$schema": "node_modules/@ztools-center/ztools-api-types/resource/ztools.schema.json", + "name": "y-clipboard", + "title": "Y剪贴板", + "description": "分类清晰、响应飞快的剪贴板历史管理:文本 / 链接 / 代码 / 图片 / 文件,支持收藏、搜索与键盘流操作", + "author": "ysysyss", + "version": "1.0.0", + "main": "dist/index.html", + "preload": "preload/services.js", + "logo": "logo.png", + "development": { + "main": "http://localhost:5173" + }, + "features": [ + { + "code": "clipboard", + "explain": "剪贴板历史管理", + "icon": "logo.png", + "cmds": ["剪贴板", "clipboard", "clip", "历史"] + } + ] +} diff --git a/plugins/y-clipboard/src-ztools/preload/package.json b/plugins/y-clipboard/src-ztools/preload/package.json new file mode 100644 index 000000000..5bbefffba --- /dev/null +++ b/plugins/y-clipboard/src-ztools/preload/package.json @@ -0,0 +1,3 @@ +{ + "type": "commonjs" +} diff --git a/plugins/y-clipboard/src-ztools/preload/services.js b/plugins/y-clipboard/src-ztools/preload/services.js new file mode 100644 index 000000000..5d5f2db55 --- /dev/null +++ b/plugins/y-clipboard/src-ztools/preload/services.js @@ -0,0 +1,14 @@ +/** + * Y剪贴板 preload + * + * 本插件的核心能力(剪贴板历史、搜索、写入)均由宿主提供的 + * window.ztools.clipboard / window.ztools.dbStorage 完成,无需额外 + * Node.js 能力。此文件保留最小实现,仅做一次宿主环境探测, + * 方便在控制台快速确认 preload 是否生效。 + */ + +window.services = { + ready() { + return typeof window.ztools !== 'undefined' + } +} diff --git a/plugins/y-clipboard/src/App.vue b/plugins/y-clipboard/src/App.vue new file mode 100644 index 000000000..7d329fff7 --- /dev/null +++ b/plugins/y-clipboard/src/App.vue @@ -0,0 +1,142 @@ + + + + + diff --git a/plugins/y-clipboard/src/api.ts b/plugins/y-clipboard/src/api.ts new file mode 100644 index 000000000..213c1aee5 --- /dev/null +++ b/plugins/y-clipboard/src/api.ts @@ -0,0 +1,371 @@ +import type { ClipboardRecord, FavoriteSnapshot, PageResult } from './types' + +/** + * 宿主 API 封装层。 + * + * 宿主 getHistory / search 的返回结构文档未给出精确字段, + * 这里做一层防御性归一化:无论返回 {list} / {rows} / {items} / {data} + * 还是裸数组,统一收敛成 ClipboardRecord[]。 + * + * 浏览器直接访问 localhost:5173 时无 window.ztools, + * 自动切换到 mock 数据,保证 UI 可以独立开发调试。 + */ + +const isHost = () => typeof window !== 'undefined' && typeof window.ztools !== 'undefined' +export const isDevMock = () => !isHost() + +/* ------------------------------------------------------------------ */ +/* 工具 */ +/* ------------------------------------------------------------------ */ + +function djb2(str: string): string { + let h = 5381 + for (let i = 0; i < str.length; i++) h = ((h << 5) + h + str.charCodeAt(i)) >>> 0 + return 'h' + h.toString(36) + str.length.toString(36) +} + +export function contentId(kind: string, content: string): string { + return djb2(kind + '\u0000' + content) +} + +function toNum(v: unknown): number { + if (typeof v === 'number') return v + if (typeof v === 'string') { + const n = Number(v) + if (!Number.isNaN(n)) return n + const d = new Date(v).getTime() + if (!Number.isNaN(d)) return d + } + return 0 +} + +function pick(obj: Record, keys: string[]): unknown { + for (const k of keys) { + const v = obj[k] + if (v !== undefined && v !== null && v !== '') return v + } + return undefined +} + +/** 图片路径 → 可显示 src(data: 原样;绝对路径转 file://) */ +export function toImgSrc(p: string): string { + if (!p) return '' + if (/^(data:|https?:|file:)/i.test(p)) return p + const norm = p.replace(/\\/g, '/') + return 'file://' + (norm.startsWith('/') ? '' : '/') + encodeURI(norm) +} + +/* ------------------------------------------------------------------ */ +/* 分类判定 */ +/* ------------------------------------------------------------------ */ + +const CODE_HINTS = [ + 'function ', 'const ', 'let ', '=>', 'import ', 'export ', 'class ', + 'return ', 'console.', ' { + const t = text.trim() + if (!t) return 'text' + if (/^#([0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$/i.test(t)) return 'color' + if (/^(https?:\/\/|www\.)\S+$/i.test(t)) return 'link' + if (t.length >= 24) { + const hits = CODE_HINTS.reduce((n, h) => (t.includes(h) ? n + 1 : n), 0) + if (hits >= 2) return 'code' + } + return 'text' +} + +/* ------------------------------------------------------------------ */ +/* 归一化 */ +/* ------------------------------------------------------------------ */ + +function normalizeRecord(raw: unknown): ClipboardRecord | null { + if (!raw || typeof raw !== 'object') return null + const o = raw as Record + + const rawType = String( + pick(o, ['type', 'kind', 'contentType']) ?? 'text' + ).toLowerCase() + + const filesRaw = pick(o, ['files', 'paths', 'fileList', 'file']) + let files: string[] | undefined + if (Array.isArray(filesRaw)) { + files = filesRaw.map(String).filter(Boolean) + } else if (typeof filesRaw === 'string' && filesRaw) { + files = [filesRaw] + } + + let content = '' + let kind: ClipboardRecord['kind'] + + if (rawType.includes('image')) { + kind = 'image' + content = String( + pick(o, ['thumbnail', 'image', 'dataUrl', 'dataURL', 'content', 'data', 'path', 'url', 'src']) ?? '' + ) + if (!content) return null + } else if (rawType.includes('file') || (files && files.length > 0)) { + kind = 'file' + if (!files || files.length === 0) return null + content = files[0] + } else { + content = String(pick(o, ['content', 'text', 'value', 'data']) ?? '') + if (!content) return null + kind = detectKind(content) + } + + const id = String(pick(o, ['id', '_id', 'recordId']) ?? djb2(kind + '\u0000' + content)) + + return { + id, + kind, + rawType, + content, + files, + createdAt: toNum(pick(o, ['createdAt', 'createAt', 'time', 'timestamp', 'date', 'updated_at'])), + raw + } +} + +function extractList(res: unknown): unknown[] { + if (Array.isArray(res)) return res + if (res && typeof res === 'object') { + const o = res as Record + for (const k of ['list', 'rows', 'items', 'data', 'records', 'result']) { + if (Array.isArray(o[k])) return o[k] + } + // { success, data: { list } } 双层结构 + if (o.data && typeof o.data === 'object') return extractList(o.data) + } + return [] +} + +function toRecords(res: unknown): ClipboardRecord[] { + return extractList(res) + .map(normalizeRecord) + .filter((r): r is ClipboardRecord => r !== null) +} + +/* ------------------------------------------------------------------ */ +/* 宿主 API */ +/* ------------------------------------------------------------------ */ + +export const host = { + async getHistory(page: number, pageSize: number): Promise { + const res = await (window.ztools as any).clipboard.getHistory(page, pageSize) + const items = toRecords(res) + return { items, hasMore: items.length >= pageSize } + }, + + async search(keyword: string): Promise { + const res = await (window.ztools as any).clipboard.search(keyword) + return toRecords(res) + }, + + async remove(id: string): Promise { + const res = await (window.ztools as any).clipboard.delete(id) + return !res || (res as any).success !== false + }, + + /** 写回剪贴板(默认同时模拟粘贴到之前焦点窗口) */ + async write(id: string, paste = true): Promise { + await (window.ztools as any).clipboard.write(id, paste) + }, + + /** 按内容写剪贴板(收藏快照等无宿主 id 的场景) */ + async writeContent( + type: 'text' | 'image' | 'file', + content: string | string[], + paste = true + ): Promise { + await (window.ztools as any).clipboard.writeContent({ type, content }, paste) + }, + + async clear(): Promise { + const res = await (window.ztools as any).clipboard.clear() + return Number((res as any)?.count ?? 0) + }, + + onChange(cb: () => void): void { + ;(window.ztools as any).clipboard.onChange(cb) + }, + + outPlugin(): void { + void (window.ztools as any).outPlugin?.() + }, + + setSubInput(onChange: (text: string) => void, placeholder: string): void { + ;(window.ztools as any).setSubInput({ text: onChange }, placeholder, true) + }, + + toast(message: string): void { + void (window.ztools as any).showToast?.(message) + }, + + theme(): { dark: boolean; accent: string } { + try { + const info = (window.ztools as any).getThemeInfo?.() ?? {} + return { + dark: window.ztools.isDarkColors?.() ?? false, + accent: String(info.primaryColor || '') + } + } catch { + return { dark: false, accent: '' } + } + }, + + onThemeChange(cb: () => void): void { + ;(window.ztools as any).onThemeChange?.(cb) + } +} + +/* ------------------------------------------------------------------ */ +/* 浏览器开发 mock */ +/* ------------------------------------------------------------------ */ + +const MOCK_TEXTS: Array<[string, string]> = [ + ['text', '会议纪要:周三评审剪贴板插件交互稿,重点看键盘流是否顺'], + ['text', '发票抬头:北京某某科技有限公司 税号 91110108MA01XXXXXX'], + ['text', '地铁 10 号线换乘 6 号线,C 口出直走 200 米'], + ['link', 'https://vuejs.org/guide/introduction.html'], + ['link', 'https://github.com/vuejs/core/releases'], + ['link', 'https://ztoolscenter.github.io/ZTools-doc/first-plugin.html'], + ['code', "const debounce = (fn, ms) => { let t; return (...a) => { clearTimeout(t); t = setTimeout(() => fn(...a), ms) } }"], + ['code', 'import { createApp } from \'vue\'\nimport App from \'./App.vue\'\ncreateApp(App).mount(\'#app\')'], + ['code', 'SELECT id, content, created_at FROM clipboard ORDER BY created_at DESC LIMIT 50;'], + ['color', '#5B8DEF'], + ['color', '#0F6E56'], + ['text', 'ssh -p 2222 dev@10.0.0.12'], + ['text', '取件码 8-2-3069,丰巢快递柜'], +] + +const MOCK_FILES = [ + ['E:\\A_YSYSYSS_workspace\\y-clipboard\\src-ztools\\plugin.json'], + ['D:\\Downloads\\设计稿-首页-v3.fig', 'D:\\Downloads\\设计稿-详情-v3.fig'], +] + +function mockImage(i: number): string { + const hue = (i * 47) % 360 + const svg = `` + return 'data:image/svg+xml;charset=utf-8,' + encodeURIComponent(svg) +} + +function buildMockData(): any[] { + const out: any[] = [] + const now = Date.now() + for (let i = 0; i < 72; i++) { + const [kind, content] = MOCK_TEXTS[i % MOCK_TEXTS.length] + const age = (i * 23 + (i % 7) * 41) * 60 * 1000 // 分布在过去约 48h + if (kind === 'text' || kind === 'link' || kind === 'code' || kind === 'color') { + out.push({ id: 'mock-' + i, type: 'text', content, createdAt: now - age }) + } else if (i % 11 === 5) { + out.push({ id: 'mock-img-' + i, type: 'image', thumbnail: mockImage(i), createdAt: now - age }) + } else if (i % 11 === 8) { + const [f] = MOCK_FILES[i % MOCK_FILES.length] + const files = i % 2 === 0 ? [f] : MOCK_FILES[i % MOCK_FILES.length] + out.push({ id: 'mock-file-' + i, type: 'file', files, createdAt: now - age }) + } + } + return out +} + +let mockDb = buildMockData() + +const mock = { + async getHistory(page: number, pageSize: number): Promise { + await sleep(60) + const start = (page - 1) * pageSize + const items = toRecords(mockDb.slice(start, start + pageSize)) + return { items, hasMore: start + pageSize < mockDb.length } + }, + + async search(keyword: string): Promise { + await sleep(80) + const kw = keyword.toLowerCase() + return toRecords( + mockDb.filter((r: any) => String(r.content ?? '').toLowerCase().includes(kw)) + ) + }, + + async remove(id: string): Promise { + mockDb = mockDb.filter((r: any) => r.id !== id) + return true + }, + + async write(_id: string): Promise { + mock.toast('已复制(开发模式不执行真实粘贴)') + }, + + async writeContent(): Promise { + mock.toast('已复制(开发模式不执行真实粘贴)') + }, + + async clear(): Promise { + const n = mockDb.length + mockDb = [] + return n + }, + + onChange(_cb: () => void): void { + /* 开发模式不监听 */ + }, + + outPlugin(): void { + mock.toast('开发模式:此处会退出插件') + }, + + setSubInput(_onChange: (t: string) => void, _ph: string): void { + /* 开发模式用页面内搜索框 */ + }, + + toast(message: string): void { + console.info('[toast]', message) + }, + + theme(): { dark: boolean; accent: string } { + return { dark: window.matchMedia?.('(prefers-color-scheme: dark)').matches ?? false, accent: '#5B8DEF' } + }, + + onThemeChange(_cb: () => void): void { + /* noop */ + } +} + +function sleep(ms: number): Promise { + return new Promise((r) => setTimeout(r, ms)) +} + +/** 统一出口:真实宿主或 mock */ +export const api = isHost() ? host : mock + +/* ------------------------------------------------------------------ */ +/* 收藏持久化(宿主 dbStorage / mock localStorage) */ +/* ------------------------------------------------------------------ */ + +const FAV_KEY = 'y-clipboard:favorites' +const FAV_LIMIT = 200 + +function rawStorage(): Pick { + if (isHost()) return window.ztools.dbStorage as any + return localStorage +} + +export const favoritesStore = { + load(): FavoriteSnapshot[] { + try { + const raw = rawStorage().getItem(FAV_KEY) + const parsed = raw ? JSON.parse(raw) : [] + return Array.isArray(parsed) ? parsed : [] + } catch { + return [] + } + }, + + save(list: FavoriteSnapshot[]): void { + try { + rawStorage().setItem(FAV_KEY, JSON.stringify(list.slice(0, FAV_LIMIT))) + } catch { /* 存储失败静默 */ } + } +} diff --git a/plugins/y-clipboard/src/components/ClipboardItem.vue b/plugins/y-clipboard/src/components/ClipboardItem.vue new file mode 100644 index 000000000..47b369487 --- /dev/null +++ b/plugins/y-clipboard/src/components/ClipboardItem.vue @@ -0,0 +1,205 @@ + + + + + diff --git a/plugins/y-clipboard/src/components/Sidebar.vue b/plugins/y-clipboard/src/components/Sidebar.vue new file mode 100644 index 000000000..0d468bcb9 --- /dev/null +++ b/plugins/y-clipboard/src/components/Sidebar.vue @@ -0,0 +1,108 @@ + + + + + diff --git a/plugins/y-clipboard/src/components/Toolbar.vue b/plugins/y-clipboard/src/components/Toolbar.vue new file mode 100644 index 000000000..bb95524fb --- /dev/null +++ b/plugins/y-clipboard/src/components/Toolbar.vue @@ -0,0 +1,114 @@ + + + + + diff --git a/plugins/y-clipboard/src/components/VirtualList.vue b/plugins/y-clipboard/src/components/VirtualList.vue new file mode 100644 index 000000000..44300ed16 --- /dev/null +++ b/plugins/y-clipboard/src/components/VirtualList.vue @@ -0,0 +1,118 @@ + + + + + diff --git a/plugins/y-clipboard/src/composables/useStore.ts b/plugins/y-clipboard/src/composables/useStore.ts new file mode 100644 index 000000000..39f85ab2e --- /dev/null +++ b/plugins/y-clipboard/src/composables/useStore.ts @@ -0,0 +1,299 @@ +import { computed, reactive, ref, watch } from 'vue' +import { api, favoritesStore, isDevMock, contentId, toImgSrc } from '../api' +import type { Category, ClipboardRecord, FavoriteSnapshot, ItemKind } from '../types' + +const PAGE_SIZE = 60 +const SEARCH_DEBOUNCE = 100 + +/* ------------------------------------------------------------------ */ +/* 单例状态 */ +/* ------------------------------------------------------------------ */ + +const records = ref([]) +const favorites = ref([]) +const activeCat = ref('all') +const query = ref('') +const selectedIndex = ref(0) +const page = ref(0) +const hasMore = ref(false) +const loading = ref(false) +const remoteSearching = ref(false) + +const favIds = computed(() => new Set(favorites.value.map((f) => f.id))) + +/* ------------------------------------------------------------------ */ +/* 过滤 */ +/* ------------------------------------------------------------------ */ + +function matchCat(r: ClipboardRecord): boolean { + if (activeCat.value === 'all') return true + if (activeCat.value === 'star') return favIds.value.has(favKey(r)) + return r.kind === activeCat.value +} + +function matchQuery(r: ClipboardRecord): boolean { + const q = query.value.trim().toLowerCase() + if (!q) return true + if (r.kind === 'file' && r.files) { + return r.files.some((f) => f.toLowerCase().includes(q)) + } + return r.content.toLowerCase().includes(q) +} + +/** 收藏在记录列表中的 key(同内容同分类视为同一条) */ +function favKey(r: ClipboardRecord): string { + return contentId(r.kind, r.files ? r.files.join('|') : r.content) +} + +/** star 分类下的"记录":直接由收藏快照构造,删除原记录也不丢 */ +const favoriteRecords = computed(() => + favorites.value.map((f) => ({ + id: f.id, + kind: f.kind, + rawType: f.kind, + content: f.content, + files: f.files, + createdAt: f.createdAt, + raw: null + })) +) + +const filtered = computed(() => { + if (activeCat.value === 'star') { + const q = query.value.trim().toLowerCase() + if (!q) return favoriteRecords.value + return favoriteRecords.value.filter(matchQuery) + } + return records.value.filter((r) => matchCat(r) && matchQuery(r)) +}) + +const counts = reactive>({ + all: 0, text: 0, link: 0, code: 0, color: 0, image: 0, file: 0, star: 0 +}) + +function recount(): void { + const c: Record = { all: records.value.length, star: favorites.value.length } + for (const r of records.value) c[r.kind] = (c[r.kind] ?? 0) + 1 + for (const k of Object.keys(counts) as Category[]) { + counts[k] = c[k] ?? 0 + } +} + +/* ------------------------------------------------------------------ */ +/* 加载 */ +/* ------------------------------------------------------------------ */ + +let loadSeq = 0 + +async function loadFirst(): Promise { + const seq = ++loadSeq + loading.value = true + try { + const res = await api.getHistory(1, PAGE_SIZE) + if (seq !== loadSeq) return + records.value = res.items + page.value = 1 + hasMore.value = res.hasMore + selectedIndex.value = 0 + recount() + } finally { + if (seq === loadSeq) loading.value = false + } +} + +async function loadMore(): Promise { + if (loading.value || !hasMore.value || query.value.trim()) return + const seq = ++loadSeq + loading.value = true + try { + const res = await api.getHistory(page.value + 1, PAGE_SIZE) + if (seq !== loadSeq) return + const seen = new Set(records.value.map((r) => r.id)) + records.value = records.value.concat(res.items.filter((r) => !seen.has(r.id))) + page.value += 1 + hasMore.value = res.hasMore + recount() + } finally { + if (seq === loadSeq) loading.value = false + } +} + +/* ------------------------------------------------------------------ */ +/* 搜索:本地即时过滤 + 远端防抖补充 */ +/* ------------------------------------------------------------------ */ + +let searchTimer: ReturnType | null = null + +function setQuery(q: string): void { + query.value = q + selectedIndex.value = 0 + if (searchTimer) clearTimeout(searchTimer) + const kw = q.trim() + if (!kw) { + remoteSearching.value = false + if (records.value.length === 0) void loadFirst() + return + } + searchTimer = setTimeout(async () => { + remoteSearching.value = true + try { + const remote = await api.search(kw) + if (query.value.trim() !== kw) return + const seen = new Set(records.value.map((r) => r.id)) + const fresh = remote.filter((r) => !seen.has(r.id)) + if (fresh.length) { + records.value = fresh.concat(records.value) + recount() + } + } finally { + remoteSearching.value = false + } + }, SEARCH_DEBOUNCE) +} + +/* ------------------------------------------------------------------ */ +/* 动作 */ +/* ------------------------------------------------------------------ */ + +async function copyRecord(r: ClipboardRecord, exit = true): Promise { + try { + const isSnapshot = activeCat.value === 'star' || !r.raw + if (isSnapshot) { + if (r.kind === 'file' && r.files) await api.writeContent('file', r.files) + else if (r.kind === 'image') await api.writeContent('image', r.content) + else await api.writeContent('text', r.content) + } else { + await api.write(r.id) + } + if (exit) api.outPlugin() + } catch (e) { + api.toast('复制失败:' + (e instanceof Error ? e.message : String(e))) + } +} + +async function deleteRecord(r: ClipboardRecord): Promise { + const idx = filtered.value.findIndex((x) => x.id === r.id) + const ok = await api.remove(r.id) + if (!ok) { + api.toast('删除失败') + return + } + if (activeCat.value === 'star') { + favorites.value = favorites.value.filter((f) => f.id !== r.id) + favoritesStore.save(favorites.value) + recount() + } else { + records.value = records.value.filter((x) => x.id !== r.id) + recount() + } + if (idx >= 0 && idx < filtered.value.length) { + selectedIndex.value = Math.min(idx, filtered.value.length - 1) + } else if (filtered.value.length > 0) { + selectedIndex.value = filtered.value.length - 1 + } else { + selectedIndex.value = 0 + } +} + +function toggleStar(r: ClipboardRecord): void { + const key = favKey(r) + if (favIds.value.has(key)) { + favorites.value = favorites.value.filter((f) => f.id !== key) + } else { + const snap: FavoriteSnapshot = { + id: key, + kind: r.kind, + content: r.content, + files: r.files, + createdAt: r.createdAt || Date.now() + } + favorites.value = [snap, ...favorites.value].slice(0, 200) + } + favoritesStore.save(favorites.value) + recount() +} + +async function clearAll(): Promise { + const n = await api.clear() + if (n > 0 || isDevMock()) { + records.value = [] + hasMore.value = false + recount() + api.toast(`已清空 ${n} 条记录`) + } +} + +function setCat(cat: Category): void { + activeCat.value = cat + selectedIndex.value = 0 +} + +function moveSelection(delta: number): void { + const len = filtered.value.length + if (len === 0) return + selectedIndex.value = Math.min(len - 1, Math.max(0, selectedIndex.value + delta)) +} + +/* 过滤结果变化时收拢选中下标,避免越界空选 */ +watch(filtered, (list) => { + if (selectedIndex.value >= list.length) selectedIndex.value = Math.max(0, list.length - 1) +}) + +/* ------------------------------------------------------------------ */ +/* 初始化 */ +/* ------------------------------------------------------------------ */ + +let inited = false + +function init(): void { + if (inited) return + inited = true + + favorites.value = favoritesStore.load() + + api.setSubInput((payload: unknown) => { + const text = typeof payload === 'string' ? payload : String((payload as any)?.text ?? '') + setQuery(text) + }, '搜索剪贴板历史') + + api.onChange(async (payload?: unknown) => { + // 变化项结构未知:能归一化就 prepend,否则保守重载第一页 + const maybe = Array.isArray(payload) ? payload[0] : payload + if (maybe && typeof maybe === 'object') { + try { + const res = await api.getHistory(1, 5) + const seen = new Set(records.value.map((r) => r.id)) + const fresh = res.items.filter((r) => !seen.has(r.id)) + if (fresh.length) { + records.value = fresh.concat(records.value) + recount() + return + } + if (res.items.length) { + records.value = res.items + recount() + return + } + } catch { /* fallthrough */ } + } + void loadFirst() + }) + + void loadFirst() +} + +export function useStore() { + return { + records, favorites, activeCat, query, selectedIndex, + loading, remoteSearching, hasMore, counts, filtered, + init, loadFirst, loadMore, setQuery, setCat, + copyRecord, deleteRecord, toggleStar, clearAll, moveSelection, + favKey + } +} + +export type Store = ReturnType + +/** 供 ClipboardItem 使用的图片 src 转换(避免组件直接依赖 api 内部) */ +export { toImgSrc } +export type { Category, ItemKind } diff --git a/plugins/y-clipboard/src/env.d.ts b/plugins/y-clipboard/src/env.d.ts new file mode 100644 index 000000000..a0b822a7e --- /dev/null +++ b/plugins/y-clipboard/src/env.d.ts @@ -0,0 +1,21 @@ +/// +/// + +declare module '*.vue' { + import type { DefineComponent } from 'vue' + const component: DefineComponent, Record, unknown> + export default component +} + +// Preload services 类型声明(对应 src-ztools/preload/services.js) +interface Services { + ready: () => boolean +} + +declare global { + interface Window { + services: Services + } +} + +export {} diff --git a/plugins/y-clipboard/src/main.css b/plugins/y-clipboard/src/main.css new file mode 100644 index 000000000..15bcd2a0a --- /dev/null +++ b/plugins/y-clipboard/src/main.css @@ -0,0 +1,102 @@ +/* ===== 主题变量 ===== */ +:root { + --bg: #f6f7f9; + --panel: #ffffff; + --border: rgba(15, 20, 32, 0.08); + --border-strong: rgba(15, 20, 32, 0.16); + --text: #1f2329; + --text-2: #5f6570; + --text-3: #949aa3; + --hover: rgba(15, 20, 32, 0.045); + --active: rgba(15, 20, 32, 0.09); + --accent: #3377ff; + --accent-weak: rgba(51, 119, 255, 0.12); + --danger: #e5484d; + --danger-weak: rgba(229, 72, 77, 0.1); + --star: #f5a623; + + /* 分类色 */ + --c-text: #6b7280; + --c-link: #2563eb; + --c-code: #7c3aed; + --c-color: #db2777; + --c-image: #0d9488; + --c-file: #d97706; + + --row-h: 72px; + --radius: 8px; +} + +.dark { + --bg: #1b1c1f; + --panel: #232428; + --border: rgba(235, 240, 250, 0.09); + --border-strong: rgba(235, 240, 250, 0.18); + --text: #e6e8eb; + --text-2: #a8adb5; + --text-3: #6f757e; + --hover: rgba(235, 240, 250, 0.06); + --active: rgba(235, 240, 250, 0.12); + --accent-weak: rgba(120, 168, 255, 0.16); + + --c-text: #9aa1ab; + --c-link: #6ea8ff; + --c-code: #b493f5; + --c-color: #f286b5; + --c-image: #4fc9b8; + --c-file: #eeb25f; +} + +* { box-sizing: border-box; margin: 0; padding: 0; } + +html, body, #app { height: 100%; } + +body { + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', + 'Microsoft YaHei', 'Noto Sans SC', sans-serif; + font-size: 13px; + color: var(--text); + background: var(--bg); + -webkit-font-smoothing: antialiased; + user-select: none; + overflow: hidden; +} + +button { + font: inherit; + color: inherit; + background: none; + border: none; + cursor: pointer; +} + +/* 滚动条 */ +::-webkit-scrollbar { width: 8px; } +::-webkit-scrollbar-thumb { + background: var(--border-strong); + border-radius: 4px; +} +::-webkit-scrollbar-track { background: transparent; } + +/* ===== 布局骨架 ===== */ +.app { + display: flex; + flex-direction: column; + height: 100vh; + background: var(--panel); +} + +.app-body { + display: flex; + flex: 1; + min-height: 0; +} + +/* ===== 图标 ===== */ +.icon-svg { width: 16px; height: 16px; flex: none; } + +/* ===== 动画 ===== */ +@keyframes fade-in { + from { opacity: 0; transform: translateY(4px); } + to { opacity: 1; transform: none; } +} diff --git a/plugins/y-clipboard/src/main.ts b/plugins/y-clipboard/src/main.ts new file mode 100644 index 000000000..8a3c77bc5 --- /dev/null +++ b/plugins/y-clipboard/src/main.ts @@ -0,0 +1,5 @@ +import { createApp } from 'vue' +import './main.css' +import App from './App.vue' + +createApp(App).mount('#app') diff --git a/plugins/y-clipboard/src/types.ts b/plugins/y-clipboard/src/types.ts new file mode 100644 index 000000000..26af53c52 --- /dev/null +++ b/plugins/y-clipboard/src/types.ts @@ -0,0 +1,36 @@ +/** 内容分类 */ +export type ItemKind = 'text' | 'link' | 'code' | 'color' | 'image' | 'file' + +export type Category = 'all' | ItemKind | 'star' + +/** 归一化后的剪贴板记录(无论宿主返回什么结构,UI 只面对这个) */ +export interface ClipboardRecord { + /** 宿主记录 id(无 id 时用内容 hash 代替) */ + id: string + /** 分类结果 */ + kind: ItemKind + /** 原始类型标记 text / image / file ... */ + rawType: string + /** 文本内容;图片为 dataURL/路径;文件为主路径 */ + content: string + /** 文件类记录的完整路径列表 */ + files?: string[] + /** 创建时间戳(ms),未知为 0 */ + createdAt: number + /** 原始记录,写回宿主时可能需要 */ + raw?: unknown +} + +export interface PageResult { + items: ClipboardRecord[] + hasMore: boolean +} + +export interface FavoriteSnapshot { + /** 快照 id:生成时基于内容 */ + id: string + kind: ItemKind + content: string + files?: string[] + createdAt: number +} diff --git a/plugins/y-clipboard/src/utils/format.ts b/plugins/y-clipboard/src/utils/format.ts new file mode 100644 index 000000000..2cab95b48 --- /dev/null +++ b/plugins/y-clipboard/src/utils/format.ts @@ -0,0 +1,71 @@ +import type { ClipboardRecord, ItemKind } from '../types' + +/** 相对时间:刚刚 / n 分钟前 / n 小时前 / 昨天 / MM-DD / YYYY-MM-DD */ +export function relTime(ts: number): string { + if (!ts) return '' + const diff = Date.now() - ts + if (diff < 60_000) return '刚刚' + if (diff < 3_600_000) return `${Math.floor(diff / 60_000)} 分钟前` + if (diff < 86_400_000) return `${Math.floor(diff / 3_600_000)} 小时前` + if (diff < 172_800_000) return '昨天' + const d = new Date(ts) + const md = `${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}` + if (d.getFullYear() === new Date().getFullYear()) return md + return `${d.getFullYear()}-${md}` +} + +/** 文本预览:压掉多余空白,折叠换行 */ +export function previewText(text: string, max = 240): string { + const t = text.replace(/\s+/g, ' ').trim() + return t.length > max ? t.slice(0, max) + '…' : t +} + +/** 文件路径列表 → 文件名列表 */ +export function fileNames(files: string[]): string { + return files.map((f) => f.replace(/[\\/]+/g, '/').split('/').pop() || f).join('、') +} + +/** 字节数描述(文件/图片大小如有) */ +export function humanSize(bytes?: number): string { + if (!bytes || bytes <= 0) return '' + const units = ['B', 'KB', 'MB', 'GB'] + let i = 0 + let n = bytes + while (n >= 1024 && i < units.length - 1) { + n /= 1024 + i++ + } + return `${n.toFixed(n >= 100 || i === 0 ? 0 : 1)} ${units[i]}` +} + +export const KIND_META: Record = { + text: { label: '文本', color: 'var(--c-text)', icon: 'M4 7h16M4 12h16M4 17h10' }, + link: { label: '链接', color: 'var(--c-link)', icon: 'M10 14a5 5 0 0 0 7.07 0l3-3a5 5 0 0 0-7.07-7.07L11.5 5.4M14 10a5 5 0 0 0-7.07 0l-3 3a5 5 0 0 0 7.07 7.07l1.5-1.47' }, + code: { label: '代码', color: 'var(--c-code)', icon: 'M8 6l-5 6 5 6M16 6l5 6-5 6M13 4l-2 16' }, + color: { label: '颜色', color: 'var(--c-color)', icon: 'M12 3v3m0 12v3M3 12h3m12 0h3M5.6 5.6l2.1 2.1m8.6 8.6l2.1 2.1m0-12.8l-2.1 2.1M7.7 16.3l-2.1 2.1' }, + image: { label: '图片', color: 'var(--c-image)', icon: 'M3 5h18v14H3zM3 15l5-4 4 3 3-2 6 5M15.5 9.5a1 1 0 1 0 0-.01' }, + file: { label: '文件', color: 'var(--c-file)', icon: 'M6 2h8l4 4v16H6zM14 2v5h4' } +} + +/** 颜色色板展示(#hex 记录) */ +export function isHexColor(t: string): boolean { + return /^#([0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$/i.test(t.trim()) +} + +/** 记录的次级说明文案(空串表示不显示) */ +export function recordMeta(r: ClipboardRecord): string { + if (r.kind === 'image') return '' + if (r.kind === 'file' && r.files) return `${r.files.length} 个文件` + if (r.kind === 'color') return '颜色值' + if (r.kind === 'link') return hostname(r.content) + if (r.kind === 'code') return '代码片段' + return `${r.content.length} 字符` +} + +function hostname(url: string): string { + try { + return new URL(url).hostname + } catch { + return url.split('/')[2] || url + } +} diff --git a/plugins/y-clipboard/tsconfig.json b/plugins/y-clipboard/tsconfig.json new file mode 100644 index 000000000..39b73bc6f --- /dev/null +++ b/plugins/y-clipboard/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/y-clipboard/vite.config.js b/plugins/y-clipboard/vite.config.js new file mode 100644 index 000000000..ce331609e --- /dev/null +++ b/plugins/y-clipboard/vite.config.js @@ -0,0 +1,12 @@ +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [vue()], + base: './', + build: { + outDir: 'src-ztools/dist', + emptyOutDir: true + } +})