Module:Recipe: Difference between revisions
mNo edit summary |
No edit summary |
||
| (18 intermediate revisions by 2 users not shown) | |||
| Line 6: | Line 6: | ||
local param = { | local param = { | ||
sCharArg = 'character', | sCharArg = 'character', | ||
sKitchArg = 'kitchenware', | |||
sTypeArg = 'type', | sTypeArg = 'type', | ||
sSortArg = 'sort', | sSortArg = 'sort', | ||
| Line 30: | Line 31: | ||
sOut = sOut .. 's' | sOut = sOut .. 's' | ||
end | end | ||
return sOut | return sOut | ||
end | end | ||
local function | local function normalizeText(s) | ||
return mw.ustring.lower(mw.text.trim(tostring(s or ''))) | return mw.ustring.lower(mw.text.trim(tostring(s or ''))) | ||
end | end | ||
| Line 41: | Line 43: | ||
end | end | ||
local function | local function addUseCategory(category, name, quality, sort) | ||
if not name or tostring(name) == '' then | |||
return | |||
end | |||
if quality and tostring(quality) ~= '' then | |||
if sort and tostring(sort) ~= '' then | |||
category:wikitext('[[Category:Uses ', quality, '-Quality ', name, '|', sort, ']]') | |||
else | |||
category:wikitext('[[Category:Uses ', quality, '-Quality ', name, ']]') | |||
end | |||
return | |||
end | |||
if sort and tostring(sort) ~= '' then | |||
category:wikitext('[[Category:Uses ', name, '|', sort, ']]') | |||
else | |||
category:wikitext('[[Category:Uses ', name, ']]') | |||
end | |||
end | |||
return | local function getCurrentPageName(args) | ||
return args[param.sPage] or args.page or mw.title.getCurrentTitle().text | |||
end | end | ||
local function | local function getQualityClass(quality) | ||
return | if not quality or tostring(quality) == '' then | ||
return nil | |||
end | |||
return 'card-quality-' .. normalizeText(quality) | |||
end | end | ||
| Line 59: | Line 81: | ||
-------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | ||
local function | local function addRecipeCard(category, sAmt, sName, quality) | ||
local cardArgs = { | local cardArgs = { | ||
name = sName, | name = sName, | ||
text = sAmt, | text = sAmt, | ||
show_caption = '1 | show_caption = '1' | ||
} | } | ||
| Line 73: | Line 94: | ||
local cardNode = Card._main(cardArgs) | local cardNode = Card._main(cardArgs) | ||
addUseCategory( | |||
category, | |||
sName, | sName, | ||
quality, | |||
padLeft(tostring(sAmt or ''):gsub('%D', ''), 10) | padLeft(tostring(sAmt or ''):gsub('%D', ''), 10) | ||
) | ) | ||
| Line 89: | Line 109: | ||
text = sText or '', | text = sText or '', | ||
show_caption = '1', | show_caption = '1', | ||
mini = '1' | mini = '1' | ||
} | } | ||
| Line 99: | Line 118: | ||
local cardNode = Card._main(cardArgs) | local cardNode = Card._main(cardArgs) | ||
addUseCategory(category, sName) | |||
return cardNode | return cardNode | ||
end | |||
local function addYieldCard(pageTitle, sYield) | |||
return Card._main({ | |||
name = pageTitle, | |||
text = sYield, | |||
show_caption = '1' | |||
}) | |||
end | end | ||
| Line 111: | Line 136: | ||
local function renderHeader(args, output, category) | local function renderHeader(args, output, category) | ||
local header = output:tag('div'):addClass(' | local header = output:tag('div'):addClass('recipe-header') | ||
local sType = args[param.sTypeArg] | local sType = args[param.sTypeArg] | ||
header:tag('span'):addClass(' | header:tag('span'):addClass('recipe-header-main') | ||
:tag('span'):addClass(' | :tag('span'):addClass('recipe-header-text'):wikitext('[[' .. sType .. ']]'):done() | ||
category:wikitext('[[Category:' .. sType .. ']]') | category:wikitext('[[Category:' .. sType .. ']]') | ||
| Line 202: | Line 224: | ||
end | end | ||
header:tag('span'):addClass(' | header:tag('span'):addClass('recipe-header-sub') | ||
:tag('span | :tag('span'):wikitext(' for '):done() | ||
:tag('span'):addClass('recipe-header-text'):wikitext(sTime):done() | |||
:tag('span'):addClass(' | |||
end | end | ||
| Line 215: | Line 236: | ||
local sCharName = args[param.sCharArg] | local sCharName = args[param.sCharArg] | ||
header:tag('span'):addClass(' | header:tag('span'):addClass('recipe-header-sub') | ||
:tag('span'):addClass(' | :tag('span'):wikitext('[[File:' .. sCharName .. ' Icon.png|24x24px|link=' .. sCharName .. ']]'):done() | ||
:tag('span'):addClass(' | :tag('span'):addClass('recipe-header-text'):wikitext('[[' .. sCharName .. ']]'):done() | ||
:tag('span'):addClass(' | end | ||
local function renderKitchenwareHeader(args, header) | |||
if type(args[param.sKitchArg]) ~= 'string' then | |||
return | |||
end | |||
local sKitchName = args[param.sKitchArg] | |||
header:tag('span'):addClass('recipe-header-sub') | |||
:tag('span'):wikitext('[[File:' .. sKitchName .. ' Icon.png|24x24px|link=' .. sKitchName .. ']]'):done() | |||
:tag('span'):addClass('recipe-header-text'):wikitext('[[' .. sKitchName .. ']]'):done() | |||
end | end | ||
| Line 224: | Line 256: | ||
-- Standard recipe rendering | -- Standard recipe rendering | ||
-------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | ||
local function isRestrictedStandardParam(sKey) | |||
for _, keyParam in pairs(param) do | |||
if keyParam == sKey then | |||
return true | |||
end | |||
end | |||
return false | |||
end | |||
local function renderStandardYield(args, body) | local function renderStandardYield(args, body) | ||
| Line 230: | Line 272: | ||
end | end | ||
local sYield = args[param.sYieldArg] or | local sYield = args[param.sYieldArg] or nil | ||
local pageTitle = args | local pageTitle = getCurrentPageName(args) | ||
local yieldCard = | local yieldCard = addYieldCard(pageTitle, sYield) | ||
body | body | ||
:tag('div'):addClass(' | :tag('div'):addClass('recipe-body-icon') | ||
:wikitext('➜'):done() | :wikitext('➜'):done() | ||
:tag('div'):addClass(' | :tag('div'):addClass('recipe-body-yield') | ||
:node(yieldCard) | :node(yieldCard) | ||
end | end | ||
| Line 260: | Line 292: | ||
renderCharacter(args, header) | renderCharacter(args, header) | ||
local body = output:tag('div'):addClass(' | local body = output:tag('div'):addClass('recipe-body') | ||
local sSortDelim = param.sSortDelim | local sSortDelim = param.sSortDelim | ||
| Line 270: | Line 302: | ||
for sKey in string.gmatch(args[param.sSortArg] or '', '([^' .. sSortDelim .. ']+)') do | for sKey in string.gmatch(args[param.sSortArg] or '', '([^' .. sSortDelim .. ']+)') do | ||
if type(args[sKey]) ~= 'nil' then | if type(args[sKey]) ~= 'nil' then | ||
body:node( | body:node(addRecipeCard(category, args[sKey], sKey)) | ||
tArgsProcessed[sKey] = true | tArgsProcessed[sKey] = true | ||
end | end | ||
| Line 276: | Line 308: | ||
for sKey, sVal in pairs(args) do | for sKey, sVal in pairs(args) do | ||
if tArgsProcessed[sKey] ~= true and not isRestrictedStandardParam(sKey) then | |||
body:node(addRecipeCard(category, sVal, sKey)) | |||
if tArgsProcessed[sKey] ~= true and not | |||
body:node( | |||
end | end | ||
end | end | ||
| Line 295: | Line 319: | ||
-------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | ||
-- Cooking | -- Cooking parsing | ||
-------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | ||
local function getMaxCookingItemIndex(args) | |||
local maxIndex = 0 | |||
for key, _ in pairs(args) do | |||
local index = tostring(key):match('^item_(%d+)') | |||
if index then | |||
index = tonumber(index) | |||
if index and index > maxIndex then | |||
maxIndex = index | |||
end | |||
end | |||
end | |||
return maxIndex | |||
end | |||
local function getCookingIngredient(args, index) | local function getCookingIngredient(args, index) | ||
| Line 303: | Line 344: | ||
local ingredient = { | local ingredient = { | ||
index = index, | index = index, | ||
amount = args[prefix .. '_amount'] or | amount = args[prefix .. '_amount'] or nil, | ||
quality = args[prefix .. '_quality'], | quality = args[prefix .. '_quality'], | ||
item = args[prefix], | item = args[prefix], | ||
| Line 310: | Line 351: | ||
} | } | ||
if argExists(args, prefix .. '_type') then | if argExists(args, prefix .. '_type') then | ||
table.insert(ingredient.types, args[prefix .. '_type']) | table.insert(ingredient.types, args[prefix .. '_type']) | ||
end | end | ||
local typeIndex = 1 | local typeIndex = 1 | ||
| Line 324: | Line 362: | ||
end | end | ||
local optionIndex = 1 | local optionIndex = 1 | ||
| Line 334: | Line 370: | ||
local hasIngredient = | local hasIngredient = | ||
argExists(args, prefix) | |||
or #ingredient.types > 0 | or #ingredient.types > 0 | ||
or #ingredient.options > 0 | or #ingredient.options > 0 | ||
| Line 345: | Line 381: | ||
end | end | ||
-------------------------------------------------------------------------------- | |||
-- Cooking type split-card helpers | |||
-------------------------------------------------------------------------------- | |||
local function makeTypeIcon(typeName) | |||
return '[[File:' .. typeName .. ' Icon.png|74x74px|link=' .. typeName .. ']]' | |||
end | |||
local | local function joinTypeCaption(types) | ||
local out = {} | |||
for _, typeName in ipairs(types) do | |||
table.insert( | table.insert(out, '[[' .. typeName .. ']]') | ||
end | end | ||
return | return table.concat(out, ' / ') | ||
end | end | ||
------------------------- | local function renderCookingSplitTypeCard(category, body, ingredient) | ||
local qualityClass = getQualityClass(ingredient.quality or 'Gray') | |||
local container = body:tag('span') | |||
:addClass('card-container') | |||
:addClass('recipe-type-split-card') | |||
local wrapper = container:tag('span') | |||
:addClass('card-wrapper') | |||
local cardBody = wrapper:tag('span') | |||
:addClass('card-body') | |||
local imageContainer = cardBody:tag('span') | |||
:addClass('card-image-container') | |||
:addClass('recipe-type-split-image') | |||
imageContainer:tag('span') | |||
:addClass('recipe-type-split-half') | |||
:addClass('recipe-type-split-half-a') | |||
:wikitext(makeTypeIcon(ingredient.types[1])) | |||
:done() | |||
imageContainer:tag('span') | |||
:addClass('recipe-type-split-half') | |||
:addClass('recipe-type-split-half-b') | |||
:wikitext(makeTypeIcon(ingredient.types[2])) | |||
:done() | |||
if qualityClass then | |||
imageContainer:addClass(qualityClass) | |||
end | |||
if tostring(ingredient.amount or '') ~= '' then | |||
container:tag('span') | |||
:addClass('card-label') | |||
:wikitext(tostring(ingredient.amount or '1')) | |||
:done() | |||
end | |||
container:tag('span') | |||
:addClass('card-caption') | |||
:wikitext(joinTypeCaption(ingredient.types)) | |||
:done() | |||
for _, typeName in ipairs(ingredient.types) do | for _, typeName in ipairs(ingredient.types) do | ||
category | addUseCategory(category, typeName) | ||
end | end | ||
end | |||
-------------------------------------------------------------------------------- | |||
-- Cooking display | |||
-------------------------------------------------------------------------------- | |||
local function renderCookingSpecificItem(category, body, ingredient) | |||
body:node(addRecipeCard( | |||
category, | |||
ingredient.amount, | |||
ingredient.item, | |||
ingredient.quality | |||
)) | |||
end | |||
local | local function renderCookingTypeFallback(category, body, ingredient) | ||
:addClass(' | local wrapper = body:tag('div') | ||
:addClass('recipe-type- | :addClass('recipe-body-cooking-ingredient') | ||
:addClass('recipe-body-cooking-type-cards') | |||
for _, typeName in ipairs(ingredient.types) do | |||
wrapper:node(addMiniCard( | |||
category, | |||
typeName, | |||
ingredient.amount, | |||
ingredient.quality | |||
)) | |||
end | end | ||
end | |||
local function renderCookingTypeCards(category, body, ingredient) | |||
if #ingredient.types == 2 then | |||
renderCookingSplitTypeCard(category, body, ingredient) | |||
else | |||
renderCookingTypeFallback(category, body, ingredient) | |||
end | end | ||
end | end | ||
| Line 406: | Line 487: | ||
local function renderCookingOptionCards(category, body, ingredient) | local function renderCookingOptionCards(category, body, ingredient) | ||
local wrapper = body:tag('div') | local wrapper = body:tag('div') | ||
:addClass(' | :addClass('recipe-body-cooking-ingredient') | ||
:addClass(' | :addClass('recipe-body-cooking-option-cards') | ||
for _, itemName in ipairs(ingredient.options) do | for _, itemName in ipairs(ingredient.options) do | ||
wrapper:node( | wrapper:node(addMiniCard( | ||
category, | |||
itemName, | |||
ingredient.amount, | |||
ingredient.quality | |||
)) | |||
end | end | ||
end | end | ||
local function renderCookingIngredient(category, body, ingredient) | local function renderCookingIngredient(category, body, ingredient) | ||
if ingredient.item then | if ingredient.item then | ||
renderCookingSpecificItem(category, body, ingredient) | |||
return | return | ||
end | end | ||
if #ingredient.options > 0 then | if #ingredient.options > 0 then | ||
renderCookingOptionCards(category, body, ingredient) | renderCookingOptionCards(category, body, ingredient) | ||
| Line 430: | Line 511: | ||
end | end | ||
if #ingredient.types > 0 then | if #ingredient.types > 0 then | ||
renderCookingTypeCards(category, body, ingredient) | |||
return | return | ||
end | end | ||
end | end | ||
| Line 459: | Line 522: | ||
end | end | ||
local sYield = args[param.sYieldArg] or | local sYield = args[param.sYieldArg] or nil | ||
local pageTitle = | local pageTitle = getCurrentPageName(args) | ||
local yieldCard = | local yieldCard = addYieldCard(pageTitle, sYield) | ||
body | |||
:tag('div'):addClass('recipe-body-icon') | |||
:wikitext('➜'):done() | |||
:wikitext('➜') | :tag('div'):addClass('recipe-body-yield') | ||
:node(yieldCard) | |||
end | end | ||
| Line 506: | Line 539: | ||
renderTime(args, header) | renderTime(args, header) | ||
renderCharacter(args, header) | renderCharacter(args, header) | ||
renderKitchenwareHeader(args, header) | |||
local body = output:tag('div') | local body = output:tag('div') | ||
:addClass(' | :addClass('recipe-body') | ||
:addClass(' | :addClass('recipe-body-cooking') | ||
local foundIngredient = false | local foundIngredient = false | ||
local maxIndex = getMaxCookingItemIndex(args) | |||
for index = 1, maxIndex do | |||
local ingredient = getCookingIngredient(args, | local ingredient = getCookingIngredient(args, index) | ||
if | if ingredient then | ||
foundIngredient = true | |||
renderCookingIngredient(category, body, ingredient) | |||
end | end | ||
end | end | ||
| Line 553: | Line 583: | ||
function p._main(args, frame) | function p._main(args, frame) | ||
local output = mw.html.create('div') | local output = mw.html.create('div') | ||
:addClass(' | :addClass('recipe-container') | ||
local category = mw.html.create() | local category = mw.html.create() | ||
| Line 564: | Line 594: | ||
local sType = args[param.sTypeArg] | local sType = args[param.sTypeArg] | ||
if | if normalizeText(sType) == 'cooking' then | ||
renderCookingRecipe(args, frame, output, category) | renderCookingRecipe(args, frame, output, category) | ||
else | else | ||