Editing Module:Recipe

Warning: You are not logged in. Your IP address will be publicly visible if you make any edits. If you log in or create an account, your edits will be attributed to your username, along with other benefits.
The edit can be undone. Please check the comparison below to verify that this is what you want to do, and then publish the changes below to finish undoing the edit.
Latest revision Your text
Line 6: Line 6:
local param = {
local param = {
   sCharArg = 'character',
   sCharArg = 'character',
  sKitchArg = 'kitchenware',
   sTypeArg = 'type',
   sTypeArg = 'type',
   sSortArg = 'sort',
   sSortArg = 'sort',
Line 31: Line 30:
     sOut = sOut .. 's'
     sOut = sOut .. 's'
   end
   end
   return sOut
   return sOut
end
end


local function normalizeText(s)
local function normalizeType(s)
   return mw.ustring.lower(mw.text.trim(tostring(s or '')))
   return mw.ustring.lower(mw.text.trim(tostring(s or '')))
end
end
Line 43: Line 41:
end
end


local function addUseCategory(category, name, quality, sort)
local function joinDisplay(list, separator)
if not name or tostring(name) == '' then
  local out = {}
return
end


if quality and tostring(quality) ~= '' then
  for _, value in ipairs(list) do
if sort and tostring(sort) ~= '' then
    table.insert(out, '[[' .. value .. ']]')
category:wikitext('[[Category:Uses ', quality, '-Quality ', name, '|', sort, ']]')
  end
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


local function getCurrentPageName(args)
   return table.concat(out, separator or ' / ')
   return args[param.sPage] or args.page or mw.title.getCurrentTitle().text
end
end


local function getQualityClass(quality)
local function joinFileNameParts(list)
   if not quality or tostring(quality) == '' then
   return table.concat(list, ' & ')
    return nil
  end
 
  return 'card-quality-' .. normalizeText(quality)
end
end


Line 81: Line 59:
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------


local function addRecipeCard(category, sAmt, sName, quality)
local function addRecipe(category, sAmt, sName, quality)
   local cardArgs = {
   local cardArgs = {
     name = sName,
     name = sName,
     text = sAmt,
     text = sAmt,
     show_caption = '1'
     show_caption = '1',
    mobile = 'bulleted'
   }
   }


Line 94: Line 73:
   local cardNode = Card._main(cardArgs)
   local cardNode = Card._main(cardArgs)


   addUseCategory(
   category:wikitext(
     category,
     '[[Category:Uses ',
     sName,
     sName,
     quality,
     '|',
     padLeft(tostring(sAmt or ''):gsub('%D', ''), 10)
     padLeft(tostring(sAmt or ''):gsub('%D', ''), 10),
    ']]'
   )
   )


Line 109: Line 89:
     text = sText or '',
     text = sText or '',
     show_caption = '1',
     show_caption = '1',
    mobile = 'bulleted',
     mini = '1'
     mini = '1'
   }
   }
Line 118: Line 99:
   local cardNode = Card._main(cardArgs)
   local cardNode = Card._main(cardArgs)


   addUseCategory(category, sName)
   if category and sName then
    category:wikitext('[[Category:Uses ', sName, ']]')
  end


   return cardNode
   return cardNode
end
local function addYieldCard(pageTitle, sYield)
  return Card._main({
    name = pageTitle,
    text = sYield,
    show_caption = '1'
  })
end
end


Line 136: Line 111:


local function renderHeader(args, output, category)
local function renderHeader(args, output, category)
   local header = output:tag('div'):addClass('recipe-header')
   local header = output:tag('div'):addClass('recipe_header')
 
   local sType = args[param.sTypeArg]
   local sType = args[param.sTypeArg]


   header:tag('span'):addClass('recipe-header-main')
   header:tag('span'):addClass('recipe_header_main')
     :tag('span'):addClass('recipe-header-text'):wikitext('[[' .. sType .. ']]'):done()
     :tag('span'):addClass('mobileHide'):wikitext('<big>' .. sType .. '</big>'):done()
    :tag('span'):addClass('mobileHide'):wikitext('<big>' .. sType .. '</big>'):done()
    :tag('span'):addClass('recipe_header_text'):wikitext('[[' .. sType .. ']]'):done()


   category:wikitext('[[Category:' .. sType .. ']]')
   category:wikitext('[[Category:' .. sType .. ']]')
Line 224: Line 202:
   end
   end


   header:tag('span'):addClass('recipe-header-sub')
   header:tag('span'):addClass('recipe_header_sub')
     :tag('span'):wikitext(' for '):done()
     :tag('span'):addClass('mobileHide'):wikitext(' for '):done()
     :tag('span'):addClass('recipe-header-text'):wikitext(sTime):done()
    :tag('span'):addClass('hidden'):wikitext(' for '):done()
     :tag('span'):addClass('recipe_header_text'):wikitext(sTime):done()
end
end


Line 236: Line 215:
   local sCharName = args[param.sCharArg]
   local sCharName = args[param.sCharArg]


   header:tag('span'):addClass('recipe-header-sub')
   header:tag('span'):addClass('recipe_header_sub')
    :tag('span'):wikitext('[[File:' .. sCharName .. ' Icon.png|24x24px|link=' .. sCharName .. ']]'):done()
     :tag('span'):addClass('mobileHide'):wikitext(' with '):done()
     :tag('span'):addClass('recipe-header-text'):wikitext('[[' .. sCharName .. ']]'):done()
     :tag('span'):addClass('hidden'):wikitext('[[File:' .. sCharName .. ' Icon.png|24x24px|link=' .. sCharName .. ']]'):done()
end
     :tag('span'):addClass('recipe_header_text'):wikitext('[[' .. sCharName .. ']]'):done()
 
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 256: Line 224:
-- 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 272: Line 230:
   end
   end


   local sYield = args[param.sYieldArg] or nil
   local sYield = args[param.sYieldArg] or '1'
   local pageTitle = getCurrentPageName(args)
   local pageTitle = args.page or mw.title.getCurrentTitle().text


   local yieldCard = addYieldCard(pageTitle, sYield)
   local yieldCard = Card._main({
    name = pageTitle,
    text = sYield,
    show_caption = '1',
  })


   body
   body
     :tag('div'):addClass('recipe-body-icon')
     :tag('div'):addClass('recipe_body_icon')
       :wikitext('➜'):done()
       :wikitext('➜'):done()
     :tag('div'):addClass('recipe-body-yield')
     :tag('div'):addClass('recipe_body_yield')
       :node(yieldCard)
       :node(yieldCard)
  local itemText = require('Module:Item').main{
    [1] = pageTitle,
    [2] = '15',
    x = sYield
  }
end
end


Line 292: Line 260:
   renderCharacter(args, header)
   renderCharacter(args, header)


   local body = output:tag('div'):addClass('recipe-body')
   local body = output:tag('div'):addClass('recipe_body')


   local sSortDelim = param.sSortDelim
   local sSortDelim = param.sSortDelim
Line 302: Line 270:
   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(addRecipeCard(category, args[sKey], sKey))
       body:node(addRecipe(category, args[sKey], sKey))
       tArgsProcessed[sKey] = true
       tArgsProcessed[sKey] = true
     end
     end
Line 308: Line 276:


   for sKey, sVal in pairs(args) do
   for sKey, sVal in pairs(args) do
     if tArgsProcessed[sKey] ~= true and not isRestrictedStandardParam(sKey) then
    local restricted = false
       body:node(addRecipeCard(category, sVal, sKey))
 
    for _, keyParam in pairs(param) do
      if keyParam == sKey then
        restricted = true
      end
    end
 
     if tArgsProcessed[sKey] ~= true and not restricted then
       body:node(addRecipe(category, sVal, sKey))
     end
     end
   end
   end
Line 319: Line 295:


--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- Cooking parsing
-- Cooking recipe 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 344: Line 303:
   local ingredient = {
   local ingredient = {
     index = index,
     index = index,
     amount = args[prefix .. '_amount'] or nil,
     amount = args[prefix .. '_amount'] or '1',
     quality = args[prefix .. '_quality'],
     quality = args[prefix .. '_quality'],
     item = args[prefix],
     item = args[prefix],
Line 351: Line 310:
   }
   }


  -- |item_1_type = Fish
   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


  -- |item_1_type_1 = Freshwater Fish
  -- |item_1_type_2 = Saltwater Fish
   local typeIndex = 1
   local typeIndex = 1


Line 362: Line 324:
   end
   end


  -- |item_1_option_1 = Rice
  -- |item_1_option_2 = Wheat
   local optionIndex = 1
   local optionIndex = 1


Line 370: Line 334:


   local hasIngredient =
   local hasIngredient =
     argExists(args, prefix)
     ingredient.item ~= nil
     or #ingredient.types > 0
     or #ingredient.types > 0
     or #ingredient.options > 0
     or #ingredient.options > 0
Line 381: Line 345:
end
end


--------------------------------------------------------------------------------
local function getKitchenware(args)
-- Cooking type split-card helpers
  local kitchenware = {}
--------------------------------------------------------------------------------


local function makeTypeIcon(typeName)
  if argExists(args, 'kitchenware') then
  return '[[File:' .. typeName .. ' Icon.png|74x74px|link=' .. typeName .. ']]'
    table.insert(kitchenware, args.kitchenware)
end
  end


local function joinTypeCaption(types)
   local index = 1
   local out = {}


   for _, typeName in ipairs(types) do
   while argExists(args, 'kitchenware_' .. index) do
     table.insert(out, '[[' .. typeName .. ']]')
     table.insert(kitchenware, args['kitchenware_' .. index])
    index = index + 1
   end
   end


   return table.concat(out, ' / ')
   return kitchenware
end
end


local function renderCookingSplitTypeCard(category, body, ingredient)
--------------------------------------------------------------------------------
  local qualityClass = getQualityClass(ingredient.quality or 'Gray')
-- Cooking recipe display
--------------------------------------------------------------------------------


   local container = body:tag('span')
local function renderCookingTypeCard(category, body, ingredient)
     :addClass('card-container')
   local wrapper = body:tag('div')
     :addClass('recipe-type-split-card')
     :addClass('recipe_body_cooking_ingredient')
     :addClass('recipe_body_cooking_type_card')


   local wrapper = container:tag('span')
   local fileBase = joinFileNameParts(ingredient.types)
    :addClass('card-wrapper')
  local fileName = 'Recipe ' .. fileBase .. ' Icon.png'
  local caption = joinDisplay(ingredient.types, ' / ')


   local cardBody = wrapper:tag('span')
   for _, typeName in ipairs(ingredient.types) do
     :addClass('card-body')
     category:wikitext('[[Category:Uses ', typeName, ']]')
  end


   local imageContainer = cardBody:tag('span')
   local amountText = tostring(ingredient.amount or '1')
    :addClass('card-image-container')
    :addClass('recipe-type-split-image')


   imageContainer:tag('span')
   local card = wrapper:tag('div')
     :addClass('recipe-type-split-half')
     :addClass('card')
     :addClass('recipe-type-split-half-a')
     :addClass('recipe-type-card')
    :wikitext(makeTypeIcon(ingredient.types[1]))
    :done()


   imageContainer:tag('span')
   if ingredient.quality then
     :addClass('recipe-type-split-half')
     card:addClass('card-quality-' .. normalizeType(ingredient.quality))
    :addClass('recipe-type-split-half-b')
  end
    :wikitext(makeTypeIcon(ingredient.types[2]))
    :done()
   
if qualityClass then
    imageContainer:addClass(qualityClass)
end


   if tostring(ingredient.amount or '') ~= '' then
   card:tag('div')
    container:tag('span')
    :addClass('card-image')
      :addClass('card-label')
    :wikitext('[[File:' .. fileName .. '|64x64px|link=]]')
      :wikitext(tostring(ingredient.amount or '1'))
      :done()
  end


   container:tag('span')
   card:tag('div')
     :addClass('card-caption')
     :addClass('card-caption')
     :wikitext(joinTypeCaption(ingredient.types))
     :wikitext(caption)
    :done()
 
  for _, typeName in ipairs(ingredient.types) do
    addUseCategory(category, typeName)
  end
end
 
--------------------------------------------------------------------------------
-- Cooking display
--------------------------------------------------------------------------------
 
local function renderCookingSpecificItem(category, body, ingredient)
  body:node(addRecipeCard(
    category,
    ingredient.amount,
    ingredient.item,
    ingredient.quality
  ))
end
 
local function renderCookingTypeFallback(category, body, ingredient)
  local wrapper = body:tag('div')
    :addClass('recipe-body-cooking-ingredient')
    :addClass('recipe-body-cooking-type-cards')


   for _, typeName in ipairs(ingredient.types) do
   if amountText ~= '' then
     wrapper:node(addMiniCard(
     card:tag('div')
       category,
       :addClass('card-text')
      typeName,
      :wikitext(amountText)
      ingredient.amount,
      ingredient.quality
    ))
  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 487: Line 406:
local function renderCookingOptionCards(category, body, ingredient)
local function renderCookingOptionCards(category, body, ingredient)
   local wrapper = body:tag('div')
   local wrapper = body:tag('div')
     :addClass('recipe-body-cooking-ingredient')
     :addClass('recipe_body_cooking_ingredient')
     :addClass('recipe-body-cooking-option-cards')
     :addClass('recipe_body_cooking_options')


   for _, itemName in ipairs(ingredient.options) do
   for _, itemName in ipairs(ingredient.options) do
     wrapper:node(addMiniCard(
     wrapper:node(addRecipe(category, ingredient.amount, itemName, ingredient.quality))
      category,
      itemName,
      ingredient.amount,
      ingredient.quality
    ))
   end
   end
end
end


local function renderCookingIngredient(category, body, ingredient)
local function renderCookingIngredient(category, body, ingredient)
  -- Specific item:
  -- |item_1 = Rice
   if ingredient.item then
   if ingredient.item then
     renderCookingSpecificItem(category, body, ingredient)
     body:node(addRecipe(category, ingredient.amount, ingredient.item, ingredient.quality))
     return
     return
   end
   end


  -- Multiple accepted specific items:
  -- |item_1_option_1 = Rice
  -- |item_1_option_2 = Wheat
   if #ingredient.options > 0 then
   if #ingredient.options > 0 then
     renderCookingOptionCards(category, body, ingredient)
     renderCookingOptionCards(category, body, ingredient)
Line 511: Line 430:
   end
   end


  -- Type-based ingredient:
  -- |item_1_type = Fish
  -- |item_1_type_1 = Freshwater Fish
  -- |item_1_type_2 = Saltwater Fish
   if #ingredient.types > 0 then
   if #ingredient.types > 0 then
     renderCookingTypeCards(category, body, ingredient)
     renderCookingTypeCard(category, body, ingredient)
     return
     return
   end
   end
end
local function renderKitchenwareIcon(body, kitchenware)
  body:tag('div')
    :addClass('recipe_body_icon')
    :addClass('recipe_body_kitchenware_icon')
    :wikitext('[[File:Icon_' .. kitchenware .. '.png|35x35px|link=' .. kitchenware .. ']]')
end
local function renderKitchenwareMiniCard(category, body, kitchenware)
  body:tag('div')
    :addClass('recipe_body_icon')
    :addClass('recipe_body_kitchenware_card')
    :node(addMiniCard(category, kitchenware, ''))
end
end


Line 522: Line 459:
   end
   end


   local sYield = args[param.sYieldArg] or nil
   local sYield = args[param.sYieldArg] or '1'
   local pageTitle = getCurrentPageName(args)
   local pageTitle = args.page or mw.title.getCurrentTitle().text
  local kitchenware = getKitchenware(args)
 
  local yieldCard = Card._main({
    name = pageTitle,
    text = sYield,
    show_caption = '1',
  })


   local yieldCard = addYieldCard(pageTitle, sYield)
   if #kitchenware == 0 then
    body:tag('div')
      :addClass('recipe_body_icon')
      :wikitext('➜')
  elseif #kitchenware == 1 then
    -- Default: icon mode.
    -- Change this to renderKitchenwareMiniCard(category, body, kitchenware[1])
    -- if you prefer mini-card kitchenware display.
    renderKitchenwareIcon(body, kitchenware[1])


   body
    category:wikitext('[[Category:Uses ', kitchenware[1], ']]')
     :tag('div'):addClass('recipe-body-icon')
   else
       :wikitext('➜'):done()
     local wrapper = body:tag('div')
     :tag('div'):addClass('recipe-body-yield')
      :addClass('recipe_body_icon')
      :node(yieldCard)
       :addClass('recipe_body_kitchenware_multi')
 
    for _, itemName in ipairs(kitchenware) do
      wrapper:node(addMiniCard(category, itemName, ''))
     end
  end
 
  body:tag('div')
    :addClass('recipe_body_yield')
    :node(yieldCard)
 
  local itemText = require('Module:Item').main{
    [1] = pageTitle,
    [2] = '15',
    x = sYield
  }
end
end


Line 539: Line 506:
   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('recipe-body')
     :addClass('recipe_body')
     :addClass('recipe-body-cooking')
     :addClass('recipe_body_cooking')


  local ingredientIndex = 1
   local foundIngredient = false
   local foundIngredient = false
  local maxIndex = getMaxCookingItemIndex(args)


   for index = 1, maxIndex do
   while true do
     local ingredient = getCookingIngredient(args, index)
     local ingredient = getCookingIngredient(args, ingredientIndex)


     if ingredient then
     if not ingredient then
       foundIngredient = true
       break
      renderCookingIngredient(category, body, ingredient)
     end
     end
    foundIngredient = true
    renderCookingIngredient(category, body, ingredient)
    ingredientIndex = ingredientIndex + 1
   end
   end


Line 583: Line 553:
function p._main(args, frame)
function p._main(args, frame)
   local output = mw.html.create('div')
   local output = mw.html.create('div')
     :addClass('recipe-container')
     :addClass('recipe_container')


   local category = mw.html.create()
   local category = mw.html.create()
Line 594: Line 564:
     local sType = args[param.sTypeArg]
     local sType = args[param.sTypeArg]


     if normalizeText(sType) == 'cooking' then
     if normalizeType(sType) == 'cooking' then
       renderCookingRecipe(args, frame, output, category)
       renderCookingRecipe(args, frame, output, category)
     else
     else
Please note that all contributions to The Petit Planet Wiki are considered to be released under the Creative Commons Attribution-ShareAlike (see Petit Planet Wiki:Copyrights for details). If you do not want your writing to be edited mercilessly and redistributed at will, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource. Do not submit copyrighted work without permission!
Cancel Editing help (opens in new window)
Preview page with this template
Below are commonly used wikitext from MediaWiki:Edittools. Click on any to insert them in the edit box.
File Pages==Summary====Licensing=={{Fairuse}}{{File|}}
Dynamic Page List¦²«»²{¦}²«»«/»«!----»
Array in DPL¹^2{}^2^2{¹}^2
Parser Functions{{#if:||}}
{{#ifeq:|||}}
{{#expr:}}
{{#switch:||#default=}}
{{#replace:||}}
{{#titleparts:}}
{{#tag:|}}
Markup{{}}|[][[]][[Category:]]#REDIRECT [[]] [[Category:Redirect Pages]]<code></code><includeonly></includeonly><noinclude></noinclude><nowiki></nowiki><!----><br>§
Notices{{Stub|}}{{Stub Dialogue}}{{Upcoming}}{{Under Construction}}{{Placeholder|}}
Magic Words{{!}}{{formatnum:}}{{lc:}}{{uc:}}{{PAGENAME}}{{FULLPAGENAME}}{{ROOTPAGENAME}}{{BASEPAGENAME}}{{SUBPAGENAME}}{{DISPLAYTITLE:|noreplace}}__TOC____NOTOC____EXPECTUNUSEDCATEGORY____HIDDENCAT__
HTML Entities&mdash;&nbsp;&comma;&shy;