优化: 移除死代码(backend/useStore)与过期类型依赖,引入 marked/dompurify/vitest

This commit is contained in:
lxy
2026-08-24 02:13:14 +08:00
parent cf2de7d64d
commit 01f0f45007
4 changed files with 401 additions and 256 deletions
+397 -9
View File
@@ -9,16 +9,18 @@
"version": "1.0.0", "version": "1.0.0",
"dependencies": { "dependencies": {
"@tauri-apps/api": "^2.11.1", "@tauri-apps/api": "^2.11.1",
"dompurify": "^3.4.14",
"mammoth": "^1.12.0", "mammoth": "^1.12.0",
"marked": "^18.0.10",
"pdfjs-dist": "^5.6.205", "pdfjs-dist": "^5.6.205",
"vue": "^3.5.13" "vue": "^3.5.13"
}, },
"devDependencies": { "devDependencies": {
"@tauri-apps/cli": "^2.11.4", "@tauri-apps/cli": "^2.11.4",
"@types/pdfjs-dist": "^2.10.377",
"@vitejs/plugin-vue": "^5.2.1", "@vitejs/plugin-vue": "^5.2.1",
"typescript": "~5.6.3", "typescript": "~5.6.3",
"vite": "^6.0.5", "vite": "^6.0.5",
"vitest": "^4.1.11",
"vue-tsc": "^2.2.0" "vue-tsc": "^2.2.0"
} }
}, },
@@ -1116,6 +1118,13 @@
"win32" "win32"
] ]
}, },
"node_modules/@standard-schema/spec": {
"version": "1.1.0",
"resolved": "https://registry.npmmirror.com/@standard-schema/spec/-/spec-1.1.0.tgz",
"integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==",
"dev": true,
"license": "MIT"
},
"node_modules/@tauri-apps/api": { "node_modules/@tauri-apps/api": {
"version": "2.11.1", "version": "2.11.1",
"resolved": "https://registry.npmmirror.com/@tauri-apps/api/-/api-2.11.1.tgz", "resolved": "https://registry.npmmirror.com/@tauri-apps/api/-/api-2.11.1.tgz",
@@ -1343,6 +1352,24 @@
"node": ">= 10" "node": ">= 10"
} }
}, },
"node_modules/@types/chai": {
"version": "5.2.3",
"resolved": "https://registry.npmmirror.com/@types/chai/-/chai-5.2.3.tgz",
"integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/deep-eql": "*",
"assertion-error": "^2.0.1"
}
},
"node_modules/@types/deep-eql": {
"version": "4.0.2",
"resolved": "https://registry.npmmirror.com/@types/deep-eql/-/deep-eql-4.0.2.tgz",
"integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==",
"dev": true,
"license": "MIT"
},
"node_modules/@types/estree": { "node_modules/@types/estree": {
"version": "1.0.9", "version": "1.0.9",
"resolved": "https://registry.npmmirror.com/@types/estree/-/estree-1.0.9.tgz", "resolved": "https://registry.npmmirror.com/@types/estree/-/estree-1.0.9.tgz",
@@ -1350,15 +1377,12 @@
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/@types/pdfjs-dist": { "node_modules/@types/trusted-types": {
"version": "2.10.377", "version": "2.0.7",
"resolved": "https://registry.npmmirror.com/@types/pdfjs-dist/-/pdfjs-dist-2.10.377.tgz", "resolved": "https://registry.npmmirror.com/@types/trusted-types/-/trusted-types-2.0.7.tgz",
"integrity": "sha512-RNBWpazVTkC5aiUIIo6d7ojlL0hJSoeQP1QCvTsVLW6qkNEpTALiI0DNGCYAGDfhbL0r17c/zNPQ15lk948UXg==", "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "optional": true
"pdfjs-dist": "*"
}
}, },
"node_modules/@vitejs/plugin-vue": { "node_modules/@vitejs/plugin-vue": {
"version": "5.2.4", "version": "5.2.4",
@@ -1374,6 +1398,129 @@
"vue": "^3.2.25" "vue": "^3.2.25"
} }
}, },
"node_modules/@vitest/expect": {
"version": "4.1.11",
"resolved": "https://registry.npmmirror.com/@vitest/expect/-/expect-4.1.11.tgz",
"integrity": "sha512-VX2x5vNJXET47KAFzwERI+KRMtTTCSWTfSMKsW7JsUsXV4psq++e3DvZpuTDOpHcxytiDs6p2nhVb2tVDiiUYw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@standard-schema/spec": "^1.1.0",
"@types/chai": "^5.2.2",
"@vitest/spy": "4.1.11",
"@vitest/utils": "4.1.11",
"chai": "^6.2.2",
"tinyrainbow": "^3.1.0"
},
"funding": {
"url": "https://opencollective.com/vitest"
}
},
"node_modules/@vitest/mocker": {
"version": "4.1.11",
"resolved": "https://registry.npmmirror.com/@vitest/mocker/-/mocker-4.1.11.tgz",
"integrity": "sha512-2XJVD55d1o5AZous5CCGKS74g/riOj9odEt2bQpCVZeblHyHdnMeFl4jl0XjU21stf4mbjUkew2eXQZt65g5CQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@vitest/spy": "4.1.11",
"estree-walker": "^3.0.3",
"magic-string": "^0.30.21"
},
"funding": {
"url": "https://opencollective.com/vitest"
},
"peerDependencies": {
"msw": "^2.4.9",
"vite": "^6.0.0 || ^7.0.0 || ^8.0.0"
},
"peerDependenciesMeta": {
"msw": {
"optional": true
},
"vite": {
"optional": true
}
}
},
"node_modules/@vitest/mocker/node_modules/estree-walker": {
"version": "3.0.3",
"resolved": "https://registry.npmmirror.com/estree-walker/-/estree-walker-3.0.3.tgz",
"integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/estree": "^1.0.0"
}
},
"node_modules/@vitest/pretty-format": {
"version": "4.1.11",
"resolved": "https://registry.npmmirror.com/@vitest/pretty-format/-/pretty-format-4.1.11.tgz",
"integrity": "sha512-yiZzPbGTS9Sr/JpFl8zHrcIkAofNbFV6k21vIgQN/cY/oxZeXhJv5sc/MBJ5jFKWmWs+oJHw0UXLZjmf931+Vw==",
"dev": true,
"license": "MIT",
"dependencies": {
"tinyrainbow": "^3.1.0"
},
"funding": {
"url": "https://opencollective.com/vitest"
}
},
"node_modules/@vitest/runner": {
"version": "4.1.11",
"resolved": "https://registry.npmmirror.com/@vitest/runner/-/runner-4.1.11.tgz",
"integrity": "sha512-LztvUgdwMNJMIkj3hQnnxiC2Xy1zNxq928W/xhjCLaNCzqTZOudjwbQf6v9IntZGPw132i2Lq2rgTRZHD3JHNw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@vitest/utils": "4.1.11",
"pathe": "^2.0.3"
},
"funding": {
"url": "https://opencollective.com/vitest"
}
},
"node_modules/@vitest/snapshot": {
"version": "4.1.11",
"resolved": "https://registry.npmmirror.com/@vitest/snapshot/-/snapshot-4.1.11.tgz",
"integrity": "sha512-pN7ikn1ON7h8ee4gIAp4AzyK+zBtJPzVbqOgu5LCEh4VaJVbPQcgYQYJIMGQPXVeJJq1fnfazis7a5pFNPahog==",
"dev": true,
"license": "MIT",
"dependencies": {
"@vitest/pretty-format": "4.1.11",
"@vitest/utils": "4.1.11",
"magic-string": "^0.30.21",
"pathe": "^2.0.3"
},
"funding": {
"url": "https://opencollective.com/vitest"
}
},
"node_modules/@vitest/spy": {
"version": "4.1.11",
"resolved": "https://registry.npmmirror.com/@vitest/spy/-/spy-4.1.11.tgz",
"integrity": "sha512-apNa/prQy2qCeywhnixOHPRCgGNhvg7T4Dapfl1GahLp/R+uhBm5cPyFoNVyqsNd2h1nJxL6BqqdIjiABL60YA==",
"dev": true,
"license": "MIT",
"funding": {
"url": "https://opencollective.com/vitest"
}
},
"node_modules/@vitest/utils": {
"version": "4.1.11",
"resolved": "https://registry.npmmirror.com/@vitest/utils/-/utils-4.1.11.tgz",
"integrity": "sha512-zTCVGpyFsGWBhllOyKlTw/vnr6D9qxsfSDyfbyZmTyjHw5N/VuvzHpHoQjm2ZJzn4RJgx5w4r7V0er69CmLgPQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@vitest/pretty-format": "4.1.11",
"convert-source-map": "^2.0.0",
"tinyrainbow": "^3.1.0"
},
"funding": {
"url": "https://opencollective.com/vitest"
}
},
"node_modules/@volar/language-core": { "node_modules/@volar/language-core": {
"version": "2.4.15", "version": "2.4.15",
"resolved": "https://registry.npmmirror.com/@volar/language-core/-/language-core-2.4.15.tgz", "resolved": "https://registry.npmmirror.com/@volar/language-core/-/language-core-2.4.15.tgz",
@@ -1564,6 +1711,16 @@
"sprintf-js": "~1.0.2" "sprintf-js": "~1.0.2"
} }
}, },
"node_modules/assertion-error": {
"version": "2.0.1",
"resolved": "https://registry.npmmirror.com/assertion-error/-/assertion-error-2.0.1.tgz",
"integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=12"
}
},
"node_modules/balanced-match": { "node_modules/balanced-match": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz", "resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz",
@@ -1607,6 +1764,23 @@
"balanced-match": "^1.0.0" "balanced-match": "^1.0.0"
} }
}, },
"node_modules/chai": {
"version": "6.2.2",
"resolved": "https://registry.npmmirror.com/chai/-/chai-6.2.2.tgz",
"integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=18"
}
},
"node_modules/convert-source-map": {
"version": "2.0.0",
"resolved": "https://registry.npmmirror.com/convert-source-map/-/convert-source-map-2.0.0.tgz",
"integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
"dev": true,
"license": "MIT"
},
"node_modules/core-util-is": { "node_modules/core-util-is": {
"version": "1.0.3", "version": "1.0.3",
"resolved": "https://registry.npmmirror.com/core-util-is/-/core-util-is-1.0.3.tgz", "resolved": "https://registry.npmmirror.com/core-util-is/-/core-util-is-1.0.3.tgz",
@@ -1632,6 +1806,15 @@
"integrity": "sha512-98l0sW87ZT58pU4i61wa2OHwxbiYSbuxsCBozaVnYX2iCnr3bLM3fIes1/ej7h1YdOKuKt/MLs706TVnALA65w==", "integrity": "sha512-98l0sW87ZT58pU4i61wa2OHwxbiYSbuxsCBozaVnYX2iCnr3bLM3fIes1/ej7h1YdOKuKt/MLs706TVnALA65w==",
"license": "BSD-2-Clause" "license": "BSD-2-Clause"
}, },
"node_modules/dompurify": {
"version": "3.4.14",
"resolved": "https://registry.npmmirror.com/dompurify/-/dompurify-3.4.14.tgz",
"integrity": "sha512-dVoH9z+MY+C9IilgGCk3YfFqjLi3fChm2OiKJMzh6axrJ5qwxqWaZamgmHrpv22CN/KdbZJuGEGgfQoL00LTdg==",
"license": "(MPL-2.0 OR Apache-2.0)",
"optionalDependencies": {
"@types/trusted-types": "^2.0.7"
}
},
"node_modules/duck": { "node_modules/duck": {
"version": "0.1.12", "version": "0.1.12",
"resolved": "https://registry.npmmirror.com/duck/-/duck-0.1.12.tgz", "resolved": "https://registry.npmmirror.com/duck/-/duck-0.1.12.tgz",
@@ -1653,6 +1836,13 @@
"url": "https://github.com/fb55/entities?sponsor=1" "url": "https://github.com/fb55/entities?sponsor=1"
} }
}, },
"node_modules/es-module-lexer": {
"version": "2.3.2",
"resolved": "https://registry.npmmirror.com/es-module-lexer/-/es-module-lexer-2.3.2.tgz",
"integrity": "sha512-poHGpORABojJJucnV9KbOavETW8lBVnphkW77ER5/BQ5Fz7oXSoCNek7IH3vR5nRjdsEz926ibFYX8KtLQmdyw==",
"dev": true,
"license": "MIT"
},
"node_modules/esbuild": { "node_modules/esbuild": {
"version": "0.25.12", "version": "0.25.12",
"resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.25.12.tgz", "resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.25.12.tgz",
@@ -1701,6 +1891,16 @@
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/expect-type": {
"version": "1.4.0",
"resolved": "https://registry.npmmirror.com/expect-type/-/expect-type-1.4.0.tgz",
"integrity": "sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==",
"dev": true,
"license": "Apache-2.0",
"engines": {
"node": ">=12.0.0"
}
},
"node_modules/fdir": { "node_modules/fdir": {
"version": "6.5.0", "version": "6.5.0",
"resolved": "https://registry.npmmirror.com/fdir/-/fdir-6.5.0.tgz", "resolved": "https://registry.npmmirror.com/fdir/-/fdir-6.5.0.tgz",
@@ -1827,6 +2027,18 @@
"node": ">=12.0.0" "node": ">=12.0.0"
} }
}, },
"node_modules/marked": {
"version": "18.0.10",
"resolved": "https://registry.npmmirror.com/marked/-/marked-18.0.10.tgz",
"integrity": "sha512-FJeH4bRpYoXiggcgriCGItKCSv3xkngJc4QCZ/rkQCogU3VYaLxYJoZl8Nw/b4+x7iij/pd+09mZ6A1dXzpL0A==",
"license": "MIT",
"bin": {
"marked": "bin/marked.js"
},
"engines": {
"node": ">= 20"
}
},
"node_modules/minimatch": { "node_modules/minimatch": {
"version": "9.0.9", "version": "9.0.9",
"resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-9.0.9.tgz", "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-9.0.9.tgz",
@@ -1875,6 +2087,20 @@
"license": "MIT", "license": "MIT",
"optional": true "optional": true
}, },
"node_modules/obug": {
"version": "2.1.4",
"resolved": "https://registry.npmmirror.com/obug/-/obug-2.1.4.tgz",
"integrity": "sha512-4a+OsYv9UktOJKE+l1A4OufDgdRF9PifWj+tJnHURo/P+WOxpG4GzUFL9qCalmWauao6ogiG+QvnCovwPoyAWA==",
"dev": true,
"funding": [
"https://github.com/sponsors/sxzz",
"https://opencollective.com/debug"
],
"license": "MIT",
"engines": {
"node": ">=12.20.0"
}
},
"node_modules/option": { "node_modules/option": {
"version": "0.2.4", "version": "0.2.4",
"resolved": "https://registry.npmmirror.com/option/-/option-0.2.4.tgz", "resolved": "https://registry.npmmirror.com/option/-/option-0.2.4.tgz",
@@ -1903,6 +2129,13 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/pathe": {
"version": "2.0.3",
"resolved": "https://registry.npmmirror.com/pathe/-/pathe-2.0.3.tgz",
"integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==",
"dev": true,
"license": "MIT"
},
"node_modules/pdfjs-dist": { "node_modules/pdfjs-dist": {
"version": "5.6.205", "version": "5.6.205",
"resolved": "https://registry.npmmirror.com/pdfjs-dist/-/pdfjs-dist-5.6.205.tgz", "resolved": "https://registry.npmmirror.com/pdfjs-dist/-/pdfjs-dist-5.6.205.tgz",
@@ -2041,6 +2274,13 @@
"integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/siginfo": {
"version": "2.0.0",
"resolved": "https://registry.npmmirror.com/siginfo/-/siginfo-2.0.0.tgz",
"integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==",
"dev": true,
"license": "ISC"
},
"node_modules/source-map-js": { "node_modules/source-map-js": {
"version": "1.2.1", "version": "1.2.1",
"resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.1.tgz", "resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.1.tgz",
@@ -2056,6 +2296,20 @@
"integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==",
"license": "BSD-3-Clause" "license": "BSD-3-Clause"
}, },
"node_modules/stackback": {
"version": "0.0.2",
"resolved": "https://registry.npmmirror.com/stackback/-/stackback-0.0.2.tgz",
"integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==",
"dev": true,
"license": "MIT"
},
"node_modules/std-env": {
"version": "4.2.0",
"resolved": "https://registry.npmmirror.com/std-env/-/std-env-4.2.0.tgz",
"integrity": "sha512-oCUKSupKTHX53EyjDtuZQ64pjLJ6yYCtpmEw0goYxtjG9KpbRe8KAsl2tBUGU9DyMcJ0RwJ8GqJAFzMXcXW1Rw==",
"dev": true,
"license": "MIT"
},
"node_modules/string_decoder": { "node_modules/string_decoder": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmmirror.com/string_decoder/-/string_decoder-1.1.1.tgz", "resolved": "https://registry.npmmirror.com/string_decoder/-/string_decoder-1.1.1.tgz",
@@ -2065,6 +2319,23 @@
"safe-buffer": "~5.1.0" "safe-buffer": "~5.1.0"
} }
}, },
"node_modules/tinybench": {
"version": "2.9.0",
"resolved": "https://registry.npmmirror.com/tinybench/-/tinybench-2.9.0.tgz",
"integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==",
"dev": true,
"license": "MIT"
},
"node_modules/tinyexec": {
"version": "1.3.0",
"resolved": "https://registry.npmmirror.com/tinyexec/-/tinyexec-1.3.0.tgz",
"integrity": "sha512-QKAl9m8gWWGHV8jZcPeym6j+XULi6tOf1mT83WYJ4Lk2ytW/uwAWkrP0uFsdoYMdueVJ0qs26wZ+23xeB4ibNQ==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=18"
}
},
"node_modules/tinyglobby": { "node_modules/tinyglobby": {
"version": "0.2.17", "version": "0.2.17",
"resolved": "https://registry.npmmirror.com/tinyglobby/-/tinyglobby-0.2.17.tgz", "resolved": "https://registry.npmmirror.com/tinyglobby/-/tinyglobby-0.2.17.tgz",
@@ -2082,6 +2353,16 @@
"url": "https://github.com/sponsors/SuperchupuDev" "url": "https://github.com/sponsors/SuperchupuDev"
} }
}, },
"node_modules/tinyrainbow": {
"version": "3.1.1",
"resolved": "https://registry.npmmirror.com/tinyrainbow/-/tinyrainbow-3.1.1.tgz",
"integrity": "sha512-yau8yJdTt989Mm0Bd/236QnzEiPf2xLLTqUZRUJOo/3CB078LSwzei343DgtJVmfJKJE3TMINY1u42SQsP6mXw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/typescript": { "node_modules/typescript": {
"version": "5.6.3", "version": "5.6.3",
"resolved": "https://registry.npmmirror.com/typescript/-/typescript-5.6.3.tgz", "resolved": "https://registry.npmmirror.com/typescript/-/typescript-5.6.3.tgz",
@@ -2183,6 +2464,96 @@
} }
} }
}, },
"node_modules/vitest": {
"version": "4.1.11",
"resolved": "https://registry.npmmirror.com/vitest/-/vitest-4.1.11.tgz",
"integrity": "sha512-fhACrNXUidIbGSBr5FlbuBkO7VWC1ZyLl0DO4CU2DrQoAPxX84Ysxs+HeGQpii5lZWV1Q4gBZTTu49mF+A6Edw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@vitest/expect": "4.1.11",
"@vitest/mocker": "4.1.11",
"@vitest/pretty-format": "4.1.11",
"@vitest/runner": "4.1.11",
"@vitest/snapshot": "4.1.11",
"@vitest/spy": "4.1.11",
"@vitest/utils": "4.1.11",
"es-module-lexer": "^2.0.0",
"expect-type": "^1.3.0",
"magic-string": "^0.30.21",
"obug": "^2.1.1",
"pathe": "^2.0.3",
"picomatch": "^4.0.3",
"std-env": "^4.0.0-rc.1",
"tinybench": "^2.9.0",
"tinyexec": "^1.0.2",
"tinyglobby": "^0.2.15",
"tinyrainbow": "^3.1.0",
"vite": "^6.0.0 || ^7.0.0 || ^8.0.0",
"why-is-node-running": "^2.3.0"
},
"bin": {
"vitest": "vitest.mjs"
},
"engines": {
"node": "^20.0.0 || ^22.0.0 || >=24.0.0"
},
"funding": {
"url": "https://opencollective.com/vitest"
},
"peerDependencies": {
"@edge-runtime/vm": "*",
"@opentelemetry/api": "^1.9.0",
"@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0",
"@vitest/browser-playwright": "4.1.11",
"@vitest/browser-preview": "4.1.11",
"@vitest/browser-webdriverio": "4.1.11",
"@vitest/coverage-istanbul": "4.1.11",
"@vitest/coverage-v8": "4.1.11",
"@vitest/ui": "4.1.11",
"happy-dom": "*",
"jsdom": "*",
"vite": "^6.0.0 || ^7.0.0 || ^8.0.0"
},
"peerDependenciesMeta": {
"@edge-runtime/vm": {
"optional": true
},
"@opentelemetry/api": {
"optional": true
},
"@types/node": {
"optional": true
},
"@vitest/browser-playwright": {
"optional": true
},
"@vitest/browser-preview": {
"optional": true
},
"@vitest/browser-webdriverio": {
"optional": true
},
"@vitest/coverage-istanbul": {
"optional": true
},
"@vitest/coverage-v8": {
"optional": true
},
"@vitest/ui": {
"optional": true
},
"happy-dom": {
"optional": true
},
"jsdom": {
"optional": true
},
"vite": {
"optional": false
}
}
},
"node_modules/vscode-uri": { "node_modules/vscode-uri": {
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmmirror.com/vscode-uri/-/vscode-uri-3.1.0.tgz", "resolved": "https://registry.npmmirror.com/vscode-uri/-/vscode-uri-3.1.0.tgz",
@@ -2228,6 +2599,23 @@
"typescript": ">=5.0.0" "typescript": ">=5.0.0"
} }
}, },
"node_modules/why-is-node-running": {
"version": "2.3.0",
"resolved": "https://registry.npmmirror.com/why-is-node-running/-/why-is-node-running-2.3.0.tgz",
"integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==",
"dev": true,
"license": "MIT",
"dependencies": {
"siginfo": "^2.0.0",
"stackback": "0.0.2"
},
"bin": {
"why-is-node-running": "cli.js"
},
"engines": {
"node": ">=8"
}
},
"node_modules/xmlbuilder": { "node_modules/xmlbuilder": {
"version": "10.1.1", "version": "10.1.1",
"resolved": "https://registry.npmmirror.com/xmlbuilder/-/xmlbuilder-10.1.1.tgz", "resolved": "https://registry.npmmirror.com/xmlbuilder/-/xmlbuilder-10.1.1.tgz",
+4 -1
View File
@@ -9,22 +9,25 @@
"dev:web": "vite --mode web", "dev:web": "vite --mode web",
"build": "vue-tsc -b && vite build", "build": "vue-tsc -b && vite build",
"preview": "vite preview", "preview": "vite preview",
"test": "vitest run",
"tauri": "tauri", "tauri": "tauri",
"tauri:dev": "tauri dev", "tauri:dev": "tauri dev",
"tauri:build": "tauri build" "tauri:build": "tauri build"
}, },
"dependencies": { "dependencies": {
"@tauri-apps/api": "^2.11.1", "@tauri-apps/api": "^2.11.1",
"dompurify": "^3.4.14",
"mammoth": "^1.12.0", "mammoth": "^1.12.0",
"marked": "^18.0.10",
"pdfjs-dist": "^5.6.205", "pdfjs-dist": "^5.6.205",
"vue": "^3.5.13" "vue": "^3.5.13"
}, },
"devDependencies": { "devDependencies": {
"@tauri-apps/cli": "^2.11.4", "@tauri-apps/cli": "^2.11.4",
"@types/pdfjs-dist": "^2.10.377",
"@vitejs/plugin-vue": "^5.2.1", "@vitejs/plugin-vue": "^5.2.1",
"typescript": "~5.6.3", "typescript": "~5.6.3",
"vite": "^6.0.5", "vite": "^6.0.5",
"vitest": "^4.1.11",
"vue-tsc": "^2.2.0" "vue-tsc": "^2.2.0"
} }
} }
-73
View File
@@ -1,73 +0,0 @@
/* =====================================================================
* useStore.ts — 统一 Store 接口(兼容 Tauri 和 Web 双模式)
*
* 设计:
* - 检测 __TAURI__ 环境,决定走 invoke 还是直接调 TS store
* - 暴露与现有 store 相同的方法签名(88 处组件调用零改动)
* - 返回 reactive ref(与 Vue 响应式兼容)
*
* Web 模式:直接 return store(现有行为,零改动)
* Tauri 模式:返回封装对象,内部 invoke Rust 命令
* ===================================================================== */
import type { Deck, Slide, SlideElement, LibItem, PageTemplate, ChatMessage, AiCfg } from '../core/types'
import { store as tsStore } from '../core/store'
import { invoke } from '../core/bridge'
/** 是否运行在 Tauri 桌面环境中 */
export const isTauri = typeof window !== 'undefined' && '__TAURI__' in window
/** 根据环境创建 store 接口 */
function createStore() {
// Web 模式:直接返回现有 TS store
if (!isTauri) return tsStore
// Tauri 模式:封装 invoke 调用
// 注意:所有写操作通过 exec_op 统一走 Op Log
const CLIENT_ID = 'client-' + Math.random().toString(36).slice(2, 10)
/** 生成一个 Op 并发送到 Rust 后端 */
async function execOp(type: string, payload: Record<string, unknown>) {
try {
const result = await invoke<{ success: boolean; deck: Deck; error?: string }>('exec_op', {
opJson: { type, clientId: CLIENT_ID, timestamp: Date.now(), ...payload }
})
if (result?.deck) {
// 更新本地 ref 状态(由 TauriBridge watcher 处理)
}
} catch (e) {
console.error('exec_op 失败:', e)
}
}
// 返回与 TS store 类型兼容的对象
// 关键属性通过 computed ref 暴露
return {
...tsStore,
// 读操作暂时委托给 TS store(未来Rust端会emit状态同步)
// 写操作改为 invoke
setTheme: async (name: string) => {
await execOp('set_theme', { theme: name })
},
addSlide: async (atIndex?: number) => {
const slide: Slide = { id: 's-' + Date.now(), background: 'bg', elements: [] }
const idx = atIndex != null ? atIndex + 1 : tsStore.getCount()
await execOp('add_slide', { atIndex: idx, slide })
tsStore.addSlide(atIndex)
},
updateElement: async (id: string, patch: Record<string, unknown>) => {
await execOp('update_element', { slideIdx: tsStore.getCurrentIndex(), elementId: id, patch })
},
delElement: async (id: string) => {
const el = tsStore.findElement(id)
await execOp('del_element', { slideIdx: tsStore.getCurrentIndex(), elementId: id, deletedElement: el ? { ...el } : undefined })
},
undo: async () => {
await invoke('undo')
},
redo: async () => {
await invoke('redo')
},
}
}
export const store = createStore()
-173
View File
@@ -1,173 +0,0 @@
/* =====================================================================
* backend.ts — 持久化后端抽象层
*
* store 只管内存状态 + Op Log,持久化通过 Backend 接口抽象。
* 三个实现:
* - LocalBackend localStorageWeb 版当前模式)
* - TauriBackend Rust 文件系统,桌面版,B4 实现)
* - CloudBackend HTTP API,云端版,C0 实现)
*
* 设计原则:
* - 接口只管读写数据,不管状态逻辑(状态逻辑在 store)
* - 所有方法返回 PromiseTauriBackend/CloudBackend 天然异步)
* - LocalBackend 内部用 localStorage 但包装为 Promise(统一接口)
* ===================================================================== */
import type { Deck, LibItem, PageTemplate, Theme, ChatMessage, AiCfg } from './types'
export interface Backend {
// ---- 当前 deck ----
loadDeck(): Promise<Deck | null>
saveDeck(deck: Deck): Promise<void>
loadBackup(): Promise<Deck | null>
saveBackup(deck: Deck): Promise<void>
clearBackup(): Promise<void>
// ---- 文库 ----
loadLibrary(): Promise<LibItem[]>
saveLibrary(lib: LibItem[]): Promise<void>
getActiveLibId(): Promise<string | null>
setActiveLibId(id: string | null): Promise<void>
// ---- 会话(按 chatId 隔离) ----
loadChat(chatId: string): Promise<ChatMessage[]>
saveChat(chatId: string, msgs: ChatMessage[]): Promise<void>
clearChat(chatId: string): Promise<void>
// ---- 用户模板 ----
loadTemplates(): Promise<PageTemplate[]>
saveTemplates(tpls: PageTemplate[]): Promise<void>
// ---- 自定义主题 ----
loadThemes(): Promise<Record<string, Theme>>
saveThemes(themes: Record<string, Theme>): Promise<void>
// ---- AI 配置 ----
loadCfg(): Promise<Partial<AiCfg> | null>
saveCfg(cfg: AiCfg): Promise<void>
}
/* ============================================================
* LocalBackend — localStorage 实现(Web 版当前模式)
* ============================================================ */
const KEYS = {
deck: 'u-ppt.deck.v1',
deckBak: 'u-ppt.deck.v1.bak',
lib: 'u-ppt.library.v1',
activeLib: 'u-ppt.activeLib.v1',
chatPrefix: 'u-ppt.chat.',
templates: 'u-ppt.templates.v1',
themes: 'u-ppt.themes.v1',
cfg: 'u-ppt.ai-cfg.v1',
}
function lsGet(key: string): string | null {
try { return localStorage.getItem(key) } catch (e) { return null }
}
function lsSet(key: string, val: string): void {
try { localStorage.setItem(key, val) } catch (e) { /* 配额满等忽略 */ }
}
function lsDel(key: string): void {
try { localStorage.removeItem(key) } catch (e) {}
}
export class LocalBackend implements Backend {
async loadDeck(): Promise<Deck | null> {
const raw = lsGet(KEYS.deck)
if (!raw) return null
try { return JSON.parse(raw) } catch (e) { return null }
}
async saveDeck(deck: Deck): Promise<void> {
lsSet(KEYS.deck, JSON.stringify(deck))
}
async loadBackup(): Promise<Deck | null> {
const raw = lsGet(KEYS.deckBak)
if (!raw) return null
try { return JSON.parse(raw) } catch (e) { return null }
}
async saveBackup(deck: Deck): Promise<void> {
lsSet(KEYS.deckBak, JSON.stringify(deck))
}
async clearBackup(): Promise<void> {
lsDel(KEYS.deckBak)
}
async loadLibrary(): Promise<LibItem[]> {
const raw = lsGet(KEYS.lib)
if (!raw) return []
try { return JSON.parse(raw) || [] } catch (e) { return [] }
}
async saveLibrary(lib: LibItem[]): Promise<void> {
lsSet(KEYS.lib, JSON.stringify(lib))
}
async getActiveLibId(): Promise<string | null> {
return lsGet(KEYS.activeLib)
}
async setActiveLibId(id: string | null): Promise<void> {
if (id) lsSet(KEYS.activeLib, id)
else lsDel(KEYS.activeLib)
}
async loadChat(chatId: string): Promise<ChatMessage[]> {
const raw = lsGet(KEYS.chatPrefix + chatId)
if (!raw) return []
try { return JSON.parse(raw) || [] } catch (e) { return [] }
}
async saveChat(chatId: string, msgs: ChatMessage[]): Promise<void> {
lsSet(KEYS.chatPrefix + chatId, JSON.stringify(msgs))
}
async clearChat(chatId: string): Promise<void> {
lsDel(KEYS.chatPrefix + chatId)
}
async loadTemplates(): Promise<PageTemplate[]> {
const raw = lsGet(KEYS.templates)
if (!raw) return []
try { return JSON.parse(raw) || [] } catch (e) { return [] }
}
async saveTemplates(tpls: PageTemplate[]): Promise<void> {
// 只存用户模板(category === 'user'
lsSet(KEYS.templates, JSON.stringify(tpls.filter(t => t.category === 'user')))
}
async loadThemes(): Promise<Record<string, Theme>> {
const raw = lsGet(KEYS.themes)
if (!raw) return {}
try { return JSON.parse(raw) || {} } catch (e) { return {} }
}
async saveThemes(themes: Record<string, Theme>): Promise<void> {
lsSet(KEYS.themes, JSON.stringify(themes))
}
async loadCfg(): Promise<Partial<AiCfg> | null> {
const raw = lsGet(KEYS.cfg)
if (!raw) return null
try { return JSON.parse(raw) } catch (e) { return null }
}
async saveCfg(cfg: AiCfg): Promise<void> {
lsSet(KEYS.cfg, JSON.stringify(cfg))
}
}
/* ---------- 当前活动的 Backend 实例 ---------- */
let activeBackend: Backend = new LocalBackend()
export function getBackend(): Backend {
return activeBackend
}
export function setBackend(b: Backend): void {
activeBackend = b
}