Skip to content

Instantly share code, notes, and snippets.

@OTDE
Created April 29, 2026 00:55
Show Gist options
  • Select an option

  • Save OTDE/aab9f4f274761f9533cad5afc5fea193 to your computer and use it in GitHub Desktop.

Select an option

Save OTDE/aab9f4f274761f9533cad5afc5fea193 to your computer and use it in GitHub Desktop.
Tiny HTML Julia DSL
const Attribute = Pair{Symbol,<:Any}
const BareElement = Tuple{Symbol,Vararg{Any}}
const HTMLElement = Tuple{Symbol,Union{NamedTuple,Nothing},Vararg{Any}}
const VoidElement = Tuple{Symbol,Union{NamedTuple,Nothing}}
const VoidTags = (:area, :base, :br, :col, :embed, :hr, :img, :input, :link, :meta, :param, :source, :track, :wbr)
escapehtml(text) = replace(text, '&' => "&amp;", '<' => "&lt;", ">" => "&gt;", '"' => "&quot;", ''' => "&#39;")
kebabcase(symbol::Symbol) = replace(string(symbol), '_' => '-')
struct Raw{Character} end
raw(character) = Raw{character}()
writehtml(io::IO) = Base.Fix1(writehtml, io)
writehtml(io, args...) = foreach(writehtml(io), args)
writehtml(::IO, ::Nothing) = nothing
writehtml(io::IO, text::String) = write(io, escapehtml(text))
writehtml(io::IO, symbol::Symbol) = writehtml(io, kebabcase(symbol))
writehtml(io::IO, ::Raw{Character}) where {Character} = write(io, Character)
writehtml(io::IO, attributes::NamedTuple) = writehtml(io, pairs(attributes)...)
writehtml(io::IO, (key, value)::Attribute) = writehtml(io, ' ', key, '=', raw('"'), string(value), raw('"'))
writehtml(io::IO, (kind, children...)::BareElement) = writehtml(io, (kind, nothing, children...))
writehtml(io::IO, (kind, attributes)::VoidElement) = writehtml(io, raw('<'), kind, attributes, raw('>'))
writehtml(io::IO, (kind, attributes, children...)::HTMLElement) =
kind in VoidTags ?
writehtml(io, (kind, attributes)) :
writehtml(io, (kind, attributes), children..., raw('<'), '/', kind, raw('>'))
function renderhtml(document::Element)
buffer = IOBuffer("<!DOCTYPE html>")
writehtml(buffer, document)
return String(take!(buffer))
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment