Module:Recipe table
Appearance
Template:Documentation header
This module creates the table for {{crafting}}, {{brewing}}, {{smelting}} and {{looming}}. It can only be invoked within other modules.
Usage
The entry point is the table function. The first argument should be whatever arguments you want to pass through, the second argument should be a table of settings.
| Setting | Use |
|---|---|
| type | What type of recipe, e.g.: 'Crafting'
|
| ingredientArgs | A table of the args which contain the ingredients, e.g.: { 'Input' }
|
| outputArgs | A table of the args which contain the outputs, e.g.: { 'Output' }
|
| uiFunc | The function to call from Module:UI, e.g.: 'craftingTable'
|
The module returns the wikitext table as the first parameter, and a table of unique ingredients as the second output.
Dependencies
es:Módulo:Recipe table
fr:Module:Tableau de recette
ja:モジュール:Recipe table
pt:Módulo:Recipe table
ru:Модуль:Таблица рецептов
uk:Модуль:Recipe table
local m = {}
local i18n = {
headingDescription = 'Description',
headingIngredients = 'Ingredients',
headingName = 'Name',
headingRecipe = '[[$1]] recipe',
moduleSlot = [[Module:Inventory slot]],
moduleUi = [[Module:UI]],
separator = ' +',
setSeparator = ' or',
tableDescription = '$1 recipes',
}
local slot = require(i18n.moduleSlot)
local prefixes = slot.i18n.prefixes
local aliases = mw.loadData('Module:Inventory slot/Aliases') -- Load aliases
-- Function to remove Minecraft formatting codes
local function removeFormattingCodes(text)
return text:gsub("&[0-9a-fk-or]", "")
end
-- Parses recipe arguments into structured frames
local function parseRecipeArgs(args, ingredientArgVals, outputArgs)
local recipeArgs = {}
for _, arg in pairs(ingredientArgVals) do
recipeArgs[arg] = args[arg]
end
for _, arg in pairs(outputArgs) do
recipeArgs[arg] = args[arg]
end
local parsedFrameText = {}
local parsedRecipeArgs = {}
for arg, frameText in pairs(recipeArgs) do
if frameText then
-- Clean formatting codes from the frame text
frameText = removeFormattingCodes(frameText)
local randomise
for _, oArg in pairs(outputArgs) do
if arg == oArg then
randomise = 'never'
break
end
end
local frames = not randomise and parsedFrameText[frameText]
if not frames then
frames = slot.parseFrameText(frameText, randomise, true)
parsedFrameText[frameText] = frames
end
parsedRecipeArgs[arg] = frames
end
end
return parsedRecipeArgs
end
-- Creates the table header
m.makeHeader = function(recipeType, class, showName, showDescription, multirow)
class = class or ''
local nameCell = ''
if showName then
nameCell = i18n.headingName .. '!!'
end
local descriptionCell = ''
if showDescription then
descriptionCell = '!!class="unsortable"|' .. i18n.headingDescription
end
local recipeAttribs = ''
if multirow then
class = 'sortable ' .. class
recipeAttribs = 'class="unsortable"|'
end
local header = table.concat({
' {| class="wikitable crafting ' .. class .. '" data-description="' .. i18n.tableDescription:gsub('%$1', recipeType) .. '"',
'!' .. nameCell ..
i18n.headingIngredients .. '!!' ..
recipeAttribs .. i18n.headingRecipe:gsub('%$1', recipeType) ..
descriptionCell
}, '\n')
return header
end
-- Creates links for the name/ingredients columns out of item sets
function m.makeItemLinks(itemSets, removePrefixes)
local links = {}
for i, itemSet in ipairs(itemSets) do
local linkSet = {}
for i2, item in ipairs(itemSet) do
local name = item.name
local mod = item.mod
-- Clean formatting codes from the item name
name = removeFormattingCodes(name)
-- Resolve alias if available
local aliasData = aliases[name]
if aliasData then
-- Use alias-provided link and title (clean formatting codes)
local link = aliasData.link or name
local displayName = removeFormattingCodes(aliasData.title or name)
linkSet[i2] = string.format("[[%s|%s]]", link, displayName)
else
-- Fallback to default prefixed link
if removePrefixes then
name = name
:gsub('^' .. prefixes.any .. ' ', '')
:gsub('^' .. prefixes.matching .. ' ', '')
:gsub('^%l', string.upper)
end
linkSet[i2] = m.prefixedLink(name, mod)
end
end
links[i] = table.concat(linkSet, i18n.setSeparator .. '<br>')
end
return table.concat(links, i18n.separator .. '<br>')
end
-- Create the contents for the ingredients cell
function m.makeIngredientsCell(ingredients, itemSets)
return ingredients or m.makeItemLinks(itemSets)
end
-- Main entry point, creates the table with the relevant DPL vars
function m.makeItemSets(argVals, parsedArgs)
local usedItems = {}
local function addItem(items, arg, frame, alias)
if alias then
frame = alias.frame
end
-- Clean formatting codes from the frame name
frame.name = removeFormattingCodes(frame.name)
local uniqName = (frame.mod or '') .. ':' .. frame.name
if not usedItems[uniqName] then
usedItems[uniqName] = true
items[#items + 1] = frame
end
return alias and alias.length or 1
end
local itemSets = {}
local i = 1
for _, arg in ipairs(argVals) do
local frames = parsedArgs[arg]
if frames then
local items = {}
local frameNum = 1
while frameNum <= #frames do
local frame = frames[frameNum]
if frame[1] then
local subframeNum = 1
while subframeNum <= #frame do
local subframe = frame[subframeNum]
if subframe.name ~= '' then
local alias = frame.aliasReference and frame.aliasReference[subframeNum]
subframeNum = subframeNum + addItem(items, arg, subframe, alias)
else
subframeNum = subframeNum + 1
end
end
frameNum = frameNum + 1
elseif frame.name ~= '' then
local alias = frames.aliasReference and frames.aliasReference[frameNum]
frameNum = frameNum + addItem(items, arg, frame, alias)
else
frameNum = frameNum + 1
end
end
if #items > 0 then
itemSets[i] = items
i = i + 1
end
end
end
return itemSets
end
function m.table(args, settings)
local f = mw.getCurrentFrame()
local multirow = f:callParserFunction('#dplvar', 'recipetable-multirow')
if multirow == '' then
multirow = nil
end
local showHead = args.head
local showFoot = args.foot
if multirow then
showHead = nil
elseif showHead and not showFoot then
multirow = true
f:callParserFunction('#dplvar:set', 'recipetable-multirow', '1')
else
showHead = true
showFoot = true
end
local showName = args.showname
local showDescription = args.showdescription
if multirow then
if showHead then
showName = args.showname or '1'
f:callParserFunction('#dplvar:set', 'recipetable-name', showName, 'recipetable-description', showDescription)
else
showName = f:callParserFunction('#dplvar', 'recipetable-name')
showDescription = f:callParserFunction('#dplvar', 'recipetable-description')
end
end
if showName ~= '1' then
showName = nil
end
if showDescription == '' then
showDescription = nil
end
local out = {}
if showHead then
out[1] = m.makeHeader(settings.type, args.class, showName, showDescription, multirow)
end
local ingredientArgVals = settings.ingredientArgs
local outputArgs = settings.outputArgs
local parsedRecipeArgs = args
if not args.parsed then
parsedRecipeArgs = parseRecipeArgs(args, ingredientArgVals, outputArgs)
end
local cells = {}
local outputItemSets = m.makeItemSets(outputArgs, parsedRecipeArgs)
if showName then
cells[1] = '!' .. m.makeNameCell(args.name, outputItemSets)
end
local ingredientsItemSets = m.makeItemSets(ingredientArgVals, parsedRecipeArgs)
cells[#cells + 1] = '|' .. m.makeIngredientsCell(args.ingredients, ingredientsItemSets)
cells[#cells + 1] = '|style="padding:1px;text-align:center"|' .. require(i18n.moduleUi)[settings.uiFunc](args)
if showDescription then
cells[#cells + 1] = '|' .. (args.description or '')
end
out[#out + 1] = table.concat(cells, '\n')
out[#out + 1] = showFoot and '|}' or ''
if showFoot then
f:callParserFunction('#dplvar:set',
'recipetable-multirow', '',
'recipetable-name', '',
'recipetable-description', ''
)
end
return table.concat(out, '\n|-\n'), ingredientsItemSets, outputItemSets
end
return m