HTML Elements

Element class

At the heart of the HTMLBuilder.jl functionality is the HTMLElement type. Each html element is an instance of this type; for instance, p is of type pType, and alias for HTMLElement{pVal}, where pVal is an alias for Val{:p}. After building the element

julia> using HTMLBuilder
julia> element = p("Some text")<p>Some text</p>

you can test its type:

julia> element isa pTypetrue
julia> pTypepType (alias for HTMLElement{Val{:p}})

This type is related to the element's class field:

julia> element.class isa pValtrue

Element attributes

The attributes field contains the information about the HTML attributes of an element's HTML tag. This is by default an empty NamedTuple:

julia> element = p("Some text")<p>Some text</p>
julia> element.attributesNamedTuple()

However, any attributes you pass during construction will be stored there:

julia> href = "https://rafaelbailo.github.io/HTMLBuilder.jl/";
julia> element = a((; href), "The HTMLBuilder.jl documentation")<a href='https://rafaelbailo.github.io/HTMLBuilder.jl/'>The HTMLBuilder.jl documentation</a>
julia> element.attributes(href = "https://rafaelbailo.github.io/HTMLBuilder.jl/",)

Any attributes with value "" or true will be treated as boolean HTML attributes. Attributes with value false will be ignored:

julia> button((; disabled=""), "Button text")<button disabled>Button text</button>
julia> button((; disabled=true), "Button text")<button disabled>Button text</button>
julia> button((; disabled=false), "Button text")<button>Button text</button>

You can customise the default attributes of a custom element by extending the HTMLBuilder.get_default_attributes method:

julia> @register withCustomAttributesHTMLElement{Val{:withCustomAttributes}}
julia> HTMLBuilder.get_default_attributes(s::withCustomAttributesVal) = (; disabled = true)
julia> withCustomAttributes()<withCustomAttributes disabled></withCustomAttributes>

Element config

The config field contains the configuration options of an HTML element. Two options are currently available.

The indent option controls whether the contents of an element are indented. Compare

julia> p("Some text.")<p>Some text.</p>

with

julia> p("Some text.", (; indent = false))<p>Some text.</p>

The single_tag option is used to reduce an HTML element to a single tag. This is used by default for the br and img elements:

julia> br()<br>
julia> img()<img>

You can customise the default configuration of a custom element by extending the HTMLBuilder.get_default_config method:

julia> @register withCustomConfigHTMLElement{Val{:withCustomConfig}}
julia> HTMLBuilder.get_default_config(s::withCustomConfigVal) = (; indent = true)
julia> withCustomConfig("Some content.")<withCustomConfig> Some content. </withCustomConfig>

Element children

The children field contains the content ("children") of an HTML element. If we define a complex HTML expression,

julia> element = body(dv(h1("A title"), p("Some text.")))<body>
  <div>
    <h1>A title</h1>
    <p>Some text.</p>
  </div>
</body>

we can then explore the content by recursively accesing the children field:

julia> element.children[1]<div>
  <h1>A title</h1>
  <p>Some text.</p>
</div>
julia> element.children[1].children[1]<h1>A title</h1>
julia> element.children[1].children[2]<p>Some text.</p>

The Content type

The field children is always a Vector{Content}, where Content = Union{HTML, AbstractString}, and HTML is an abstract type. All HTMLElements inherit from HTML.

You can customise the default children of a custom element by extending the HTMLBuilder.get_default_children method, always returning a Vector{Content}:

julia> @register withCustomChildrenHTMLElement{Val{:withCustomChildren}}
julia> function HTMLBuilder.get_default_children(s::withCustomChildrenVal, config) return [h1("Children one"), p("Children two")] end
julia> withCustomChildren()<withCustomChildren><h1>Children one</h1><p>Children two</p></withCustomChildren>

Beyond the default settings

While every element has default attributes, config, and children, they can be specifically set on each construction. Given an element (such as p), the following are valid calls:

  • Only specifying the children:
    • element(child::Content)
    • element(children::Vector{Content})
    • element(children::Content...)
  • Specifying the attributes and the children:
    • element(attributes::NamedTuple, child::Content)
    • element(attributes::NamedTuple, children::Vector{Content})
    • element(attributes::NamedTuple, children::Content...)
  • Specifying the children and the configuration:
    • element(child::Content, config::NamedTuple)
    • element(children::Vector{Content}, config::NamedTuple)
  • Specifying the attributes, the children, and the configuration:
    • element(attributes::NamedTuple, child::Content, config::NamedTuple)
    • element(attributes::NamedTuple, children::Vector{Content}, config::NamedTuple)

Note that the order is always:

  1. attributes
  2. child or children
  3. config

where attributes or config may be omitted.

Note further that, when specifying several children, we must usually pass children::Vector{Content}. However, when config is not speficied, children::Content... is also allowed.