diff --git a/VorleserKit/Sources/BookParser/PlainTextParser.swift b/VorleserKit/Sources/BookParser/PlainTextParser.swift new file mode 100644 index 0000000..32d3d23 --- /dev/null +++ b/VorleserKit/Sources/BookParser/PlainTextParser.swift @@ -0,0 +1,21 @@ +import Foundation + +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) + } + + return Book(title: title, author: author, chapters: chapters) + } + + public static func parse(url: URL) throws -> Book { + let text = try String(contentsOf: url, encoding: .utf8) + let title = url.deletingPathExtension().lastPathComponent + return parse(text: text, title: title) + } +} diff --git a/VorleserKit/Tests/BookParserTests/PlainTextParserTests.swift b/VorleserKit/Tests/BookParserTests/PlainTextParserTests.swift new file mode 100644 index 0000000..1c42af1 --- /dev/null +++ b/VorleserKit/Tests/BookParserTests/PlainTextParserTests.swift @@ -0,0 +1,36 @@ +import Testing +import Foundation +@testable import BookParser + +@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") + #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") + } + + @Test func parsesFromFile() throws { + let tmpFile = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent("test.txt") + try "Line one.\n\nLine two.".write(to: tmpFile, atomically: true, encoding: .utf8) + defer { try? FileManager.default.removeItem(at: tmpFile) } + + let book = try PlainTextParser.parse(url: tmpFile) + #expect(book.chapters.count == 2) + #expect(book.title == "test") + } +}