resultBuilder
support for
swift-markdown.
The default way to build Markdown in swift-markdown is to use varargs initializers, e.g. as in the example from the README.md:
let document = Document(
Paragraph(
Text("This is a "),
Emphasis(
Text("paragraph."))))
Wouldn't it be nice to be able to use a SwiftUI like "resultBuilder" syntax, like:
let document = Document {
Paragraph {
"This is a "
"paragraph"
.emphasis()
}
}
And maybe even control structures like:
let document = Document {
"Our Tasks:"
.font(.largeTitle)
List {
ForEach(todos) { todo in
Text(todo.title)
}
}
}
Or custom Markdown "views":
struct TOC: DynamicMarkdownBlock {
let pages : [ Page ]
var body: [ MarkdownBlock ] {
"Table of Contents"
.font(.title)
ForEach(pages) { page in
Paragraph {
Text(page.title)
.font(.title2)
Text(page.abstract)
}
}
}
}
That's what we play with here.
Maybe we can get it to a state suitable for a PR on swift-markdown itself.
An experiment for curious people. Work in progress.
It is not entirely clear how useful this thing is. Is there really a usecase for building Markdown in Swift? 😃
A goal is/was to not come up with protocols/structures specific to the resultBuilders, but to directly attach to the ones provided by swift-markdown already.
If that would be internal to the Markdown module, a few hacky things could be dropped (i.e. because the API could be accessed).
The implementation also doesn't have to resort to the type-safyness
attached to SwiftUI style setups, because the swift-markdown
protocols do not use associated types.
Also, it doesn't need two-way setups like Binding
.
Things missing:
- table stuff (needs an own builder for scoping the contents), but could be similar to the macOS SwiftUI table
-
List
- conditionals
- finish the ForEach
- an Environment maybe
- also add an HTML resultBuilder?
- many more things?
Maybe more things from SwiftBlocksUI could be used (it generates Slack JSON block structures, but those are essentially just fancy markdown).
Example Package.swift:
// swift-tools-version:5.3
import PackageDescription
let package = Package(
name : "MyWebsite",
products : [ .executable(name: "MyWebsite", targets: [ "MyWebsite" ]) ],
dependencies : [
.package(url: "https://github.com/DoccZz/SwiftMarkdownBuilder.git", from: "0.1.0")
],
targets: [
.target(name: "MyWebsite", dependencies: [
.product(name: "MarkdownBuilder", package: "SwiftMarkdownBuilder")
])
]
)
SwiftMarkdownBuilder is brought to you by the Always Right Institute and ZeeZide. We like feedback, GitHub stars, cool contract work, presumably any form of praise you can think of.