html_dsl
A fun way to create HTML in Gleam.
Premise
I wanted a simple framework to build HTML and I saw a way forward with strings.
I thought that Gleam had a very unique type system in which I could wrap strings around a named type like Html
or Head
. The way I implemented it does restrict general reactivity through Gleam itself, but I never thought making this a standalone framework as an option. The idea was to combine this with existing frontend libraries like HTMX to add that touch of reactivity.
Going forward
I’m not sure what else to expand except implementing more existing HTML elements.
Examples
import html_dsl/types/html.{Html, Attribute, head, style, script, body, title, charset, meta, button}
import html_dsl/types/id.{Id}
import html_dsl/types/class.{Class}
// If you're familiar with HTML, this might seem pretty standalone
fn main() {
let my_doc = Html(
"en", // States the locale
head([
title("My doc"),
charset("utf-8"),
meta("description","This is my doc"),
meta("viewport","width=device-width, initial-scale=1"),
style("https://cdn.tailwindcss.com"),
script("https://unpkg.com/htmx.org@1.9.11")
])
// Most elements are strings under the hood so we can concat them
<> body(
Id("main-content"), // This declares we do not need an id
Class("text-white"),
[], // Have no custom attributes
button(
id.Nil,
class.Nil,
[
Attribute("hx-trigger", "click"),
Attribute("hx-get", "/clicked"),
Attribute("hx-boost", "true"),
Attribute("target", "#main-content")
],
"Happy Days"
)
)
)
// We can access the document as a string
let _ = html.html_to_string(my_doc)
// or through the pipe operator
let _ = my_doc
|> html.html_to_string()
}
So why use strings to build each element? Ultimately everything is parsed into a string so I wanted to get straight to the point with little to no intermediate step. Don’t get me wrong, I still have intermediate’s here and there, but that’s more for explicitness. It prevents bad HTML from being written.
Development
./dev.sh run # Run the project
./dev.sh test # Run the tests
./dev.sh docs # Generate the documentation
./dev.sh build # Build the project