add BookParser facade with format detection, Book character addressing tests
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
24
VorleserKit/Sources/BookParser/BookParser.swift
Normal file
24
VorleserKit/Sources/BookParser/BookParser.swift
Normal file
@@ -0,0 +1,24 @@
|
||||
import Foundation
|
||||
|
||||
public enum BookParserError: Error, CustomStringConvertible {
|
||||
case unsupportedFormat(String)
|
||||
|
||||
public var description: String {
|
||||
switch self {
|
||||
case .unsupportedFormat(let ext): "unsupported file format: \(ext)"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public struct BookParser {
|
||||
public static func parse(url: URL) throws -> Book {
|
||||
switch url.pathExtension.lowercased() {
|
||||
case "epub":
|
||||
return try EPUBParser.parse(url: url)
|
||||
case "txt", "text":
|
||||
return try PlainTextParser.parse(url: url)
|
||||
default:
|
||||
throw BookParserError.unsupportedFormat(url.pathExtension)
|
||||
}
|
||||
}
|
||||
}
|
||||
57
VorleserKit/Tests/BookParserTests/BookTests.swift
Normal file
57
VorleserKit/Tests/BookParserTests/BookTests.swift
Normal file
@@ -0,0 +1,57 @@
|
||||
import Testing
|
||||
import Foundation
|
||||
@testable import BookParser
|
||||
@testable import VorleserKit
|
||||
|
||||
@Suite("BookParser")
|
||||
struct BookParserFacadeTests {
|
||||
@Test func detectsEPUBByExtension() throws {
|
||||
let url = Bundle.module.url(forResource: "test", withExtension: "epub", subdirectory: "Fixtures")!
|
||||
let book = try BookParser.parse(url: url)
|
||||
#expect(book.chapters.count == 2)
|
||||
}
|
||||
|
||||
@Test func detectsTextByExtension() throws {
|
||||
let tmpFile = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent("test.txt")
|
||||
try "Paragraph one.\n\nParagraph two.".write(to: tmpFile, atomically: true, encoding: .utf8)
|
||||
defer { try? FileManager.default.removeItem(at: tmpFile) }
|
||||
|
||||
let book = try BookParser.parse(url: tmpFile)
|
||||
#expect(book.chapters.count == 2)
|
||||
}
|
||||
}
|
||||
|
||||
@Suite("Book character addressing")
|
||||
struct BookCharacterAddressingTests {
|
||||
let book = Book(
|
||||
title: "Test",
|
||||
author: nil,
|
||||
chapters: [
|
||||
Chapter(index: 0, title: "Ch 1", text: "Hello world."),
|
||||
Chapter(index: 1, title: "Ch 2", text: "Second chapter."),
|
||||
]
|
||||
)
|
||||
|
||||
@Test func totalCharacters() {
|
||||
#expect(book.totalCharacters == 27)
|
||||
}
|
||||
|
||||
@Test func chapterAndLocalOffset() {
|
||||
let first = book.chapterAndLocalOffset(for: 0)
|
||||
#expect(first?.chapterIndex == 0)
|
||||
#expect(first?.localOffset == 0)
|
||||
|
||||
let second = book.chapterAndLocalOffset(for: 12)
|
||||
#expect(second?.chapterIndex == 1)
|
||||
#expect(second?.localOffset == 0)
|
||||
}
|
||||
|
||||
@Test func sentenceIndex() {
|
||||
let idx = book.sentenceIndex(containing: 0)
|
||||
#expect(idx != nil)
|
||||
}
|
||||
|
||||
@Test func outOfRangeReturnsNil() {
|
||||
#expect(book.chapterAndLocalOffset(for: 9999) == nil)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user