Module:Infobox/sandbox: Difference between revisions

From Official Factorio Wiki
Jump to navigation Jump to search
(Ported Infobox/vrow)
No edit summary
 
(12 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 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
  if args[2] and args[2] ~= "" then
     return
     local label = frame:expandTemplate{title = 'Translation', args = {args[1]}}
  end


     return string.format(
  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">
[[<tr class="border-top">
<td colspan=2>
<td colspan=2>
Line 38: Line 96:
</td>
</td>
</tr>]],
</tr>]],
      label,
    label,
      args[3] or args[2])
    content)
  elseif 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
end
    local label = frame:expandTemplate{title = 'Translation', args = {args[1]}}


    return string.format(
function p.technology_parsing(frame)
[[<tr class="border-top">
  return p._technology_parsing(frame, frame.args)
<td colspan=2>
%s
</td>
</tr>
<tr>
<td class="infobox-vrow-value" colspan=2>
<i>%s</i>
</td>
</tr>]],
      label,
      args[4])
  end
end
end


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


Line 87: 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 102: 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 124: 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 146: Line 198:
   end
   end
   return table.concat(ret, "+")
   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
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