// // GeminiHTMLRenderer.swift // GeminiRenderer // // Created by Shadowfacts on 12/16/20. // import Foundation import HTMLEntities public class GeminiHTMLRenderer { public var linkPrefix: ((URL) -> String?)? public var addHeadingLineIDs = true public var addLinkClass = true public init() { } public func renderDocumentToHTML(_ doc: Document) -> String { var str = "" var inPreformatting = false var inList = false for (index, line) in doc.lines.enumerated() { if inList && !line.isListItem { str += "" inList = false } switch line { case let .text(text): str += "
\(text.htmlEscape())
" case let .link(url, text: maybeText): let text = maybeText ?? url.absoluteString let linkPrefix = self.linkPrefix?(url) ?? "" str += "\(linkPrefix)\(text.htmlEscape())
" case .preformattedToggle(alt: _): inPreformatting = !inPreformatting if inPreformatting { str += "" } else { str += "" } case let .preformattedText(text): str += text.htmlEscape() str += "\n" case let .heading(text, level: level): let tag = "h\(level.rawValue)" str += "<\(tag)" if addHeadingLineIDs { str += " id=\"l\(index)\"" } str += ">\(text.htmlEscape())\(tag)>" case let .unorderedListItem(text): if !inList { inList = true str += "
\(text.htmlEscape())" } } return str } } extension Document.Line { var isListItem: Bool { switch self { case .unorderedListItem(_): return true default: return false } } }