Add helpers for rendering a Gemini document back to source

This commit is contained in:
Shadowfacts 2020-07-13 00:02:53 -04:00
parent f870daa634
commit 1a4be887d3
Signed by: shadowfacts
GPG Key ID: 94A5AB95422746E5
2 changed files with 100 additions and 0 deletions

View File

@ -15,6 +15,12 @@ public struct Document {
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 extension Document {
@ -26,11 +32,49 @@ public extension Document {
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 "###"
}
}
}
}

View File

@ -0,0 +1,56 @@
//
// DocumentTests.swift
// GeminiFormatTests
//
// Created by Shadowfacts on 7/12/20.
//
import XCTest
@testable import GeminiFormat
class DocumentTests: XCTestCase {
func testLineText() {
XCTAssertEqual(Document.Line.text("some text").geminiText(), "some text")
XCTAssertEqual(Document.Line.link(URL(string: "gemini://example.com/foo?bar")!, text: "some link").geminiText(), "=> gemini://example.com/foo?bar some link")
XCTAssertEqual(Document.Line.link(URL(string: "gemini://example.com/foo?bar")!, text: nil).geminiText(), "=> gemini://example.com/foo?bar")
XCTAssertEqual(Document.Line.preformattedToggle(alt: "blah").geminiText(), "```blah")
XCTAssertEqual(Document.Line.preformattedToggle(alt: nil).geminiText(), "```")
XCTAssertEqual(Document.Line.preformattedText("test").geminiText(), "test")
XCTAssertEqual(Document.Line.heading("one", level: .h1).geminiText(), "# one")
XCTAssertEqual(Document.Line.heading("two", level: .h2).geminiText(), "## two")
XCTAssertEqual(Document.Line.heading("three", level: .h3).geminiText(), "### three")
XCTAssertEqual(Document.Line.unorderedListItem("list item").geminiText(), "* list item")
XCTAssertEqual(Document.Line.quote("quoted").geminiText(), "> quoted")
}
func testDocumentText() {
let doc = Document(url: URL(string: "gemini://example.com")!, lines: [
.text("text"),
.link(URL(string: "gemini://example.com/")!, text: "a link"),
.link(URL(string: "gemini://example.com/foo?bar")!, text: nil),
.preformattedToggle(alt: "blah"),
.preformattedText("test"),
.preformattedToggle(alt: nil),
.heading("one", level: .h1),
.heading("two", level: .h2),
.heading("three", level: .h3),
.unorderedListItem("list item"),
.quote("quoted"),
])
XCTAssertEqual(doc.toGeminiText(), """
text
=> gemini://example.com/ a link
=> gemini://example.com/foo?bar
```blah
test
```
# one
## two
### three
* list item
> quoted
""")
}
}