Modul:HtmlBuilder
Modul ini dilindungi. Modul ini sangat mencolok yang digunakan oleh banyak halaman, atau sangat sering disubstitusikan. Karena vandalisme atau kesalahan akan mempengaruhi banyak halaman, dan suntingan kecil dapat memberi beban besar pada server, modul ini dilindungi dari penyuntingan. |
-- Module for building complex HTML (e.g. infoboxes, navboxes) using a fluent interface.
local HtmlBuilder = {}
local metatable = {}
metatable.__index = function(t, key)
local ret = rawget(t, key)
if ret then
return ret
end
ret = metatable[key]
if type(ret) == 'function' then
return function(...)
return ret(t, ...)
end
else
return ret
end
end
metatable.__tostring = function(t)
local ret = {}
t._build(ret)
return table.concat(ret)
end
metatable._build = function(t, ret)
if t.tagName then
table.insert(ret, '<' .. t.tagName)
for i, attr in ipairs(t.attributes) do
table.insert(ret, ' ' .. attr.name .. '="' .. attr.val .. '"')
end
if #t.styles > 0 then
table.insert(ret, ' style="')
for i, prop in ipairs(t.styles) do
if type(prop) == 'string' then -- added with cssText()
table.insert(ret, prop .. ';')
else -- added with css()
table.insert(ret, prop.name .. ':' .. prop.val .. ';')
end
end
table.insert(ret, '"')
end
if t.selfClosing then
table.insert(ret, ' /')
end
table.insert(ret, '>')
end
for i, node in ipairs(t.nodes) do
if node then
if type(node) == 'table' then
node._build(ret)
else
table.insert(ret, tostring(node))
end
end
end
if t.tagName and not t.unclosed and not t.selfClosing then
table.insert(ret, '</' .. t.tagName .. '>')
end
end
metatable.node = function(t, builder)
if builder then
table.insert(t.nodes, builder)
end
return t
end
metatable.wikitext = function(t, ...)
local vals = {...}
for i = 1, #vals do
if vals[i] then
table.insert(t.nodes, vals[i])
end
end
return t
end
metatable.newline = function(t)
table.insert(t.nodes, '\n')
return t
end
metatable.tag = function(t, tagName, args)
args = args or {}
args.parent = t
local builder = HtmlBuilder.create(tagName, args)
table.insert(t.nodes, builder)
return builder
end
local function getAttr(t, name)
for i, attr in ipairs(t.attributes) do
if attr.name == name then
return attr
end
end
end
metatable.attr = function(t, name, val)
if type(val) == 'string' or type(val) == 'number' then
-- if caller sets the style attribute explicitly, then replace all styles previously added with css() and cssText()
if name == 'style' then
t.styles = {val}
return t
end
local attr = getAttr(t, name)
if attr then
attr.val = val
else
table.insert(t.attributes, {name = name, val = val})
end
end
return t
end
metatable.addClass = function(t, class)
if class then
local attr = getAttr(t, 'class')
if attr then
attr.val = attr.val .. ' ' .. class
else
t.attr('class', class)
end
end
return t
end
metatable.css = function(t, name, val)
if type(val) == 'string' or type(val) == 'number' then
for i, prop in ipairs(t.styles) do
if prop.name == name then
prop.val = val
return t
end
end
table.insert(t.styles, {name = name, val = val})
end
return t
end
metatable.cssText = function(t, css)
if css then
table.insert(t.styles, css)
end
return t
end
metatable.done = function(t)
return t.parent or t
end
metatable.allDone = function(t)
while t.parent do
t = t.parent
end
return t
end
function HtmlBuilder.create(tagName, args)
args = args or {}
local builder = {}
setmetatable(builder, metatable)
builder.nodes = {}
builder.attributes = {}
builder.styles = {}
builder.tagName = tagName
builder.parent = args.parent
builder.unclosed = args.unclosed or false
builder.selfClosing = args.selfClosing or false
return builder
end
return HtmlBuilder