This module depends on the following other modules: |
This module uses TemplateStyles: |
This module creates an infobox using the builder pattern. All infoboxes using this module can be found at Category:Infobox modules.
Building an infobox
For an infobox to be built without errors, certain essential functions must be called before others. The following table details groups of functions and their priorities. The lower the number, the higher the priority. The functions setHeaderTextColor()
and setHeaderBackgroundColor()
are not required, but their CSS changes will not be applied if called later. In addition, the functions that add rows to the table, addHeader()
, addImage()
, and addRow()
are not all required, but is it recommended to use at least addHeader()
and addRow()
.
Priority | Functions |
---|---|
1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
Import the module
local InfoboxBuilder = require('Module:InfoboxBuilder')
Unpack the frame arguments
function p.main(frame)
local args = frame:getParent().args
...
Create the infobox object
local infobox = InfoboxBuilder.new()
Set the infobox name
Setting the infobox name sets the template that the infobox links to inside of the navbar.
infobox:setName('Infobox')
Define the parameters
When defining the parameters, the arguments will be processed when given a function or table. fn
is an optional processing function or table that will transform the raw argument value into a specific format. An optional default value for the raw argument can be set using the default
option.
An example of using fn
would be to have fn
be a function that splits a comma separated list into a table in Lua.
infobox:setParams {
...
}
Pass in the arguments
infobox:setArgs(args)
Process the arguments
Processing the arguments will set default value (if it exists) and turn the raw argument passed in from setArgs(args) into a processed format for each parameter. This step is required or else the infobox will not work.
infobox:processArgs()
Specify a category map
A category map can be optionally set. This uses the processed argument and generates the correct categories.
infobox:setCategoryMap({
...
})
Prepare
Create the look of the infobox by adding headers, images, or rows. If the values shown in these cells use values from parameters, an optional postprocessing function or table fn
will transform the processed arguments for display purposes.
-- add a header or subheader
infobox:addHeader(
{...},
{...}
)
-- add an image
infobox:addImage(
{...},
{...}
)
-- add a row
infobox:addRow(
{...},
{...}
)
Build
To build the infobox from data into an HTML table, call the tostring() function.
infobox:tostring()
Get the categories from the category map
To get the categories, call the getCategories()
function.
infobox:getCategories()
Functions
For the following functions, assume an InfoboxBuilder object called "infobox" already exists.
local infobox = InfoboxBuilder.new()
Public functions
new
This function is required.
InfoboxBuilder.new()
Creates a new InfoboxBuilder object.
setName
This function is required.
This function is chainable.
infobox:setName(arg)
- arg
arg
should be a string
. Setting the infobox name will link the navbar to the correct template page and template talk page.
setHeaderTextColor
This function is optional.
This function is chainable.
infobox:setHeaderTextColor(arg)
- arg
arg
should be a string
that contains a valid CSS color (hex code, rgb value, hsl value, etc.). Calling this function will change the color of the text in the infobox's headers and subheaders. The changes will not apply to headers added before this function is called, so it is recommended to call this function early.
setHeaderBackgroundColor
This function is optional.
This function is chainable.
infobox:setHeaderBackgroundColor(arg)
- arg
arg
should be a string
that contains a valid CSS color (hex code, rgb value, hsl value, etc.). Calling this function will change the background color of the infobox's headers and subheaders. The changes will not apply to headers added before this function is called, so it is recommended to call this function early.
setParams
This function is required.
This function is chainable.
infobox:setParams(...)
This function sets the valid parameters, their default values, and their formatting.
The arguments passed in should be tables of format:
{
name = <paramName>,
fn = <processingFn>,
default = <default>
}
- paramName
paramName
should be a valid string
that is unique. This name serves the key used to grab the raw values from the args
table passed in from setArgs()
. It also serves as the key for each parameter and will be referenced later.
- processingFn
processingFn
should be a function
or a table
that transforms the raw value of the argument passed in. This value is optional.
A collection of predefined processing functions can be found at Module:ProcessingFunctions.
- default
default
should be a string that serves as the default value if no raw value is present for the key in the args
table. This value is optional.
setArgs
This function is required.
This function is chainable.
infobox:setArgs(args)
- args
args
should be a table
with key value pairs representing parameter names and values.
getRawArgs
infobox:getRawArgs()
This function returns the "private" rawArgs
associative array containing the raw values passed in from setArgs()
.
getProcessedArgs
infobox:getProcessedArgs()
This function returns the "private" procArgs
associative array after being processed.
getArgs
infobox:getArgs(which)
- which
which
should be a string
that is either "raw" or "processed" for the raw argument values or processed argument values, respectively.
This function returns the "private" rawArgs
or procArgs
associative arrays depending on the value of which
.
setCategoryMap
This function is optional.
This function is chainable.
infobox:setCategoryMap(catMap)
- catMap
catMap
should be a table
of table
s, where the key of the outer table corresponds with a parameter name and the key of the inner tables correspond with possible values of the associated parameter. The inner table values should be the category name related to each parameter value.
getCategories
infobox:getCategories()
This function returns a string
with autogenerated categories in wikitext form.
processArgs
This function is required.
This function is chainable.
infobox:processArgs()
This function processes the all the arguments passed in with the given processing functions defined when setting parameters.
addHeader
This function is optional, but recommended.
This function is chainable.
infobox:addHeader(arg, options)
This functions adds a header or subheader to the infobox, depending on the option set.
- arg
arg
should be a table
of the following format:
{
tag = <tag>,
content = <content>,
fn = <displayFn>,
attr = <attr>,
colspan = <colspan>,
rowspan = <rowspan>,
css = <css>
}
- tag
tag
should be a string
of value "argth" or "th".
- content
When tag
is set to "th", content
should contain the wikitext that will show up.
When tag
is set to "argth", content
should be a string
or table
of parameter names. This value will be passed into displayFn
if it is set.
- displayFn
displayFn
should be a function
that transforms one or more processed arguments (based on content
into something that can be displayed (ex. an HTML list). The order of the parameters in this function is the same as the order of content
, if content
is a table
. This value is optional.
A collection of predefined display functions can be found at Module:DisplayFunctions.
- attr
attr
should be a table
containing HTML attributes. The value gets passed into the mw.html:attr() function. This value is optional.
- colspan
colspan
should be a number
or string
denoting the number of columns this header spans. This value is optional.
- rowspan
rowspan
should be a number
or string
denoting the number of rows this header spans. This value is optional.
- css
css
should be a table
of CSS names and values. The value gets passed into the mw.html:css() function. This value is optional.
- options
options
should be a table
of the following format:
{
hideIfEmpty = <hideIfEmpty>,
subheader = <subheader>
}
- hideIfEmpty
hideIfEmpty
should be a table
containing strings of parameter names. If all values for those parameters are empty, then the header or subheader is hidden. This value is optional.
- subheader
subheader
should be a boolean
denoting whether the header should be a subheader or not. The default value is false. This value is optional.
addImage
This function is optional, but recommended.
This function is chainable.
infobox:addImage(cols, options)
This function adds a single image or multiple images inside of a row. For multiple images, it selectively hides all but one image using TabberNeue.
- cols
cols
should be a table
that is a numeric array. Each entry in this table should have the following format:
{
tag = <tag>,
content = <content>,
fn = <displayFn>,
tabName = <tabName>,
required = <required>
}
- tag
tag
should be a string
of value "argtd" or "td".
- content
When tag
is set to "td", content
should be a string
that shows up as the wikitext.
When tag
is set to "argtd", content
should be a string
or table
of parameter names. This value will be passed into displayFn
if it is set.
- displayFn
displayFn
should be a function
that transforms one or more processed arguments (based on content
into something that can be displayed (ex. an HTML list). The order of the parameters in this function is the same as the order of content
, if content
is a table
. This value is optional.
- tabName
tabName
should be a string
if there are multiple images. The value of this does nothing if there's only one image.
- required
required
should be a boolean
if the tab is required. This means that even if no value is provided, the tab will show up with a '?'.
- options
options
should be a table
of the following format:
{
hideIfEmpty = <hideIfEmpty>
}
- hideIfEmpty
hideIfEmpty
should be a table
containing strings of parameter names. If all values for those parameters are empty, then the image section is hidden. This value is optional.
addRow
This function is optional, but recommended.
This function is chainable.
infobox:addRow(cols, options)
This function adds anywhere from 1 to 30 cells to a row. The colspan for each cell is automatically set to be evenly split so that all cells are the same width. The exception is when there are two cells, where the first cell spans 12 columns and the second cell spans 18 cells.
- cols
cols
should be a table
that is a numeric array. Each entry in this table should have the following format:
{
tag = <tag>,
content = <content>,
fn = <displayFn>,
attr = <attr>,
colspan = <colspan>,
rowspan = <rowspan>,
css = <css>,
class = <class>,
cssFns = <cssFns>,
classFns = <classFns>
}
- tag
tag
should be a string
of value "argth", "argtd", "th", or "td".
- content
When tag
is set to "td" or "th", content
should contain the wikitext that will show up.
When tag
is set to "argtd" or "argth", content
should be a string
or table
of parameter names. This value will be passed into displayFn
if it is set.
- displayFn
displayFn
should be a function
that transforms one or more processed arguments (based on content
into something that can be displayed (ex. an HTML list). The order of the parameters in this function is the same as the order of content
, if content
is a table
. This value is optional.
A collection of predefined display functions can be found at Module:DisplayFunctions.
- attr
attr
should be a table
containing HTML attributes. The value gets passed into the mw.html:attr() function. This value is optional.
- colspan
colspan
should be a number
or string
denoting the number of columns this header spans. This value is optional.
- rowspan
rowspan
should be a number
or string
denoting the number of rows this header spans. This value is optional.
- css
css
should be a table
of CSS names and values. The value gets passed into the mw.html:css() function. This value is optional.
- class
class
should be either a string
with a class name or table
(numeric array) containing class names. Each class name gets passed into the mw.html:addClass() function. This value is optional.
- cssFns
cssFns
should be a table
of functions. Each function takes the processed value of parameter content
as input and should output a valid CSS table
. This value only applies to cells with tag "argth" or "argtd". This value is optional.
- classFns
classFns
should be a table
of functions. Each function takes the processed value of parameter content
as input and should output a class name string
. This value only applies to cells with tag "argth" or "argtd". This value is optional.
- options
options
should be a table
of the following format:
{
hideIfEmpty = <hideIfEmpty>,
defaultCss = <defaultCss>
}
- hideIfEmpty
hideIfEmpty
should be a table
containing strings of parameter names. If all values for those parameters are empty, then the cell is hidden. This value is optional.
- defaultCss
defaultCss
should be a table
of CSS names and values. This CSS applies to all cells in this row. This value is optional.
tostring
This function is required.
infobox:tostring()
This function "finishes" the infobox and returns an output HTML table with all styles automatically applied from Template:Infobox/styles.css. In order to generate an infobox, this function must be called.
Private functions
While these are not necessarily "private", these functions are not intended to be called externally.
getContent
infobox:getContent(paramName)
Gets the content for display for a specified parameter. If the value for a parameter has not been postprocessed, then the dFunc
for that parameter, if it exists, will be called.
shouldShow
infobox:shouldShow(paramNames)
This is a helper function to tell if a certain cell should be visible depending on the parameter names given. If all values for the parameters given have no value, then a cell should not show.
addSpacer
infobox:addSpacer()
This function sets up the 30 column layout by inserting an empty row. It also serves as a spacer.
addLinks
infobox:addLinks()
This function adds the navbar at the end of the infobox. This navbar contains links to the template page and the template talk page for this infobox. This uses the page using the value passed in from the setName()
function.
local Navbar = require('Module:Navbar')._navbar
local InfoboxBuilder = {}
InfoboxBuilder.__index = InfoboxBuilder
InfoboxBuilder.__tostring = InfoboxBuilder.tostring
local tagmap = {
th = 'th',
td = 'td',
argth = 'th',
argtd = 'td',
i18nth = 'th',
i18ntd = 'td',
}
--- Create the infobox
-- @return obj metatable
-- A metatable describing the infobox
function InfoboxBuilder.new()
local obj = setmetatable({
name = '',
headerColors = {
['color'] = nil,
['background-color'] = nil
},
params = {},
paramNames = { 'bg color', 'text color' },
rawArgs = {},
procArgs = {},
displayArgs = {},
categoryMap = {},
infobox = mw.html.create('table')
:addClass('infobox')
:css('width', '330px'),
finished = false
}, InfoboxBuilder)
return obj
end
--- Set the infobox name, for use with bottom links
-- @param arg string
-- Name of the template, not nil or empty
-- @return self
-- The current object
function InfoboxBuilder:setName(arg)
if arg == nil or arg == '' then
error("Template name must not be nil or empty")
end
self.name = arg
return self
end
--- Set the text color of the header
-- @param arg string
-- Text color of the header, should be a valid value for the CSS
-- "color" property, not nil or empty
-- @return self
-- The current object
function InfoboxBuilder:setHeaderTextColor(arg)
if arg == nil or arg == '' then
error("Header text color must not be nil or empty")
end
self.headerColors['color'] = arg
return self
end
--- Set the background color of the header
-- @param arg string
-- Background color of the header, should be a valid value for the
-- CSS "background-color" property, not nil or empty
-- @return self
-- The current object
function InfoboxBuilder:setHeaderBackgroundColor(arg)
if arg == nil or arg == '' then
error("Header background color must not be nil or empty")
end
self.headerColors['background-color'] = arg
return self
end
--- Sets the infobox params
-- @param ... {{ name, pFunc, dFunc, default }, ...}
-- name string
-- The name of the parameter, not nil, cannot be duplicate
-- pFunc function or table that processes the raw arguments
-- - A function that accepts the parameter as an argument and
-- returns a string or list, OR
-- - A table that has the parameter as a key
-- dFunc function
-- A function that accepts the parameter as an argument and
-- returns a string
-- default string or nil
-- The default value if no argument is given
-- @return self
-- The current object
function InfoboxBuilder:setParams(...)
for _, p in ipairs(...) do
if p.name == nil or p.name == "" then
error("param name must not be nil or empty")
end
if self.paramNames[p.name] then
error("param name cannot be duplicate")
end
self.params[p.name] = {
pFunc = p.pFunc,
dFunc = p.dFunc,
default = p.default
}
table.insert(self.paramNames, p.name)
end
return self
end
--- Sets the infobox arguments
-- @param args Frame
-- A frame object, passed in when invoked
-- @return self
-- The current object
function InfoboxBuilder:setArgs(args)
for name, value in pairs(args) do
if value ~= '' then
self.rawArgs[name] = value
end
end
if self.rawArgs['bg color'] then
self:setHeaderBackgroundColor(self.rawArgs['bg color'])
end
if self.rawArgs['text color'] then
self:setHeaderTextColor(self.rawArgs['text color'])
end
return self
end
--- Gets the raw argument values passed
-- @return args table
-- A table containing the args
function InfoboxBuilder:getRawArgs()
return self.rawArgs
end
--- Gets the argument values after being processed
-- @return args table
-- A table containing the args
function InfoboxBuilder:getProcessedArgs()
return self.procArgs
end
--- Gets the argument values of the table, for either raw or processed
-- @param which string
-- A string that determines which argument values to return
-- @retun args table
-- A table containing the args
function InfoboxBuilder:getArgs(which)
if which == 'raw' then
return self:getRawArgs()
elseif which == 'processed' then
return self:getProcessedArgs()
end
return {}
end
--- Sets the category map for each param
-- @param catMap
-- @return self
-- The current object
function InfoboxBuilder:setCategoryMap(catMap)
if catMap and type(catMap) == 'table' then
self.categoryMap = catMap
end
return self
end
--- Returns categories based on processed args
-- @return categories string
-- A string containing with all the categories
function InfoboxBuilder:getCategories()
local categories = {}
for name, value in pairs(self.procArgs) do
local catMap = self.categoryMap[name]
local valueType = type(value)
if catMap then
if valueType == "string" or
valueType == "boolean" or
valueType == "number" then
if catMap[value] then
table.insert(
categories,
string.format('[[Category:%s]]', catMap[value])
)
end
elseif valueType == "table" then
for _, val in ipairs(value) do
if catMap[val] then
table.insert(
categories,
string.format('[[Category:%s]]', catMap[val])
)
end
end
end
end
end
return table.concat(categories, '')
end
--- Processes raw args into a format usable by auto categorizer and display functions
-- @return self
-- The current object
function InfoboxBuilder:processArgs()
for name, param in pairs(self.params) do
local value = self.rawArgs[name] or param.default
local pFunc = param.pFunc
local funcType = type(pFunc)
if value then
if funcType == 'function' then
value = pFunc(value)
elseif funcType == 'table' then
value = pFunc[value]
end
end
self.procArgs[name] = value
end
return self
end
--- Gets the content associated with a parameter
-- @param paramName string
-- The param name, not nil or empty
-- @return content string
-- A string containing the content
function InfoboxBuilder:getContent(paramName)
if paramName == nil or paramName == "" then
error("Param must not be nil or empty")
end
if self.displayArgs[paramName] ~= nil then
return self.displayArgs[paramName]
end
local currentParam = self.params[paramName]
if currentParam == nil then
error(string.format("No such param with name: %s", paramName))
end
local content = self.procArgs[paramName]
local dFunc = currentParam.dFunc
local funcType = type(dFunc)
if content == nil then
return content
end
if funcType == 'function' then
content = dFunc(content)
end
self.displayArgs[paramName] = content
return content
end
--- Determines if the row should be shown based of a list of param names
-- @param paramNames { paramName, ... }
-- paramName string
-- The param name
-- @return shouldShow boolean
function InfoboxBuilder:shouldShow(paramNames)
if paramNames and #paramNames > 0 then
local actualValues = {}
for _, name in ipairs(paramNames) do
table.insert(actualValues, self:getContent(name))
end
if #actualValues == 0 then
return false
end
end
return true
end
--- Adds a header
-- @param arg { content, attr, colspan, rowspan, css }
-- content string or nil
-- The wikitext to be rendered
-- attr {...} or nil
-- The attributes of the cell in table form
-- colspan number or nil
-- The colspan of the cell
-- roswpan number or nil
-- The rowspan of the cell
-- css {...} or nil
-- The css of the cell in table form
-- @param options { hideIfEmpty, subheader }
-- hideIfEmpty { paramName, ... }
-- paramName string
-- The param_name that will be used to check if corresponding
-- content is nil
-- subheader boolean
-- Whether the header is a subheader or not
-- @return self
-- The current object
function InfoboxBuilder:addHeader(arg, options)
local isSubheader = false
if options then
if not self:shouldShow(options.hideIfEmpty) then
return self
end
if options.subheader then
isSubheader = true
end
end
local ibCell = mw.html.create('tr')
:tag('th')
:attr('colspan', 30)
:css(self.headerColors)
if not isSubheader then
ibCell:addClass('infobox-header')
else
ibCell:addClass('infobox-subheader')
end
if arg.attr then
ibCell:attr(arg.attr)
end
if arg.colspan then
ibCell:attr('colspan', arg.colspan)
end
if arg.rowspan then
ibCell:attr('rowspan', arg.rowspan)
end
if arg.css then
ibCell:css(arg.css)
end
if arg.tag == 'th' then
ibCell:wikitext(arg.content)
elseif arg.tag == 'argth' then
ibCell:wikitext(self:getContent(arg.content))
end
self:addSpacer()
self.infobox:node(ibCell)
self:addSpacer()
return self
end
--- Adds an image, or switchable images
-- @param cols { { tag, content, title }, ... }
-- tag "artd" or "td"
-- Whether or not an it is based off a parameter
-- content string
-- The content or the parameter name
-- title string or nil
-- The title, if using switchable images
-- @param options { hideIfEmpty }
-- hideIfEmpty { paramName, ... }
-- paramName string
-- The param_name that will be used to check if corresponding
-- content is nil
-- @return self
-- The current object
function InfoboxBuilder:addImage(cols, options)
if options then
if not self:shouldShow(options.hideIfEmpty) then
return self
end
end
local ibCell = mw.html.create('tr')
:tag('td')
:addClass('infobox-image')
:attr('colspan', 30)
local content = nil
local actualArgs = {}
for _, v in ipairs(cols) do
local c = v.content
if v.tag == 'argtd' then
c = self:getContent(c)
end
if c ~= nil then
table.insert(actualArgs, { tabName = v.tabName, content = c })
end
end
if #actualArgs == 0 then
ibCell:addClass('plainlinks')
content = string.format(
"[%s?action=edit ? (edit)]",
tostring(mw.uri.fullUrl(mw.title.getCurrentTitle().text))
)
elseif #actualArgs < 2 then
content = actualArgs[1].content
else
local t = {}
for _, v in ipairs(actualArgs) do
table.insert(t, v.tabName .. '=' .. v.content)
end
content = mw.getCurrentFrame()
:callParserFunction({
name = '#tag',
args = { 'tabber', table.concat(t, '|-|') }
})
end
ibCell:wikitext(content or '?')
self.infobox:node(ibCell)
return self
end
--- Adds a row, with columns up to 30 columns spanned
-- @param cols { { tag, content, attr, colspan, rowspan, css, class, cssFunc, classFunc }, ... }
-- tag "th", "td", "argth", "argtd"
-- A string containing one of the above, "th" or "td" uses
-- content as the wikitext, "argth" or "argtd" uses content as
-- the parameter name to produce the suitable content
-- content string
-- Content to be used as wikitext or a parameter name
-- attr {...} or nil
-- The attributes of the cell in table form
-- colspan number or nil
-- The colspan of the cell
-- rowspan number or nil
-- The rowspan of the cell
-- css {...} or nil
-- The css of the cell in table form
-- class {...} or nil
-- The classes of the cell in table form or the class of the
-- cell in string form
-- cssFunc { func , ... } or nil
-- func function
-- A function that returns css in table form
-- classFunc func or nil
-- func function
-- A function that returns css classes as a table or returns
-- a css class as a table
-- @param options { hideIfEmpty }
-- hideIfEmpty { paramName, ... }
-- paramName string
-- The paramName that will be used to check if corresponding
-- content is nil
-- defaultCss {...} or nil
-- The css of all cells in table form
-- @return self
-- The current object
function InfoboxBuilder:addRow(cols, options)
local defaultCss = nil
if options then
if not self:shouldShow(options.hideIfEmpty) then
return self
end
if options.defaultCss then
defaultCss = options.defaultCss
end
end
local ibRow = self.infobox:tag('tr')
local colspans = {}
if #cols == 2 then
colspans = { 12, 18 }
end
for i, v in ipairs(cols) do
local ibCell = ibRow:tag(tagmap[v.tag] or 'td')
:attr('colspan', colspans[i] or (30 / #cols))
if v.attr then
ibCell:attr(v.attr)
end
if v.colspan then
ibCell:attr('colspan', v.colspan)
end
if v.rowspan then
ibCell:attr('rowspan', v.rowspan)
end
if defaultCss then
ibCell:css(defaultCss)
end
if v.css then
ibCell:css(v.css)
end
if v.class then
if type(v.class) == 'table' then
for _, c in ipairs(v.class) do
ibCell:addClass(c)
end
else
ibCell:addClass(c)
end
end
if v.tag == 'th' or v.tag == 'td' then
ibCell:wikitext(v.content)
elseif v.tag == 'argth' or v.tag == 'argtd' then
local content = self:getContent(v.content)
if content ~= nil then
if v.cssFunc and #v.cssFunc > 0 then
for _, func in ipairs(v.cssFunc) do
local cellCss = func(self.procArgs[v.content])
if cellCss then
ibCell:css(cellCss)
end
end
end
if v.classFunc then
local cellClasses = v.classFunc(self.procArgs[v.content])
if cellClasses then
if type(cellClasses) == 'table' then
for _, c in ipairs(cellClasses) do
ibCell:addClass(c)
end
else
ibCell:addClass(cellClasses)
end
end
end
ibCell:wikitext(content)
else
ibCell:addClass('plainlinks')
:wikitext(
string.format(
"[%s?action=edit ? (edit)]",
tostring(mw.uri.fullUrl(mw.title.getCurrentTitle().text))
)
)
end
end
end
return self
end
--- Creates the 30-col layout
function InfoboxBuilder:addSpacer()
local spacer = self.infobox:tag('tr')
for i=1,30,1 do
spacer:tag('td')
:attr('colspan', 1)
:addClass('spacer-cell')
end
end
--- Adds links to the bottom of the infobox
function InfoboxBuilder:addLinks()
if not self.finished then
self.finished = true
self:addRow({{
tag = 'td',
content = Navbar({ self.name, plain = 1, noedit = 1 }),
colspan = 30
}})
end
end
--- Generates the infobox
-- @return string
-- The html of the infobox
function InfoboxBuilder:tostring()
if not self.finished then
self:addLinks()
end
self.finished = true
return
mw.getCurrentFrame():extensionTag{
name = 'templatestyles',
args = { src = 'Template:Infobox/styles.css' }
} ..
tostring(self.infobox)
end
return InfoboxBuilder