87 lines
2.3 KiB
Swift
87 lines
2.3 KiB
Swift
|
|
enum ContentBlock: String, CaseIterable {
|
|
|
|
case audio
|
|
|
|
case swift
|
|
|
|
var processor: BlockProcessor.Type {
|
|
switch self {
|
|
case .audio: return AudioBlockProcessor.self
|
|
case .swift: return SwiftBlockProcessor.self
|
|
}
|
|
}
|
|
}
|
|
|
|
protocol BlockProcessor {
|
|
|
|
static var blockId: ContentBlock { get }
|
|
|
|
var results: PageGenerationResults { get }
|
|
|
|
init(content: Content, results: PageGenerationResults, language: ContentLanguage)
|
|
|
|
func process(_ markdown: Substring) -> String
|
|
}
|
|
|
|
extension BlockProcessor {
|
|
|
|
func invalid(_ markdown: Substring) {
|
|
results.invalid(block: Self.blockId, markdown)
|
|
}
|
|
}
|
|
|
|
protocol BlockLineProcessor: BlockProcessor {
|
|
|
|
func process(_ lines: [String], markdown: Substring) -> String
|
|
}
|
|
|
|
extension BlockLineProcessor {
|
|
|
|
func process(_ markdown: Substring) -> String {
|
|
let lines = markdown
|
|
.between("```\(Self.blockId.self)", and: "```")
|
|
.components(separatedBy: "\n")
|
|
return process(lines, markdown: markdown)
|
|
}
|
|
}
|
|
|
|
protocol OrderedKeyBlockProcessor: BlockLineProcessor {
|
|
|
|
associatedtype Key: Hashable, RawRepresentable where Key.RawValue == String
|
|
|
|
func process(_ arguments: [(key: Key, value: String)], markdown: Substring) -> String
|
|
}
|
|
|
|
extension OrderedKeyBlockProcessor {
|
|
|
|
func process(_ lines: [String], markdown: Substring) -> String {
|
|
let result: [(key: Key, value: String)] = lines.compactMap { line in
|
|
guard line.trimmed != "" else {
|
|
return nil
|
|
}
|
|
let (rawKey, rawValue) = line.splitAtFirst(":")
|
|
guard let key = Key(rawValue: rawKey.trimmed) else {
|
|
print("Invalid key \(rawKey)")
|
|
invalid(markdown)
|
|
return nil
|
|
}
|
|
return (key, rawValue.trimmed)
|
|
}
|
|
return process(result, markdown: markdown)
|
|
}
|
|
}
|
|
|
|
protocol KeyedBlockProcessor: OrderedKeyBlockProcessor {
|
|
|
|
func process(_ arguments: [Key : String], markdown: Substring) -> String
|
|
}
|
|
|
|
extension KeyedBlockProcessor {
|
|
|
|
func process(_ arguments: [(key: Key, value: String)], markdown: Substring) -> String {
|
|
let result = arguments.reduce(into: [:]) { $0[$1.key] = $1.value }
|
|
return process(result, markdown: markdown)
|
|
}
|
|
}
|