From f06cdb58991806fcbf25001a2996859fc57dd3f2 Mon Sep 17 00:00:00 2001 From: 54wedge Date: Sat, 6 Sep 2025 16:28:26 +0800 Subject: [PATCH] txt: nest chapters inside volumes when converting to epub (#1972) * txt: nest chapters inside volumes * txt: readability * txt: format --- apps/readest-app/src/utils/txt.ts | 41 ++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/apps/readest-app/src/utils/txt.ts b/apps/readest-app/src/utils/txt.ts index c524a384..ccea35c4 100644 --- a/apps/readest-app/src/utils/txt.ts +++ b/apps/readest-app/src/utils/txt.ts @@ -13,6 +13,7 @@ interface Chapter { title: string; content: string; text: string; + isVolume: boolean; } interface Txt2EpubOptions { @@ -197,7 +198,7 @@ export class TxtToEpubConverter { const formattedSegment = formatSegment(chunks.join('\n')); const title = `${chapters.length + 1}`; const content = `

${title}

${formattedSegment}

`; - chapters.push({ title, content, text: chunks.join('\n') }); + chapters.push({ title, content, text: chunks.join('\n'), isVolume: false }); } continue; } @@ -219,6 +220,7 @@ export class TxtToEpubConverter { title: escapeXml(title), content: `${headTitle}

${formattedSegment}

`, text: content, + isVolume: isVolume, }); } @@ -233,6 +235,7 @@ export class TxtToEpubConverter { title: escapeXml(segmentTitle), content: `

${formattedSegment}

`, text: initialContent, + isVolume: false, }); } chapters.push(...segmentChapters); @@ -261,20 +264,28 @@ export class TxtToEpubConverter { await zipWriter.add('META-INF/container.xml', new TextReader(containerXml), zipWriteOptions); // Create navigation points for TOC - const navPoints = chapters - .map((chapter, index) => { - const id = `chapter${index + 1}`; - const playOrder = index + 1; - return ` - - - ${chapter.title} - - - - `.trim(); - }) - .join('\n'); + let isNested = false; + let navPoints = ``; + for (let i = 0; i < chapters.length; i++) { + const id = `chapter${i + 1}`; + const playOrder = i + 1; + if (chapters[i]!.isVolume && isNested) { + navPoints += `\n`; + isNested = !isNested; + } + navPoints += + `\n` + + `${chapters[i]!.title}\n` + + `\n`; + if (chapters[i]!.isVolume && !isNested) { + isNested = !isNested; + } else { + navPoints += `\n`; + } + } + if (isNested) { + navPoints += ``; + } // Add NCX file (table of contents) const tocNcx = `