1.1.1版本审核修复

[spine-utils.js (line 35)](/Users/tianmokeji/Desktop/特效/SpineViewer/SpineViewer/js/spine-utils.js:35) 统一拦截绝对路径、..、Windows 盘符、UNC、URI、控制字符和符号链接越界。
跨素材贴图只能使用已枚举、验证且位于 Eagle 素材目录内的文件。
[spine-render.js (line 62)](/Users/tianmokeji/Desktop/特效/SpineViewer/SpineViewer/js/spine-render.js:62) 已删除未经验证的路径备用拼接。
自动缩略图只写当前回调提供的 dest,不再调用接口改写同组素材。
已删除后台整组补刷进程及 relatedDataPaths。
[viewer/spine.html (line 482)](/Users/tianmokeji/Desktop/特效/SpineViewer/SpineViewer/viewer/spine.html:482) 的手动缩略图只针对当前素材,并核对素材 ID、文件名和扩展名。
当前素材已有自定义缩略图时,会提示替换后无法自动恢复并要求确认。
手动生成的中间文件改存系统临时目录,API 失败时不再直接写 Eagle 素材目录。
八种语言文案及 README 已同步。
处理历史日志遗留问题
This commit is contained in:
tianmo committed 2026-09-17 13:38:22 +08:00
1 parent 473a270510
commit bb73cc9227
36 files changed
+499 -652

No files matched your search

+6 -6
View File
@@ -59,7 +59,7 @@ function loadRuntime(dir) {
/** 构造 TextureAtlas 并挂载贴图(跨版本兼容)。
* texturePaths: { atlas 中引用的贴图名 -> 绝对路径 },用于跨 Eagle item 文件夹解析贴图。
*/
function buildTextureAtlas(spine, atlasText, dir, texturePaths) {
function buildTextureAtlas(spine, atlasText, texturePaths) {
if (!canvasLib) throw new Error('@napi-rs/canvas 不可用');
return new Promise((resolve, reject) => {
(async () => {
@@ -69,9 +69,10 @@ function buildTextureAtlas(spine, atlasText, dir, texturePaths) {
const textureMap = {};
await Promise.all(pageNames.map(async (name) => {
// 优先使用跨文件夹解析出的绝对路径,否则回退到 atlas 同目录
const p = (texturePaths && texturePaths[name]) ? texturePaths[name] : path.join(dir, name);
if (!fs.existsSync(p)) return;
// 只接受 spine-utils 已完成目录、realpath 与符号链接边界验证的路径。
// 不在这里根据不可信的 atlas 页面名再次拼接文件系统路径。
const p = texturePaths && texturePaths[name];
if (!p || !fs.existsSync(p)) return;
try {
const img = await canvasLib.loadImage(p);
textureMap[name] = img;
@@ -150,12 +151,11 @@ function getBounds(spine, skeleton) {
async function renderThumbnail({ skeletonPath, atlasPath, texturePaths, version, runtimeDir, size = 400 }) {
if (!canvasLib) throw new Error('@napi-rs/canvas 不可用');
const isBinary = /\.skel(\.bytes)?$/i.test(skeletonPath);
const dir = path.dirname(skeletonPath);
const atlasText = fs.readFileSync(atlasPath, 'utf8');
const premultipliedAlpha = utils.parseAtlasPma(atlasText) === true;
const spine = loadRuntime(runtimeDir);
const atlas = await buildTextureAtlas(spine, atlasText, dir, texturePaths);
const atlas = await buildTextureAtlas(spine, atlasText, texturePaths);
const skeletonData = readSkeletonData(spine, skeletonPath, atlas, isBinary);
if (!skeletonData || !skeletonData.bones || skeletonData.bones.length === 0) {