Add helpers for rendering a Gemini document back to source
This commit is contained in:
parent
f870daa634
commit
1a4be887d3
|
@ -15,6 +15,12 @@ public struct Document {
|
||||||
self.url = url
|
self.url = url
|
||||||
self.lines = lines
|
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 {
|
public extension Document {
|
||||||
|
@ -26,11 +32,49 @@ public extension Document {
|
||||||
case heading(String, level: HeadingLevel)
|
case heading(String, level: HeadingLevel)
|
||||||
case unorderedListItem(String)
|
case unorderedListItem(String)
|
||||||
case quote(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 {
|
public extension Document {
|
||||||
enum HeadingLevel: Int {
|
enum HeadingLevel: Int {
|
||||||
case h1 = 1, h2 = 2, h3 = 3
|
case h1 = 1, h2 = 2, h3 = 3
|
||||||
|
|
||||||
|
var geminiText: String {
|
||||||
|
switch self {
|
||||||
|
case .h1:
|
||||||
|
return "#"
|
||||||
|
case .h2:
|
||||||
|
return "##"
|
||||||
|
case .h3:
|
||||||
|
return "###"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
""")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue