A DSL for Lua 5.2+ that lets you write Lua code that resembles HTML. When you're done, you can render the tree it builds to actual HTML!
local html = require('html')
local document = html {
html.head {
html.style [[
.red {
background: #800;
}
]]
},
html.body {
html.p 'hello world',
html.ul {
html.li 'foo',
html.li 'bar',
html.li {class='red', 'baz'}
}
}
}
-- write html to stdout
print(document:render())
Lua supports an alternate function call syntax for unary functions that take either string literals or table constructors:
-- these are equivalent:
print 'hello world'
print('hello world')
-- these are also equivalent:
f {a=1, b=3, c=5}
f({a=1, b=3, c=5})
(Ab)using this this feature, we can bend Lua to do some crazy things.
Substitute <element>
for any valid HTML5
element. When data
is a table, its dictionary
elements are used as attributes and its sequence elements are used as HTML
elements and text. When data
is a string, it is used as the only child of the
resulting element. data
can also be omitted to obtain an element with no
children or attributes. The return value is an element
.
(html.p()):render()
-- <p></p>
(html.p 'hello world'):render()
-- <p>hello world</p>
(html.ul {class='list', html.li 'a', html.li 'b'}):render()
-- <ul class="list"><li>a</li><li>b</li></ul>
Accepts a sequence table of either strings or HTML elements, and passes the strings through untouched while rendering the HTML elements to strings. The result is a concatenated string with the strings and rendered elements combined.
html.rendermixed {'hello ', html.span 'world'}
-- hello <span>world</span>
The HTML module is callable. It is equivalent to calling html.html
to create
an <html>
element.
(html {html.body {html.p 'hello world'}}):render()
-- <html><body><p>hello world</p></body></html>
Converts the element to an HTML string.
(html.p 'hello world'):render()
-- <p>hello world</p>
Appends data
to the element. data
should be either an element
or a
string
.
local para = html.p()
para:appendchild(html.span 'hello')
para:appendchild(' world')
para:render()
-- <p><span>hello</span> world</p>
Adds an attribute to the element. Attempting to add an attribute when one
already exists with the same name will result in the first one being
overwritten. When value
is a string
, embedded quotation marks will be
escaped; otherwise, value
remains untouched.
local para = html.p 'hello world'
para:addattr('class', 'shiny')
para:render()
-- <p class="shiny">hello world</p>
local para = html.p()
para:addattr('class', 'old')
para:addattr('class', 'new')
para:render()
-- <p class="new"></p>
local para = html.p()
para:addattr('data-desc', 'it is "cool"')
para:addattr('data-value', 123)
para:render()
-- <p data-desc="it is \"cool\"" data-value="123"></p>
Renders the opening tag for this element, which includes attributes.
local para = html.p {class='shiny', 'hello world'}
para:opentag()
-- <p class="shiny">
Renders the closing tag for this element, regardless of whether or not it is a void element.
local para = html.p {class='shiny', 'hello world'}
para:closetag()
-- </p>
Returns the string 'element'
if t
is a table
whose metatable indexes
html.element
. Otherwise, returns nil
.
Licensed under the Apache License 2.0. Refer to the LICENSE
file for more
information.