From 6299ea09b7479cc3dd599eec8d23c45d1b27f5c3 Mon Sep 17 00:00:00 2001 From: Huang Xin Date: Sun, 4 May 2025 19:46:08 +0800 Subject: [PATCH] fix: escape special characters when converting from txt to epub, closes #1018 (#1024) --- apps/readest-app/src/utils/txt.ts | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/apps/readest-app/src/utils/txt.ts b/apps/readest-app/src/utils/txt.ts index 1b3a0be8..389fbcef 100644 --- a/apps/readest-app/src/utils/txt.ts +++ b/apps/readest-app/src/utils/txt.ts @@ -35,6 +35,16 @@ const zipWriteOptions = { lastModDate: new Date(0), }; +const escapeXml = (str: string) => { + if (!str) return ''; + return str + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') + .replace(/'/g, '''); +}; + export class TxtToEpubConverter { public async convert(options: Txt2EpubOptions): Promise { const { file: txtFile, author: providedAuthor, language: providedLanguage } = options; @@ -105,6 +115,7 @@ export class TxtToEpubConverter { } const formatSegment = (segment: string): string => { + segment = escapeXml(segment); return segment .replace(/-{4,}|_{4,}/g, '\n') .split(/\n+/) @@ -153,7 +164,7 @@ export class TxtToEpubConverter { const headTitle = isVolume ? `

${title}

` : `

${title}

`; const formattedSegment = formatSegment(content); segmentChapters.push({ - title, + title: escapeXml(title), content: `${headTitle}

${formattedSegment}

`, }); } @@ -166,7 +177,7 @@ export class TxtToEpubConverter { initialContent.slice(0, 16); const formattedSegment = formatSegment(initialContent); segmentChapters.unshift({ - title: segmentTitle, + title: escapeXml(segmentTitle), content: `

${formattedSegment}

`, }); } @@ -221,10 +232,10 @@ export class TxtToEpubConverter { - ${bookTitle} + ${escapeXml(bookTitle)} - ${author} + ${escapeXml(author)} ${navPoints} @@ -285,9 +296,9 @@ export class TxtToEpubConverter { const contentOpf = ` - ${bookTitle} + ${escapeXml(bookTitle)} ${language} - ${author} + ${escapeXml(author)} ${identifier}