add plain text parser with paragraph-based chapter splitting

This commit is contained in:
2026-03-13 21:52:42 +01:00
parent 2e647d7fe3
commit c753a3a147
2 changed files with 57 additions and 0 deletions

View File

@@ -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)
}
}

View File

@@ -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")
}
}