spine连接器和导出修改

This commit is contained in:
tianmo
2026-09-05 16:20:23 +08:00
parent 535f8d7558
commit 0bde824c88
81 changed files with 11800 additions and 1251 deletions
+78
View File
@@ -0,0 +1,78 @@
import { normalize } from 'node:path'
const CRC_TABLE = Array.from({ length: 256 }, (_, value) => {
let crc = value
for (let bit = 0; bit < 8; bit++) crc = (crc & 1) ? 0xedb88320 ^ (crc >>> 1) : crc >>> 1
return crc >>> 0
})
function crc32(data) {
let crc = 0xffffffff
for (const byte of data) crc = CRC_TABLE[(crc ^ byte) & 0xff] ^ (crc >>> 8)
return (crc ^ 0xffffffff) >>> 0
}
function archivePath(value) {
const path = normalize(String(value || '').replace(/\\/g, '/')).replace(/\\/g, '/').replace(/^\.\//, '')
if (!path || path.startsWith('/') || path === '..' || path.startsWith('../')) throw new Error('ZIP 文件路径无效')
return path
}
function dosDateTime(date = new Date()) {
const year = Math.max(1980, date.getFullYear())
return {
time: (date.getHours() << 11) | (date.getMinutes() << 5) | Math.floor(date.getSeconds() / 2),
date: ((year - 1980) << 9) | ((date.getMonth() + 1) << 5) | date.getDate(),
}
}
/** 创建无额外依赖的 ZIPStore 模式);PNG 和 .spine 本身已压缩,无需重复压缩。 */
export function createZipArchive(files) {
const localParts = []
const centralParts = []
let offset = 0
const timestamp = dosDateTime()
for (const file of files) {
const name = Buffer.from(archivePath(file.name), 'utf8')
const data = Buffer.isBuffer(file.data) ? file.data : Buffer.from(file.data)
const crc = crc32(data)
const local = Buffer.alloc(30)
local.writeUInt32LE(0x04034b50, 0)
local.writeUInt16LE(20, 4)
local.writeUInt16LE(0x0800, 6)
local.writeUInt16LE(0, 8)
local.writeUInt16LE(timestamp.time, 10)
local.writeUInt16LE(timestamp.date, 12)
local.writeUInt32LE(crc, 14)
local.writeUInt32LE(data.length, 18)
local.writeUInt32LE(data.length, 22)
local.writeUInt16LE(name.length, 26)
localParts.push(local, name, data)
const central = Buffer.alloc(46)
central.writeUInt32LE(0x02014b50, 0)
central.writeUInt16LE(20, 4)
central.writeUInt16LE(20, 6)
central.writeUInt16LE(0x0800, 8)
central.writeUInt16LE(0, 10)
central.writeUInt16LE(timestamp.time, 12)
central.writeUInt16LE(timestamp.date, 14)
central.writeUInt32LE(crc, 16)
central.writeUInt32LE(data.length, 20)
central.writeUInt32LE(data.length, 24)
central.writeUInt16LE(name.length, 28)
central.writeUInt32LE(offset, 42)
centralParts.push(central, name)
offset += local.length + name.length + data.length
}
const centralDirectory = Buffer.concat(centralParts)
const end = Buffer.alloc(22)
end.writeUInt32LE(0x06054b50, 0)
end.writeUInt16LE(files.length, 8)
end.writeUInt16LE(files.length, 10)
end.writeUInt32LE(centralDirectory.length, 12)
end.writeUInt32LE(offset, 16)
return Buffer.concat([...localParts, centralDirectory, end])
}