Module:Infobox/sandbox: Difference between revisions

From Official Factorio Wiki
Jump to navigation Jump to search
(Better account for fully whitespace args in row and vrow)
No edit summary
 
(6 intermediate revisions by the same user not shown)
Line 1: Line 1:
local p = {}
local p = {}


function p.row(frame)
function p.vanilla(frame)
   local args = frame.args
  local args = frame:getParent().args
   if not p.clean_arg(args[2]) then
  local ret = {}
 
 
  if not p._empty_arg(args["recipe"]) then
    ret[#ret+1] = p.vrow(frame, {"Recipe", args["recipe"], p._crafting_parsing(frame, args["recipe"])})
    ret[#ret+1] = p.vrow(frame, {"Total raw", args["recipe"], p._crafting_raw(frame, p._arg_or(args["total-raw"], args["recipe"]))})
  end
  if not p._empty_arg(args["cost"]) then
    local cost = p._item_parsing(frame, args["cost"]) .. ((not p._empty_arg(args["cost-multiplier"])) and "✖ <big>" .. args["cost-multiplier"] .. "</big>" or "")
    ret[#ret+1] = p.vrow(frame, {"Cost", args["cost"], cost})
  end
  ret[#ret+1] = p.vrow(frame, {"Required technologies",
                              args["required-technologies"],
                              p._technology_parsing(frame, {args["required-technologies"], color = "228B22"}),
                              p._translate(frame, "None required")})
  ret[#ret+1] = p.vrow(frame, {"Allows",
                              args["allows"],
                              p._technology_parsing(frame, {args["allows"], color = "228B22"})})
  ret[#ret+1] = p.vrow(frame, {"Effects", args["effects"], p.item_parsing(frame, args["effects"])})
  ret[#ret+1] = frame:expandTemplate{title = 'Infobox/extra', args = {args["extra1"]}}
  if not p._empty_arg(args["map-color"]) then
    local color = frame:expandTemplate{title = 'Color', args = {args["map-color"]}}
    ret[#ret+1] = p.row(frame, {"Map color", args["map-color"], color})
   end
  ret[#ret+1] = p.row(frame, {"Map icon", args["map-icon"]})
  ret[#ret+1] = p.row(frame, {"Added in", args["added-in"]})
  ret[#ret+1] = p.row(frame, {"Walking speed", args["walking-speed"]})
  ret[#ret+1] = p.row(frame, {"Storage size", args["storage-size"]})
  ret[#ret+1] = p.row(frame, {"Fluid storage volume", args["fluid-storage-volume"]})
   if not p._empty_arg(args["expected-resources"]) then
    local label = p._translate(frame, "Expected resources")
    ret[#ret+1] = string.format(
[[<tr class="border-top">
<td>
%s
</td>
<td style="width: 70%%;">
%s
</td>
</tr>]], label, args["expected-resources"])
  end
 
  return table.concat(ret)
end
 
function p._translate(frame, str)
  return frame:expandTemplate{title = 'Translation', args = {str}}
end
 
function p.row(frame, args)
  if p._empty_arg(args[2]) then
     return
     return
   end
   end


   local label = frame:expandTemplate{title = 'Translation', args = {args[1]}}
   local label = p._translate(frame, args[1])


   return string.format(
   return string.format(
Line 22: Line 72:
end
end


function p.vrow(frame)
function p.vrow(frame, args)
   local args = frame.args
   if p._empty_arg(args[2]) and p._empty_arg(args[4]) then
    return
  end


   local label = frame:expandTemplate{title = 'Translation', args = {args[1]}}
   local label = p._translate(frame, args[1])
   local content = ""
   local content = ""
   if p.clean_arg(args[2]) then
   if not p._empty_arg(args[2]) then
     content = args[3] or args[2]
     content = args[3] or args[2]
   elseif p.clean_arg(args[4]) then -- We might want to remove this since it is only used to display "None required" for field required-technologies, but it's kind of obvious no technologies are required if it's not in the infobox already
   else -- We might want to remove this since it is only used to display "None required" for field required-technologies, but it's kind of obvious no technologies are required if it's not in the infobox already
     content = "<i>" .. args[4] .. "</i>"
     content = "<i>" .. args[4] .. "</i>"
   end
   end
Line 49: Line 101:


function p.technology_parsing(frame)
function p.technology_parsing(frame)
   local args = frame.args
   return p._technology_parsing(frame, frame.args)
   if args[1] == "?" then
end
     return args[1] -- same as old template, likely not needed
 
function p._technology_parsing(frame, args)
   if args[1] == "?" or p._empty_arg(args[1]) then
     return args[1]
   end
   end


Line 76: Line 131:


function p.item_parsing(frame)
function p.item_parsing(frame)
   local args = frame.args
   return p._item_parsing(frame, frame.args[1])
   if args[1] == "?" then
end
     return args[1] -- same as old template, likely not needed
 
function p._item_parsing(frame, item_string)
   if item_string == "?" or p._empty_arg(item_string) then
     return item_string
   end
   end


   local ret = {}
   local ret = {}
   local items = p._split(args[1], "+")
   local items = p._split(item_string, "+")
   for _, item in ipairs(items) do
   for _, item in ipairs(items) do
     local icon_args = p._split(item, ",")
     local icon_args = p._split(item, ",")
Line 91: Line 149:
end
end


function p.crafting_parsing(frame)
  return p._crafting_parsing(frame, frame.args[1])
end


function p.crafting_parsing(frame)
function p._crafting_parsing(frame, recipe)
  local args = frame.args
   if recipe == "?" or p._empty_arg(recipe) then
   if args[1] == "?" then
     return recipe
     return args[1] -- same as old template, likely not needed
   end
   end
    
    
   local recipe_parts = p._split(args[1], "=")   
   local recipe_parts = p._split(recipe, "=")   
   local ingredients = p._crafting_parsing_split(frame, recipe_parts[1])
   local ingredients = p._crafting_parsing_split(frame, recipe_parts[1])
    
    
Line 113: Line 173:


function p.crafting_raw(frame)
function p.crafting_raw(frame)
   local args = frame.args
   return p._crafting_raw(frame, frame.args[1])
   if args[1] == "?" then
end
     return args[1] -- same as old template, likely not needed
 
function p._crafting_raw(frame, recipe)
   if recipe == "?" or p._empty_arg(recipe) then
     return recipe
   end
   end


   local recipe_parts = p._split(args[1], "=")
   local recipe_parts = p._split(recipe, "=")
   return p._crafting_parsing_split(frame, recipe_parts[1])
   return p._crafting_parsing_split(frame, recipe_parts[1])
end
end
Line 137: Line 200:
end
end


function p._arg_or(arg, default)
  if p._empty_arg(arg) then
    return default
  else
    return arg
  end
end


function p._clean_arg(arg)
-- @param arg string The argument to check
if type(arg) == "string" then
-- @return boolean @Whether the argument is an whitespace string or empty string or nil
arg = mw.text.trim(arg)
function p._empty_arg(arg)
if arg == "" then
  if type(arg) == "string" then
return nil
    return not string.find(arg, "%S")
else
  else
return arg
    return not arg
end
  end
else
return arg
end
end
end



Latest revision as of 20:15, 23 October 2024

Documentation for this module may be created at Module:Infobox/sandbox/doc

local p = {}

function p.vanilla(frame)
  local args = frame:getParent().args
  local ret = {}
  

  if not p._empty_arg(args["recipe"]) then
    ret[#ret+1] = p.vrow(frame, {"Recipe", args["recipe"], p._crafting_parsing(frame, args["recipe"])})
    ret[#ret+1] = p.vrow(frame, {"Total raw", args["recipe"], p._crafting_raw(frame, p._arg_or(args["total-raw"], args["recipe"]))})
  end
  if not p._empty_arg(args["cost"]) then
    local cost = p._item_parsing(frame, args["cost"]) .. ((not p._empty_arg(args["cost-multiplier"])) and "✖ <big>" .. args["cost-multiplier"] .. "</big>" or "")
    ret[#ret+1] = p.vrow(frame, {"Cost", args["cost"], cost})
  end
  ret[#ret+1] = p.vrow(frame, {"Required technologies",
                               args["required-technologies"],
                               p._technology_parsing(frame, {args["required-technologies"], color = "228B22"}),
                               p._translate(frame, "None required")})
  ret[#ret+1] = p.vrow(frame, {"Allows",
                               args["allows"],
                               p._technology_parsing(frame, {args["allows"], color = "228B22"})})
  ret[#ret+1] = p.vrow(frame, {"Effects", args["effects"], p.item_parsing(frame, args["effects"])})
  ret[#ret+1] = frame:expandTemplate{title = 'Infobox/extra', args = {args["extra1"]}}
  if not p._empty_arg(args["map-color"]) then
    local color = frame:expandTemplate{title = 'Color', args = {args["map-color"]}}
    ret[#ret+1] = p.row(frame, {"Map color", args["map-color"], color})
  end
  ret[#ret+1] = p.row(frame, {"Map icon", args["map-icon"]})
  ret[#ret+1] = p.row(frame, {"Added in", args["added-in"]})
  ret[#ret+1] = p.row(frame, {"Walking speed", args["walking-speed"]})
  ret[#ret+1] = p.row(frame, {"Storage size", args["storage-size"]})
  ret[#ret+1] = p.row(frame, {"Fluid storage volume", args["fluid-storage-volume"]})
  if not p._empty_arg(args["expected-resources"]) then
    local label = p._translate(frame, "Expected resources")
    ret[#ret+1] = string.format(
[[<tr class="border-top">
<td>
%s
</td>
<td style="width: 70%%;">
%s
</td>
</tr>]], label, args["expected-resources"])
  end

  return table.concat(ret)
end

function p._translate(frame, str)
  return frame:expandTemplate{title = 'Translation', args = {str}}
end

function p.row(frame, args)
  if p._empty_arg(args[2]) then
    return
  end

  local label = p._translate(frame, args[1])

  return string.format(
[[<tr class="border-top">
<td>
%s
</td>
<td>
%s
</td>
</tr>]],
    label,
    args[3] or args[2])
end

function p.vrow(frame, args)
  if p._empty_arg(args[2]) and p._empty_arg(args[4]) then
    return
  end

  local label = p._translate(frame, args[1])
  local content = ""
  if not p._empty_arg(args[2]) then
    content = args[3] or args[2]
  else -- We might want to remove this since it is only used to display "None required" for field required-technologies, but it's kind of obvious no technologies are required if it's not in the infobox already
    content = "<i>" .. args[4] .. "</i>"
  end

  return string.format(
[[<tr class="border-top">
<td colspan=2>
%s
</td>
</tr>
<tr>
<td class="infobox-vrow-value" colspan=2>
%s
</td>
</tr>]],
    label,
    content)
end

function p.technology_parsing(frame)
  return p._technology_parsing(frame, frame.args)
end

function p._technology_parsing(frame, args)
  if args[1] == "?" or p._empty_arg(args[1]) then
    return args[1]
  end

  local ret = {}
  local techs = p._split(args[1], "+")
  for _, tech in ipairs(techs) do
    local tech_parts = p._split(tech, ",")
    local tech_name = tech_parts[1] .. " (research)"
    if not p._page_exists(tech_name) then -- fall back to plain name if page with " (research)" doesn't exist
      tech_name = tech_parts[1]
    end

    local tech_level = tech_parts[2] or ""
    if tech_level == "" then -- fall back to level from tech name if none given manually
      local second_to_last_char = string.sub(tech_parts[1], -2, -2)
      if second_to_last_char == " " then
        tech_level = string.sub(tech_parts[1], -1) -- last character should be the level of the tech
      end
    end
    ret[#ret+1] = frame:expandTemplate{title = 'icon/special', args = {tech_name, tech_level, color=args.color or "999"}}
  end
  return table.concat(ret)
end

function p.item_parsing(frame)
  return p._item_parsing(frame, frame.args[1])
end

function p._item_parsing(frame, item_string)
  if item_string == "?" or p._empty_arg(item_string) then
    return item_string
  end

  local ret = {}
  local items = p._split(item_string, "+")
  for _, item in ipairs(items) do
    local icon_args = p._split(item, ",")
    icon_args[2] = icon_args[2] or ""
    ret[#ret+1] = frame:expandTemplate{title = 'icon/special', args = icon_args}
  end
  return table.concat(ret)
end

function p.crafting_parsing(frame)
  return p._crafting_parsing(frame, frame.args[1])
end

function p._crafting_parsing(frame, recipe)
  if recipe == "?" or p._empty_arg(recipe) then
    return recipe
  end
  
  local recipe_parts = p._split(recipe, "=")  
  local ingredients = p._crafting_parsing_split(frame, recipe_parts[1])
  
  local products = recipe_parts[2]
  if products then
    products = "&rarr; " .. p._crafting_parsing_split(frame, products)
  else
    local item_name = frame:expandTemplate{title = 'No language suffix/No namespace'}
    products = "&rarr; " .. frame:expandTemplate{title = 'icon/special', args = {item_name, "1"}}
  end
  
  return ingredients .. products
end

function p.crafting_raw(frame)
  return p._crafting_raw(frame, frame.args[1])
end

function p._crafting_raw(frame, recipe)
  if recipe == "?" or p._empty_arg(recipe) then
    return recipe
  end

  local recipe_parts = p._split(recipe, "=")
  return p._crafting_parsing_split(frame, recipe_parts[1])
end

-- @param frame
-- @param str string A list of "item, count" separated by "+"
-- @return string @The resulting icons with a "+" between each icon
function p._crafting_parsing_split(frame, str)
  local ret = {}
  local items = p._split(str, "+")
  for _, item in ipairs(items) do
    local item_parts = p._split(item, ",")
    local item_count = item_parts[2] or "1" -- fall back to 1, not empty!
    item_count = frame:expandTemplate{title = 'Crop', args = {item_count}}
    ret[#ret+1] = frame:expandTemplate{title = 'icon/special', args = {item_parts[1], item_count}}
  end
  return table.concat(ret, "+")
end

function p._arg_or(arg, default)
  if p._empty_arg(arg) then
    return default
  else
    return arg
  end
end

-- @param arg string The argument to check
-- @return boolean @Whether the argument is an whitespace string or empty string or nil
function p._empty_arg(arg)
  if type(arg) == "string" then
    return not string.find(arg, "%S")
  else
    return not arg
  end
end

-- @param inputstr string A string to be split
-- @param separator string The separator
-- @return string[] @The separated strings, without the separator
function p._split(inputstr, separator)
  local result = {}

  for str in string.gmatch(inputstr, "([^"..separator.."]+)") do
    table.insert(result, mw.text.trim(str))
  end

  return result
end

-- @param page_title string The title of the page
-- @return boolean
function p._page_exists(page_title)
  if page_title and page_title ~= "" then
    return mw.title.new(page_title).exists
  else
    return false
  end
end

return p