88 lines
2.3 KiB
Swift
88 lines
2.3 KiB
Swift
//
|
|
// Document.swift
|
|
// GeminiFormat
|
|
//
|
|
// Created by Shadowfacts on 7/12/20.
|
|
//
|
|
|
|
import Foundation
|
|
|
|
public struct Document {
|
|
public let url: URL
|
|
public var lines: [Line]
|
|
|
|
public init(url: URL, lines: [Line] = []) {
|
|
self.url = url
|
|
self.lines = lines
|
|
}
|
|
|
|
/// Renders this Document to Gemini formatted text. This is not guaranteed to be the original input text.
|
|
public func toGeminiText() -> String {
|
|
// todo: should this be \r\n
|
|
return lines.map { $0.geminiText() }.joined(separator: "\n")
|
|
}
|
|
|
|
public var title: String? {
|
|
for case let .heading(text, level: _) in lines {
|
|
return text
|
|
}
|
|
return nil
|
|
}
|
|
}
|
|
|
|
public extension Document {
|
|
enum Line: Equatable {
|
|
case text(String)
|
|
case link(URL, text: String?)
|
|
case preformattedToggle(alt: String?)
|
|
case preformattedText(String)
|
|
case heading(String, level: HeadingLevel)
|
|
case unorderedListItem(String)
|
|
case quote(String)
|
|
|
|
func geminiText() -> String {
|
|
switch self {
|
|
case let .text(text):
|
|
return text
|
|
case let .link(url, text: text):
|
|
if let text = text {
|
|
return "=> \(url.absoluteString) \(text)"
|
|
} else {
|
|
return "=> \(url.absoluteString)"
|
|
}
|
|
case let .preformattedToggle(alt: alt):
|
|
if let alt = alt {
|
|
return "```\(alt)"
|
|
} else {
|
|
return "```"
|
|
}
|
|
case let .preformattedText(text):
|
|
return text
|
|
case let .heading(text, level: level):
|
|
return "\(level.geminiText) \(text)"
|
|
case let .unorderedListItem(text):
|
|
return "* \(text)"
|
|
case let .quote(text):
|
|
return "> \(text)"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public extension Document {
|
|
enum HeadingLevel: Int {
|
|
case h1 = 1, h2 = 2, h3 = 3
|
|
|
|
var geminiText: String {
|
|
switch self {
|
|
case .h1:
|
|
return "#"
|
|
case .h2:
|
|
return "##"
|
|
case .h3:
|
|
return "###"
|
|
}
|
|
}
|
|
}
|
|
}
|