Library to easily generate XML with a clean Lua DSL.
luarocks install luaxmlgenerator
local xml_gen = require("xml-generator")
local xml = xml_gen.xml
local doc = xml.html {charset="utf-8", lang="en"} {
xml.head {
xml.title "Hello World"
},
xml.body {
xml.h1 "Hello World",
xml.div {id="numbers"} {
function() --run as a coroutine
for i = 1, 10 do
coroutine.yield(xml.p(i))
end
end
}
}
}
print(doc)
Table of tags that should not be sanitized. By default, it contains script
and style
.
local xml_gen = require("xml-generator")
xml_gen.no_sanitize["mytag"] = true
local doc = xml_gen.xml.mytag [[
Thsi will not be sanitized! <><><><><><%%%<>%<>%<>% you can use all of this!
]]
By default, within xml_gen.xml
there is a special key called lua
which just allows for _G
to be accessed. This is useful if you use xml_gen.declare_generator
, which overloads the _ENV
(setfenv
on 5.1), where the _G
would not be ordinarily accessible.
local xml_gen = require("xml-generator")
local gen = xml_gen.declare_generator(function()
return html {
head {
title "Hello World";
};
body {
p { "The time of generation is ", lua.os.date() }
};
}
end)
print(gen())
Using xml_gen.component
you can create your own components. Here is an example of a random_number
component
---@param context fun(args: { [string] : any }, children: XML.Children): XML.Node?
---@return XML.Component
function export.component(context)
local xml_gen = require("xml-generator")
local xml = xml_gen.xml
math.randomseed(os.time())
local random_number = xml_gen.component(function(args, children)
local min = args.min or 0
--remove these from the args so they dont show up in our HTML attributes later
args.min = nil
local max = args.max or 100
args.max = nil
coroutine.yield(xml.p "This is a valid coroutine too!")
return xml.span(args) {
math.random(min, max),
children --children is a table of all the children passed to the component, this may be empty
}
end)
local doc = xml.html {
xml.body {
random_number {min = 0, max = 100};
random_number {max=10} {
xml.p "This is inside the span!"
};
random_number;
}
}
print(doc)
---@generic T
---@param func fun(...: T): XML.Node
---@return fun(...: T): XML.Node
function export.declare_generator(func)
Allows you to create a function in which the _ENV
is overloaded with the xml
table. This allows you to write XML more concisely (see example above).
---@param css { [string | string[]] : { [string | string[]] : (number | string | string[]) } }
---@return XML.Node
function export.style(css)
Creates an HTML style
tag with the given table
local xml_gen = require("xml-generator")
local style = xml_gen.style {
[{ "body", "html" }] = {
margin = 0,
padding = 0,
},
body = {
background = "#000",
color = "#fff",
}
--etc
}
print(style)
---WILL NOT BE SANITIZED
---@param ... string
---@return string[]
function export.raw(...) end
Inserts raw (NOT SANITIZED) strings into the document.
## API
You do not need to generate XML with this library, instead, you can use an `XML.Node` as its own object.
```lua
---@class XML.Children
---@field [integer] XML.Node | string | fun(): XML.Node
---@class XML.AttributeTable : XML.Children
---@field [string] string | boolean | number
---@class XML.Node
---@operator call(XML.AttributeTable): XML.Node
---@field tag string
---@field children XML.Children
---@field attributes XML.AttributeTable
---@class XML.Component : XML.Node
---@field attributes { [string] : any } The attributes can be any type for `component`s, but not for `node`s
---@field context fun(args: { [string] : any }, children: XML.Children): XML.Node?
local xml_gen = require("xml-generator")
local xml = xml_gen.xml
local my_node = xml.div {id="my-div"} {
xml.p {id="p-1"} "Hello World";
xml.p {id="p-2"} "Hello World";
xml.p {id="p-3"} "Hello World";
}
print(my_node.tag) --div
print(my_node.attributes.id) --my-div
for i, child in ipairs(my_node.children) do
print(i, child.tag, child.attributes.id)
end
print(my_node)
attributes
and children
can be empty, but will never be nil
.
tag
will be nil
if the node is a component
.