Module:Infobox
From XenReference
Documentation for this module may be created at Module:Infobox/doc
-- This module follows [[User:Ganaram inukshuk/Provisional style guide for Lua]]
local getArgs = require("Module:Arguments").getArgs
local navbar = require("Module:Navbar")._navbar
local tiu = require("Module:Template input utils")
local yesno = require("Module:Yesno")
local p = {}
-- TODO (medium priority):
-- - Use templatestyles
--------------------------------------------------------------------------------
-------------------------------- MAIN FUNCTIONS --------------------------------
--------------------------------------------------------------------------------
-- Function to be called by other modules; also called by wrapper function
function p._infobox(args)
local title = args["Title"] or "Infobox Title"
local adjacent_links = args["Adjacent Links"]
local header_row = args["Header Row"]
local rows = args["Rows"]
local footer_row = args["Footer Row"]
local name = args["name"]
-- Helper function; preprocess rows
function preprocess_rows()
-- Preproces rows
local is_jagged = true
for i = 1, #rows do
local row = rows[i]
is_jagged = is_jagged and (#row == 1 or #row == 2)
end
if is_jagged then return tiu.jagged_array_to_header_data_pairs(rows)
else return rows end
end
-- Preprocess rows
rows = preprocess_rows()
-- Nested helper function
-- Produces the title and, if present, prev/next links
function infobox_title()
if adjacent_links == nil then
return title
elseif #adjacent_links == 2 then
lines = {}
--table.insert(lines, "\n")
table.insert(lines, '{| style="width: 100%;"')
table.insert(lines, '|-')
table.insert(lines, '| style="font-size: 0.75em;" | ' .. adjacent_links[1])
table.insert(lines, '| style="width: 50%;" | ' .. title)
table.insert(lines, '| style="font-size: 0.75em;" | ' .. adjacent_links[2])
table.insert(lines, '|}')
return table.concat(lines, "\n")
elseif #adjacent_links == 8 then
lines = {}
--table.insert(lines, "\n")
table.insert(lines, '{| style="width: 100%;"')
table.insert(lines, '|-')
table.insert(lines, '| style="font-size: 0.75em;" | ' .. adjacent_links[1])
table.insert(lines, '| style="font-size: 0.75em; width: 50%;" | ' .. adjacent_links[2])
table.insert(lines, '| style="font-size: 0.75em;" | ' .. adjacent_links[3])
table.insert(lines, '|-')
table.insert(lines, '| style="font-size: 0.75em;" | ' .. adjacent_links[4])
table.insert(lines, '| style="width: 50%;" | ' .. title)
table.insert(lines, '| style="font-size: 0.75em;" | ' .. adjacent_links[5])
table.insert(lines, '|-')
table.insert(lines, '| style="font-size: 0.75em;" | ' .. adjacent_links[6])
table.insert(lines, '| style="font-size: 0.75em; width: 50%;" | ' .. adjacent_links[7])
table.insert(lines, '| style="font-size: 0.75em;" | ' .. adjacent_links[8])
table.insert(lines, '|}')
return table.concat(lines, "\n")
else
return title
end
end
-- Nested helper function
-- Produces a row in the infobox
function infobox_row(row_content)
local header = row_content["Header"]
local data = row_content["Data" ]
if header and data then
local lines = {}
table.insert(lines, '|-')
table.insert(lines, '| style="text-align: right; padding-right: 0.25em;" | ' .. header)
table.insert(lines, '| style="background-color: black; padding-left: 0.25em; font-weight: bold;" | ' .. data)
return table.concat(lines, "\n")
elseif header and not data then
local lines = {}
table.insert(lines, '|-')
table.insert(lines, '| colspan="2" style="text-align: center;" | ' .. header)
return table.concat(lines, "\n")
elseif data and not header then
local lines = {}
table.insert(lines, '|-')
table.insert(lines, '| colspan="2" style="text-align: center;" | ' .. data)
return table.concat(lines, "\n")
end
end
-- Nested helper function
-- Produces a header or footer row
function header_footer_row(row_content)
local lines = {}
table.insert(lines, '|-')
table.insert(lines, '| colspan="2" style="text-align: center; font-size: 0.8em;" | ' .. row_content)
return table.concat(lines, "\n")
end
-- Nested helper function
-- Produces the navbar, if specified
function navbar_row()
local lines = {}
table.insert(lines, '|-')
table.insert(lines, '| colspan="2" style="text-align: center;" | ' .. navbar(name, "mini", ""))
return table.concat(lines, "\n")
end
-- Start of infobox; outer div and start of table
local lines = {}
-- Infobox boilerplate
table.insert(lines,
[[<div style="
border: 1px solid #999;
margin: 0;
margin-left: 1em;
margin-bottom: 0.5em;
padding: 0.5em;
background-color: #0f0f0f;
min-width: 15em;
float: right;
max-width: 100%;
overflow: auto;">]]
)
table.insert(lines, '{| style="border-collapse: collapse; width: 100%;"')
table.insert(lines, '|+ style="font-size: 105%; font-weight: bold; text-align: center;" | ')
-- Title
table.insert(lines, infobox_title())
-- Header
if header_row then
table.insert(lines, header_footer_row(header_row))
end
-- Rows
for i = 1, #rows do
table.insert(lines, infobox_row(rows[i]))
end
-- Footer
if footer_row then
table.insert(lines, header_footer_row(footer_row))
end
-- Template navbar
if name then
table.insert(lines, navbar_row())
end
-- End of infobox
table.insert(lines, "|}")
table.insert(lines, "</div>")
return table.concat(lines, "\n")
end
-- Function to be #invoke'd
-- Wrapper function for template-based infoboxes
-- Modeled off of navbox
function p.infobox(frame)
local args = getArgs(frame)
-- Preprocess adjacent links
-- If there are two adjacent links (such as with edos), then links will be
-- placed on the left and right of the title:
-- [Link 1] Title [Link 2]
-- If there are eight adjacent links (such as with mosses), then links
-- surround the title in a 3x3 grid:
-- [Link 1] [Link 2] [Link 3]
-- [Link 4] Title [Link 5]
-- [Link 6] [Link 7] [Link 8]
local function any_keys_present(tbl, keys)
for _, key in ipairs(keys) do
if tbl[key] ~= nil then
return true
end
end
return false
end
-- Keys to links
-- Left and right are added if at least one is present -> 2-element table.
-- All three rows are added if at least one link from the upper or lower
-- rows is present, regardless of side links -> 8-element table.
-- No links are added if none of them are present -> 0-element table.
local upper_links = { "Upper Left Link", "Upper Link", "Upper Right Link" }
local side_links = { "Left Link", "Right Link" }
local lower_links = { "Lower Left Link", "Lower Link", "Lower Right Link" }
-- Check which links are present
local is_upper_lower_links_present =
any_keys_present(args, upper_links) or any_keys_present(args, lower_links)
local is_side_links_present = any_keys_present(args, side_links)
-- Build adjacent_links
-- Links from args are removed, as they're stored in a separate table
local adjacent_links = {}
if is_upper_lower_links_present then
-- Upper row of links
for _, key in ipairs(upper_links) do
table.insert(adjacent_links, args[key] or "")
args[key] = nil
end
-- Middle row of links
for _, key in ipairs(side_links) do
table.insert(adjacent_links, args[key] or "")
args[key] = nil
end
-- Bottom row of links
for _, key in ipairs(lower_links) do
table.insert(adjacent_links, args[key] or "")
args[key] = nil
end
elseif is_side_links_present then
-- Left and right links only
for _, key in ipairs(side_links) do
table.insert(adjacent_links, args[key] or "")
args[key] = nil
end
end
args["Adjacent Links"] = adjacent_links
-- Preprocess rows
-- Set row count to 30, under the reasoning that an infobox may need more
-- rows and/or headers. This may be increased to 40 if needed.
args["Rows"] = tiu.numbered_header_data_args_to_table(args, 30)
local result = p._infobox(args)
local debugg = yesno(args["debug"])
if debugg == true then
result = "<syntaxhighlight lang=\"wikitext\">" .. result .. "</syntaxhighlight>"
end
return result
end
--------------------------------------------------------------------------------
------------------------------- LEGACY FUNCTIONS -------------------------------
--------------------------------------------------------------------------------
-- These functions are kept in the meantime to support older infoboxes and WILL
-- be entirely deleted later! Please switch to the new functions!
-- Original function signature, kept for legacy support (for now).
function p.build(title, entries, prev_link, next_link)
local args = {
["Adjacent Links"] = { (prev_link or ""), (next_link or "") },
["Title"] = title,
["Rows"] = entries
}
return p._infobox(args)
end
-- Original 8-link function signature, pulled from infobox mos.
function p.build_multilink(title, entries, adjacent_links)
local args = {
["Adjacent Links"] = adjacent_links,
["Title"] = title,
["Rows"] = entries
}
return p._infobox(args)
end
return p
