(a: AssembleArgs)
| 301 | } |
| 302 | |
| 303 | function assemble(a: AssembleArgs): UmdParsed { |
| 304 | const titles = parseTitles(a.dataById.get(a.idTitleList)); |
| 305 | const offsets = parseChapterOffsets(a.dataById.get(a.idChapterList)); |
| 306 | const contentBytes = decompressContent(a); |
| 307 | |
| 308 | const chapters: UmdChapter[] = []; |
| 309 | const effectiveContentLen = a.contentLen > 0 && a.contentLen <= contentBytes.length |
| 310 | ? a.contentLen |
| 311 | : contentBytes.length; |
| 312 | |
| 313 | for (let i = 0; i < titles.length; i++) { |
| 314 | const start = offsets[i] ?? 0; |
| 315 | const end = i + 1 < offsets.length ? offsets[i + 1]! : effectiveContentLen; |
| 316 | const clampedStart = Math.min(Math.max(start, 0), effectiveContentLen); |
| 317 | const clampedEnd = Math.min(Math.max(end, clampedStart), effectiveContentLen); |
| 318 | const slice = contentBytes.subarray(clampedStart, clampedEnd); |
| 319 | chapters.push({ title: titles[i]!, content: decodeUtf16LE(slice) }); |
| 320 | } |
| 321 | |
| 322 | // Fallback: no chapters detected but we do have content — emit one chapter. |
| 323 | if (chapters.length === 0 && effectiveContentLen > 0) { |
| 324 | chapters.push({ |
| 325 | title: a.bookTitle || "正文", |
| 326 | content: decodeUtf16LE(contentBytes.subarray(0, effectiveContentLen)), |
| 327 | }); |
| 328 | } |
| 329 | |
| 330 | let coverBytes: Uint8Array | undefined; |
| 331 | let coverMime: "image/jpeg" | undefined; |
| 332 | if (a.idCover) { |
| 333 | const blob = a.dataById.get(a.idCover); |
| 334 | if (blob && blob.length > 0) { |
| 335 | coverBytes = blob; |
| 336 | coverMime = "image/jpeg"; |
| 337 | } |
| 338 | } |
| 339 | |
| 340 | return { |
| 341 | bookTitle: a.bookTitle, |
| 342 | author: a.author, |
| 343 | date: a.date, |
| 344 | bookType: a.bookType, |
| 345 | publisher: a.publisher, |
| 346 | retailer: a.retailer, |
| 347 | chapters, |
| 348 | coverBytes, |
| 349 | coverMime, |
| 350 | }; |
| 351 | } |
| 352 | |
| 353 | function parseTitles(data: Uint8Array | undefined): string[] { |
| 354 | if (!data) return []; |
no test coverage detected