HTML in shrubbery notation: lower shrubbery to a markup tree, and print a markup tree back as shrubbery
Dependencies
///|
test "a page" {
let src =
#|doctype()
#|html(lang: "en"):
#| head():
#| meta(charset: "utf-8")
#| title(): "Shrubbery HTML"
#| body():
#| main(class: "card"):
#| h1(): "Hello"
inspect(
@shrubbery_html.to_html(src),
content=(
#|<!DOCTYPE html>
#|<html lang="en">
#| <head>
#| <meta charset="utf-8">
#| <title>Shrubbery HTML</title>
#| </head>
#| <body>
#| <main class="card">
#| <h1>Hello</h1>
#| </main>
#| </body>
#|</html>
#|
),
)
}| HTML | what it is | Shrubbery HTML |
|---|---|---|
| <div>…</div> | an element | div(): … |
| <br> | a void element | br() |
| src="a.png" | an attribute | src: "a.png" |
| checked | a valueless attribute | checked |
| data-id="3" | a hyphenated name | data_id: "3" |
| xlink:href="#a" | a name _→- cannot reach | attr("xlink:href", "#a") |
| <my-element> | a custom element | my_element(): |
| <text> (SVG) | a name this syntax has taken | element("text"): |
| Hello | text | "Hello" |
| | a character reference | the character, inside the string |
| <!-- x --> | a comment | comment(" x ") |
| <!DOCTYPE html> | the doctype | doctype() |
| <script>…</script> | raw text | script(): @{…} |
| <svg>…</svg> | foreign content | svg(): … |
| <![CDATA[…]]> | CDATA, foreign only | cdata("…") |
///|
test "the space is in the string, or it is nowhere" {
inspect(
@shrubbery_html.to_html(
"p():\n \"Read \"\n a(href: \"/x\"): \"more\"\n",
style=Minified,
),
content="<p>Read <a href=/x>more</a></p>",
)
inspect(
@shrubbery_html.to_html(
"p():\n \"Read\"\n a(href: \"/x\"): \"more\"\n",
style=Minified,
),
content="<p>Read<a href=/x>more</a></p>",
)
}///|
test "SVG, and HTML again inside it" {
let src =
#|svg(viewBox: "0 0 24 24"):
#| linearGradient(id: "g"):
#| stop(offset: "0%", stop_color: "#2F6B4F")
#| foreignObject():
#| br()
inspect(
@shrubbery_html.to_html(src, style=Minified),
content="<svg viewBox=\"0 0 24 24\"><linearGradient id=g><stop offset=0% stop-color=#2F6B4F /></linearGradient><foreignObject><br></foreignObject></svg>",
)
}///|
test "a script is text, not markup" {
let src =
#|script(type: "module"):
#| @{
#| if (a < b) { go() }
#| }
inspect(
@shrubbery_html.to_html(src, style=Minified),
content="<script type=module>if (a < b) { go() }</script>",
)
}///|
test "HTML becomes shrubbery, and back again" {
let shrub = @shrubbery_html.to_shrubbery(
"<p>Read <a href=\"/x\">more</a>.</p>",
)
inspect(
shrub,
content=(
#|p():
#| "Read "
#| a(href: "/x"):
#| "more"
#| "."
#|
),
)
inspect(
@shrubbery_html.to_html(shrub, style=Minified),
content="<p>Read <a href=/x>more</a>.</p>",
)
}///|
test "a block swallows the rest of its line" {
let l = @shrubbery_html.lower("p(): \"Hello \" strong(): \"world\" \"!\"\n")
// The `!` is a child of the `strong`, not a sibling of it.
inspect(
@write.document(l.document(), style=Minified),
content="<p>Hello <strong>world!</strong></p>",
)
inspect(
l.diagnostics()[0].kind.code(),
content="shrubhtml::trailing_run_after_block",
)
}///|
test "an HTML habit is met with its replacement" {
let l = @shrubbery_html.lower("<div>\n")
inspect(l.diagnostics()[0].kind.code(), content="shrubhtml::sigil_tag")
}| package | what |
|---|---|
| names | the tables: _ ⇄ -, the reserved calls, string quoting |
| kind, error | diagnostics, and the one bridge to error-report |
| lower | shrubbery → a markup tree |
| emit | a markup tree → shrubbery |
fn lower(src : String, strict? : Bool, hook? : (String, Array[Node]) -> String??) -> Lowered raise ShrubHtmlErrorInstall
Download zipHTML in shrubbery notation: lower shrubbery to a markup tree, and print a markup tree back as shrubbery
Dependencies