From ec5bb6d0afe17b0f9a0cc39b814b83eff6c38a61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20F=C3=B6rtsch?= Date: Sat, 14 Mar 2026 05:36:06 +0100 Subject: [PATCH] task 7: restructure PlainTextParser to single-chapter model, update tests Co-Authored-By: Claude Sonnet 4.6 --- .../Sources/BookParser/PlainTextParser.swift | 19 +++++++++------ .../Tests/BookParserTests/BookTests.swift | 2 +- .../PlainTextParserTests.swift | 23 +++++++++++-------- 3 files changed, 27 insertions(+), 17 deletions(-) diff --git a/VorleserKit/Sources/BookParser/PlainTextParser.swift b/VorleserKit/Sources/BookParser/PlainTextParser.swift index 32d3d23..24c4d64 100644 --- a/VorleserKit/Sources/BookParser/PlainTextParser.swift +++ b/VorleserKit/Sources/BookParser/PlainTextParser.swift @@ -1,16 +1,21 @@ import Foundation +#if canImport(UIKit) +import UIKit +#elseif canImport(AppKit) +import AppKit +#endif + public struct PlainTextParser { public static func parse(text: String, title: String, author: String? = nil) -> Book { - let paragraphs = text.components(separatedBy: "\n\n") - .map { $0.trimmingCharacters(in: .whitespacesAndNewlines) } - .filter { !$0.isEmpty } - - let chapters = paragraphs.enumerated().map { index, text in - Chapter(index: index, title: "Section \(index + 1)", text: text) + let trimmed = text.trimmingCharacters(in: .whitespacesAndNewlines) + guard !trimmed.isEmpty else { + return Book(title: title, author: author, chapters: []) } - return Book(title: title, author: author, chapters: chapters) + let attributedText = AttributedStringBuilder.buildPlain(text: trimmed) + let chapter = Chapter(index: 0, title: title, text: trimmed, attributedText: attributedText) + return Book(title: title, author: author, chapters: [chapter]) } public static func parse(url: URL) throws -> Book { diff --git a/VorleserKit/Tests/BookParserTests/BookTests.swift b/VorleserKit/Tests/BookParserTests/BookTests.swift index d54443f..54bd8b2 100644 --- a/VorleserKit/Tests/BookParserTests/BookTests.swift +++ b/VorleserKit/Tests/BookParserTests/BookTests.swift @@ -17,7 +17,7 @@ struct BookParserFacadeTests { defer { try? FileManager.default.removeItem(at: tmpFile) } let book = try BookParser.parse(url: tmpFile) - #expect(book.chapters.count == 2) + #expect(book.chapters.count == 1) } } diff --git a/VorleserKit/Tests/BookParserTests/PlainTextParserTests.swift b/VorleserKit/Tests/BookParserTests/PlainTextParserTests.swift index 1c42af1..24ff92d 100644 --- a/VorleserKit/Tests/BookParserTests/PlainTextParserTests.swift +++ b/VorleserKit/Tests/BookParserTests/PlainTextParserTests.swift @@ -4,14 +4,6 @@ import Foundation @Suite("PlainTextParser") struct PlainTextParserTests { - @Test func parsesMultipleChapters() throws { - let text = "First chapter content.\n\nSecond chapter content.\n\nThird chapter." - let book = PlainTextParser.parse(text: text, title: "Test Book") - #expect(book.chapters.count == 3) - #expect(book.chapters[0].text == "First chapter content.") - #expect(book.chapters[1].text == "Second chapter content.") - } - @Test func parsesSingleParagraphAsOneChapter() { let text = "Just a single paragraph with no double newlines." let book = PlainTextParser.parse(text: text, title: "Test") @@ -19,6 +11,13 @@ struct PlainTextParserTests { #expect(book.chapters[0].text == text) } + @Test func multiParagraphTextBecomesOneChapter() { + let text = "First paragraph.\n\nSecond paragraph.\n\nThird paragraph." + let book = PlainTextParser.parse(text: text, title: "Test Book") + #expect(book.chapters.count == 1) + #expect(book.chapters[0].text == text) + } + @Test func setsTitle() { let book = PlainTextParser.parse(text: "Hello", title: "My Book") #expect(book.title == "My Book") @@ -30,7 +29,13 @@ struct PlainTextParserTests { defer { try? FileManager.default.removeItem(at: tmpFile) } let book = try PlainTextParser.parse(url: tmpFile) - #expect(book.chapters.count == 2) + #expect(book.chapters.count == 1) #expect(book.title == "test") } + + @Test func attributedTextStringMatchesPlainText() { + let text = "Hello world.\n\nSecond paragraph." + let book = PlainTextParser.parse(text: text, title: "Test") + #expect(book.chapters[0].attributedText.string == book.chapters[0].text) + } }