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 pType
true
julia> pType
pType (alias for HTMLElement{Val{:p}})
This type is related to the element's class
field:
julia> element.class isa pVal
true
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.attributes
NamedTuple()
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 withCustomAttributes
HTMLElement{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 withCustomConfig
HTMLElement{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 withCustomChildren
HTMLElement{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:
attributes
child
orchildren
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.