html_dsl

Hex Docs test

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
Search Document