This module is called Module:ItemRecipes on the Rend wiki, but is commented here extensively. It's an example of printing a table based on a Cargo query. The table it queries can be found here.
local lang = mw.getLanguage('en') -- this is a constant available to every function, and will be used to lowercase a variable below.
local p = {}
function p.main(frame) -- this is the function that's called from the page itself
local args = require('Module:ProcessArgs').merge(true)
-- everything above here lets us call this module either from a page via #invoke, or from another module, and have the arguments fed to the template be available in a table called args
-- you should copy Module:ProcessArgs to your wiki to use it, if it's not already there
local item = args[1] or mw.title.getCurrentTitle().text
local result = p.doQuery(item) -- first thing is to do the cargo query, which is done in its own function; see comments on that function for more info
if not result then -- if there was no result then return
return '<span style="color:#ccc">\'\'No crafting recipes found.\'\'</span>'
end
-- now we format all of the data that we got from our result to prepare it for output
local formatted = p.formatResult(result)
-- now we return a table that prints all the formatted data
return p.makeTable(formatted)
end
-----------------------------------
-- cargo
-----------------------------------
-- the code to do the query is broken up into a bunch of functions
-- just so that it's easier to see what each piece does
-- this is the outer function, which actually does the query
-- and returns the result to the main function, or returns nil if there is no result
-- the query itself will return {} (an empty table) if there is no result to the query
function p.doQuery(item)
-- [[the query takes 3 arguments:
1) a list of tables (it expects a comma-separated list as a string)
2) a list of fields to return (again, a comma separated list)
3) a table with a bunch of optional values. in this case we give a "where" condition and an "orderBy."
Mostly these parameters are the same as the ones available in a normal mediawiki Cargo query,
but there are some differences in what they're called so that they are just 1 single word in Lua
and can be written more clearly as the keys in a table]]
local result = mw.ext.cargo.query('Recipes',
p.cargoFields(),
-- the fields that we want in this example is actually kind of long and annoying to construct,
-- so it's done in its own function.
-- all you need to know is that a string is returned that contains a list of fields
{
where = p.cargoWhere(item), -- again, constructing the 'where' is kind of annoying so it's done in its own function. all you need to know is that it returns a string.
orderBy = 'tool'
}
)
if #result == 0 then
-- this just checks if the table is non-empty
-- the following code:
-- if result == {}
-- will NOT work because Lua == when used on two tables only returns true if you are comparing
-- one table to literally itself, and NOT another table that has the same structure & values as it
-- however consider the following code:
-- a = {}
-- b = a
-- in this case, a does equal b
return nil
else
return result
end
end
-- don't worry too much about the specifics of this function,
-- just know it returns a string with a list of fields we want to query
-- if we wanted to alias a field name,
-- we could do for example "result=result_alias" instead of just "result"
-- and then that would be returned to us as row.result_alias instead of row.result
-- when we do our for k, row in ipairs.... loop later on
function p.cargoFields()
-- we'll first make a table with all of the fields in it
local fields = {
'result','resultAmount','tool'
}
-- there are a bunch of items & amounts and i don't want to type them all out so do a loop for the rest
for i = 1,12 do
fields[#fields+1] = 'item' .. i
fields[#fields+1] = 'amount' .. i
end
return table.concat(fields,',') -- then concat the table into a comma-separated string and return it to the main function
end
-- also don't worry too much about the specifics of this function, just know it returns a where condition as a string
function p.cargoWhere(item)
local where = {}
for i = 1,12 do
where[#where+1] = string.format('item%s="%s"', i, item)
end
return table.concat(where,' OR ')
end
--------------------------------------------------
-- process data for output
--------------------------------------------------
-- in the end we want to print a table with three columns.
-- the function that does the actual printing should only need to print data to the page,
-- and not need to do any kind of processing on it anymore,
-- so we are doing the processing / formatting here,
-- saving it into a table called "formatted",
-- and then returning it to the main function where it will then be printed.
function p.formatResult(result)
local formatted = {}
-- this loop structure is pretty much always how you will process cargo data.
-- you will loop over the ipairs iterator of the results table and apply a bunch of processing to the row, and save it.
-- once it's been processed you will then print it.
for k, row in ipairs(result) do
formatted[k] = {
-- each of these pieces of formatting is done in its own function for ease of reading.
-- it's not too important to read them individually, just know how string.format works
p.formatLinkAndImage(row.result, row.resultAmount),
p.makeIngredientsTable(row),
p.formatTool(row.tool)
}
end
return formatted
end
function p.formatLinkAndImage(result, amount)
return string.format("[[File:%s.png|40px|link=%s]] [[%s]] (%s)",
result or '',
result or '',
result or '',
amount or ''
)
end
function p.makeIngredientsTable(row)
local tbl = mw.html.create('table'):css({
margin='-1px',
width = 'calc(100% + 2px)',
['border-collapse'] = 'collapse'
})
for i = 1, 12 do
if row['item' .. i] ~= '' then
tbl:tag('tr'):tag('td'):wikitext(p.formatLinkAndImage(row['item' .. i], row['amount' .. i]))
end
end
return tostring(tbl)
end
function p.formatTool(tool)
if lang:lc(tool) == 'by hand' then
return '[[By Hand]]'
else
return string.format('[[File:%s.png|40px|link=%s]] %s',
tool or '',
tool or '',
tool or ''
)
end
end
----------------------------------------------------
-- make table for output
----------------------------------------------------
-- since we did all our processing above, literally all that's left to do is to make the table for output.
-- this is done using the mw.html library.
function p.makeTable(formatted)
-- this table of styles corresponds to each of the columns
local styles = {
'', -- first column has no style
{ padding = '0!important', }, -- second column has no padding
'' -- third column has no style
}
local tbl = mw.html.create('table'):addClass('wikitable') -- create a wikitable html class
tbl:tag('tr') -- and make its header row
:tag('th'):wikitext('Result'):done()
:tag('th'):wikitext('Ingredients'):done()
:tag('th'):wikitext('Crafting Station'):done()
for _, row in ipairs(formatted) do -- now iterate over the formatted data
tr = tbl:tag('tr') -- create a row
for k, v in ipairs(row) do
-- create each of the columns within the row,
-- with the style we defined above and the wikitext as the row value we made in the earlier function
tr:tag('td'):css(styles[k]):wikitext(v)
end
end
return tbl -- done!
end
return p