Module:Infobox: Difference between revisions
From Against the Storm Official Wiki
m (daggum typos!) |
(Updated doc; added generic range title; *maybe* fixed the extraneous separator issue) |
||
(10 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
--- | --- | ||
--- Module to | --- Module of shortcuts and layout methods to standardize infoboxes on various | ||
--- | --- wiki pages. Supported modules should not use any mw.create or :tag methods, | ||
--- but instead call the methods of this module with the facts and rely on | |||
--- this module to build the content. | |||
--- | |||
--- | |||
--- | --- | ||
--- @module Infobox | --- @module Infobox | ||
Line 16: | Line 11: | ||
local GoodsData = require("Module:GoodsData") | local GoodsData = require("Module:GoodsData") | ||
local StyleUtils = require("Module:StyleUtils") | |||
Line 23: | Line 19: | ||
local RESOURCE_LINK_TEMPLATE = "rl" | local RESOURCE_LINK_TEMPLATE = "rl" | ||
local RESOURCE_LINK_ICONSIZE = "med" | local RESOURCE_LINK_ICONSIZE = "med" | ||
local CONSTRUCTION_TEMPLATE = "Construction" | |||
local INDEX_REQ_STACK_SIZE= "stackSize" | local INDEX_REQ_STACK_SIZE= "stackSize" | ||
local INDEX_REQ_GOOD_ID = "goodID" | local INDEX_REQ_GOOD_ID = "goodID" | ||
local PATTERN_FORMAT_TWO_DECIMALS = "%1.2f" | local PATTERN_FORMAT_TWO_DECIMALS = "%1.2f" | ||
Line 38: | Line 34: | ||
--region Public constants | --region Public constants | ||
Infobox.TITLE_ID = "ID" | Infobox.TITLE_ID = "ID" | ||
Infobox.TITLE_CATEGORY = " | Infobox.TITLE_CATEGORY = "Category" | ||
Infobox.TITLE_SIZE = " | Infobox.TITLE_SIZE = "Size" | ||
Infobox.TITLE_EATABLE = "Eatable" | Infobox.TITLE_EATABLE = "Eatable" | ||
Infobox.TITLE_BURNABLE = "Burnable" | Infobox.TITLE_BURNABLE = "Burnable" | ||
Infobox.TITLE_BURN_TIME = " | Infobox.TITLE_BURN_TIME = "Burn time" | ||
Infobox.TITLE_MOVABLE = "Movable" | Infobox.TITLE_MOVABLE = "Movable" | ||
Infobox.TITLE_ESSENTIAL = " | Infobox.TITLE_ESSENTIAL = "Essential" | ||
Infobox.TITLE_STORAGE_CAPACITY = "Storage | Infobox.TITLE_STORAGE_CAPACITY = "Storage" | ||
Infobox.TITLE_RANGE = "Range" | |||
Infobox.TITLE_FARMING_AREA = "Farming Area" | Infobox.TITLE_FARMING_AREA = "Farming Area" | ||
Infobox.TITLE_GATHERING_AREA = " | Infobox.TITLE_GATHERING_AREA = "Gather Range" | ||
Infobox.TITLE_CONSTRUCTION_TIME = " | Infobox.TITLE_CONSTRUCTION_TIME = "Build Time" | ||
Infobox.TITLE_CONSTRUCTION_COST = " | Infobox.TITLE_CONSTRUCTION_COST = "Build Cost" | ||
Infobox.TITLE_SELL_VALUE = " | Infobox.TITLE_SELL_VALUE = "Sell value" | ||
Infobox.TITLE_BUY_VALUE = " | Infobox.TITLE_BUY_VALUE = "Buy price" | ||
Infobox.TITLE_WORKPLACES = "Workplaces" | Infobox.TITLE_WORKPLACES = "Workplaces" | ||
Infobox.TITLE_RECIPES = "Recipes" | Infobox.TITLE_RECIPES = "Recipes" | ||
Line 59: | Line 55: | ||
Infobox.ICONSIZE_MED = mw.getCurrentFrame():expandTemplate{ title="ImgM" } | Infobox.ICONSIZE_MED = mw.getCurrentFrame():expandTemplate{ title="ImgM" } | ||
-- Infobox styling | -- *DEPRECATED* Infobox styling. | ||
Infobox.CSS_MAIN = { | Infobox.CSS_MAIN = { | ||
["float"] = "right", | ["float"] = "right", | ||
Line 69: | Line 65: | ||
["margin"] = "0.5em 0 0.5em 1em" | ["margin"] = "0.5em 0 0.5em 1em" | ||
} | } | ||
Infobox.CSS_INNER_TABLE = { | Infobox.CSS_INNER_TABLE = { | ||
["border-collapse"] = "collapse" | ["border-collapse"] = "collapse" | ||
} | } | ||
Infobox.CSS_TR_BORDER_BOT = { | Infobox.CSS_TR_BORDER_BOT = { | ||
["border-bottom"] = "1px solid #a2a9b1" | ["border-bottom"] = "1px solid #a2a9b1" | ||
} | } | ||
Infobox.CSS_TR_BORDER_TOP = { | Infobox.CSS_TR_BORDER_TOP = { | ||
["border-top"] = "1px solid #a2a9b1" | ["border-top"] = "1px solid #a2a9b1" | ||
Line 108: | Line 101: | ||
--- | --- | ||
---@param row table html table row we're building | ---@param row table html table row we're building | ||
---@param | ---@param needsSeparator boolean whether we need a separator | ||
---@return boolean whether we still need a separator | ---@return boolean whether we still need a separator | ||
local function trySeparator(row, | local function trySeparator(row, needsSeparator) | ||
if | if needsSeparator then | ||
StyleUtils.styleInfoboxSeparator(row) | StyleUtils.styleInfoboxSeparator(row) | ||
return false | |||
end | end | ||
return | return true | ||
end | end | ||
Line 196: | Line 188: | ||
---@param category string the category of the icon to make | ---@param category string the category of the icon to make | ||
---@return string the wiki markup for the icon | ---@return string the wiki markup for the icon | ||
function Infobox.makeCategoryIcon(category) | function Infobox.makeCategoryIcon(category, isGoodsCategory) | ||
local classStr = "" | |||
if isGoodsCategory then | |||
classStr = StyleUtils.CLASS_GOODS_CATEGORY_ICON | |||
else | |||
classStr = StyleUtils.CLASS_CATEGORY_ICON | |||
end | |||
return "[[File:" .. Infobox.ICON_FILENAMES_CATEGORIES[category] .. | return "[[File:" .. Infobox.ICON_FILENAMES_CATEGORIES[category] .. | ||
"|" .. Infobox.ICONSIZE_MED .. "|alt=" .. category .. "]]" | "|" .. Infobox.ICONSIZE_MED .. "|alt=" .. category .. | ||
"|class=" .. classStr .. "]]" | |||
end | end | ||
Line 271: | Line 271: | ||
local row | local row | ||
local nowNeedsSeparator = needsSeparator | |||
if check ~= nil and check ~= "" then | if check ~= nil and check ~= "" then | ||
row = parentNode:tag("tr") | row = parentNode:tag("tr") | ||
nowNeedsSeparator = trySeparator(row, needsSeparator) | |||
populateStandardRow(row, header, value) | populateStandardRow(row, header, value) | ||
end | end | ||
return | return nowNeedsSeparator | ||
end | end | ||
--- TODO DELETE THIS because we're not doing inline css anymore | --- *DEPRECATED* TODO DELETE THIS because we're not doing inline css anymore | ||
--- Shortcut method to build a standard row with a header and a value. | --- Shortcut method to build a standard row with a header and a value. | ||
--- | --- | ||
Line 316: | Line 317: | ||
end | end | ||
local | local templateArgs = {} | ||
for _, requiredGroup in ipairs(requiredGoods) do | for _, requiredGroup in ipairs(requiredGoods) do | ||
local stackSize = requiredGroup[INDEX_REQ_STACK_SIZE] | local stackSize = requiredGroup[INDEX_REQ_STACK_SIZE] | ||
local | local goodName = GoodsData.getGoodNameByID(requiredGroup[INDEX_REQ_GOOD_ID]) | ||
templateArgs[goodName] = stackSize | |||
end | end | ||
return | return mw.getCurrentFrame():expandTemplate{ title = CONSTRUCTION_TEMPLATE, | ||
args = templateArgs } | |||
end | end | ||
Line 343: | Line 340: | ||
local wikiInfobox = mw.html.create("div") | local wikiInfobox = mw.html.create("div") | ||
StyleUtils.styleInfobox(wikiInfobox) | StyleUtils.styleInfobox(wikiInfobox) | ||
wikiInfobox:newline() | |||
return wikiInfobox | return wikiInfobox | ||
Line 359: | Line 358: | ||
local header = wikiInfobox:tag("div") | local header = wikiInfobox:tag("div") | ||
StyleUtils.styleInfoboxHeader(header) | StyleUtils.styleInfoboxHeader(header) | ||
header:newline() | |||
return header | return header | ||
Line 389: | Line 390: | ||
local innerTable = wikiInfobox:tag("table") | local innerTable = wikiInfobox:tag("table") | ||
innerTable = StyleUtils.styleInfoboxInnerTable(innerTable) | innerTable = StyleUtils.styleInfoboxInnerTable(innerTable) | ||
innerTable | |||
innerTable:newline() | |||
return innerTable | return innerTable |
Latest revision as of 15:43, 24 December 2023
Documentation for this module may be created at Module:Infobox/doc
--- --- Module of shortcuts and layout methods to standardize infoboxes on various --- wiki pages. Supported modules should not use any mw.create or :tag methods, --- but instead call the methods of this module with the facts and rely on --- this module to build the content. --- --- @module Infobox local Infobox = {} local GoodsData = require("Module:GoodsData") local StyleUtils = require("Module:StyleUtils") --region Private constants local RESOURCE_LINK_TEMPLATE = "rl" local RESOURCE_LINK_ICONSIZE = "med" local CONSTRUCTION_TEMPLATE = "Construction" local INDEX_REQ_STACK_SIZE= "stackSize" local INDEX_REQ_GOOD_ID = "goodID" local PATTERN_FORMAT_TWO_DECIMALS = "%1.2f" local PATTERN_CAPTURE_FIRST_LETTER_IN_WORD = "(%a)([%w]*)" --endregion --region Public constants Infobox.TITLE_ID = "ID" Infobox.TITLE_CATEGORY = "Category" Infobox.TITLE_SIZE = "Size" Infobox.TITLE_EATABLE = "Eatable" Infobox.TITLE_BURNABLE = "Burnable" Infobox.TITLE_BURN_TIME = "Burn time" Infobox.TITLE_MOVABLE = "Movable" Infobox.TITLE_ESSENTIAL = "Essential" Infobox.TITLE_STORAGE_CAPACITY = "Storage" Infobox.TITLE_RANGE = "Range" Infobox.TITLE_FARMING_AREA = "Farming Area" Infobox.TITLE_GATHERING_AREA = "Gather Range" Infobox.TITLE_CONSTRUCTION_TIME = "Build Time" Infobox.TITLE_CONSTRUCTION_COST = "Build Cost" Infobox.TITLE_SELL_VALUE = "Sell value" Infobox.TITLE_BUY_VALUE = "Buy price" Infobox.TITLE_WORKPLACES = "Workplaces" Infobox.TITLE_RECIPES = "Recipes" Infobox.ICONSIZE_MED = mw.getCurrentFrame():expandTemplate{ title="ImgM" } -- *DEPRECATED* Infobox styling. Infobox.CSS_MAIN = { ["float"] = "right", ["clear"] = "right", ["width"] = "256px", ["border"] = "1px solid #a2a9b1", ["border-spacing"] = "3px", ["border-collapse"] = "collapse", ["margin"] = "0.5em 0 0.5em 1em" } Infobox.CSS_INNER_TABLE = { ["border-collapse"] = "collapse" } Infobox.CSS_TR_BORDER_BOT = { ["border-bottom"] = "1px solid #a2a9b1" } Infobox.CSS_TR_BORDER_TOP = { ["border-top"] = "1px solid #a2a9b1" } -- Infobox icons Infobox.ICON_FILENAMES_CATEGORIES = { -- Buildings ["Camps"] = "Construct Camps.png", ["City Buildings"] = "Construct City Buildings.png", ["Food Production"] = "Construct Food Production.png", ["Industry"] = "Construct Industry.png", -- Goods ["Building Materials"] = "Icon_UI_CategoryBuilding.png", ["Consumable Items"] = "Icon_UI_CategoryConsumable.png", ["Crafting Resources"] = "Icon_UI_CategoryCrafting.png", ["Food"] = "Icon UI CategoryFood.png", ["Fuel & Exploration"] = "Icon_UI_CategoryFuel.png", ["Trade Goods"] = "Icon_UI_CategoryTrade.png" } --endregion --region Private methods --- --- Adds a separator if needed. --- ---@param row table html table row we're building ---@param needsSeparator boolean whether we need a separator ---@return boolean whether we still need a separator local function trySeparator(row, needsSeparator) if needsSeparator then StyleUtils.styleInfoboxSeparator(row) return false end return true end --- --- Shortcut method to populate the provided row with a header and a value. --- ---@param htmlRow table the html table row we're populating ---@param header string header text ---@param value string value text ---@return table the same htmlTable local function populateStandardRow(htmlRow, header, value) htmlRow:tag("th"):wikitext(header):done() :tag("td"):wikitext(value):done() :done():newline() return htmlRow end --endregion --region Public methods --- --- Shortcut string to reformat numbers with two decimals. --- ---@param value number whole or with a fractional part ---@return string reformatted to force two decimal places function Infobox.toTwoDecimalPlaces(value) return string.format(PATTERN_FORMAT_TWO_DECIMALS, value) end --- --- Capitalizes the first character of each word to "Make It Title Case." Also --- converts any underscores to spaces. --- --- @param title string to capitalize --- @return string capitalized with title case function Infobox.toTitleCase(title) title = title:gsub("_", " ") local newTitle = title:gsub(PATTERN_CAPTURE_FIRST_LETTER_IN_WORD, function(firstLetter, rest) return firstLetter:upper() .. rest:lower() end) return newTitle end --- --- A shortcut method for making resource links. --- ---@param goodID string the ID of the good to link to ---@return string wikimarkup representing an icon and link function Infobox.resourceLink(goodID) local goodName = GoodsData.getGoodNameByID(goodID) return mw.getCurrentFrame():expandTemplate{ title=RESOURCE_LINK_TEMPLATE, args={ resource=goodName, iconsize= RESOURCE_LINK_ICONSIZE } } end --- --- A shortcut method for looking up an icon and assigning its wiki markup. --- ---@param category string the category of the icon to make ---@return string the wiki markup for the icon function Infobox.makeCategoryIcon(category, isGoodsCategory) local classStr = "" if isGoodsCategory then classStr = StyleUtils.CLASS_GOODS_CATEGORY_ICON else classStr = StyleUtils.CLASS_CATEGORY_ICON end return "[[File:" .. Infobox.ICON_FILENAMES_CATEGORIES[category] .. "|" .. Infobox.ICONSIZE_MED .. "|alt=" .. category .. "|class=" .. classStr .. "]]" end --- --- A shortcut method for making a standard title. --- ---@param parentNode table the html node to add to ---@param title string the title to write ---@return table the title node added function Infobox.makeTitle(parentNode, title) local p = parentNode:tag("p") StyleUtils.styleInfoboxTitle(p) p:wikitext(title):done():newline() return p end --- --- A shortcut method for adding a description as flavor text. --- ---@param parentNode table the html node to add to ---@param description string the description to write out ---@return table the title node added function Infobox.makeFlavorText(parentNode, description) local p = parentNode:tag("p") StyleUtils.styleInfoboxFlavorText(p) p:wikitext(description):done():newline() return p end --- --- A shortcut method for adding a large icon to the header. --- ---@param parentNode table the html node to add to ---@param iconFilename string the icon to use ---@return table the title node added function Infobox.makeTitleIcon(parentNode, iconFilename) local div = parentNode:tag("div") StyleUtils.styleInfoboxTitleIcon(div) div:wikitext("[[File:" .. iconFilename .. "]]"):done():newline() return div end --- --- A shortcut method to make a table row based on the provided check, also --- checks to see whether it needs to add a separator. --- ---@param parentNode table the html node to add to ---@param check boolean whether the row can be added ---@param needsSeparator boolean whether the row needs a separator before it ---@param header string the header of the row ---@param value string the value of the row ---@return boolean whether the next row still needs a separator before it function Infobox.makeInnerRow(parentNode, check, needsSeparator, header, value) local row local nowNeedsSeparator = needsSeparator if check ~= nil and check ~= "" then row = parentNode:tag("tr") nowNeedsSeparator = trySeparator(row, needsSeparator) populateStandardRow(row, header, value) end return nowNeedsSeparator end --- *DEPRECATED* TODO DELETE THIS because we're not doing inline css anymore --- Shortcut method to build a standard row with a header and a value. --- ---@param htmlNode table the MediaWiki HTML entity to build on ---@param cssInline string inline style to apply ---@param header string header text ---@param value string value text ---@return table the same htmlTable function Infobox.buildStandardRow(htmlNode, cssInline, header, value) htmlNode:tag("tr"):css(cssInline) :tag("th"):wikitext(header):done() :tag("td"):wikitext(value):done() :done():newline() return htmlNode end --- --- Lays out an inner, no-styling table to display construction goods with --- their stack sizes. --- --- @param requiredGoods table of required goods, with stack sizes and IDs --- @return string wikimarkup for a table of required goods to insert in other markup function Infobox.writeRequiredGoodsRows(requiredGoods) if not requiredGoods or #requiredGoods == 0 then error("Cannot write content with provided table of required goods.") end local templateArgs = {} for _, requiredGroup in ipairs(requiredGoods) do local stackSize = requiredGroup[INDEX_REQ_STACK_SIZE] local goodName = GoodsData.getGoodNameByID(requiredGroup[INDEX_REQ_GOOD_ID]) templateArgs[goodName] = stackSize end return mw.getCurrentFrame():expandTemplate{ title = CONSTRUCTION_TEMPLATE, args = templateArgs } end --- --- Starts off a new infobox. --- --- @return table the html node created function Infobox.startNewInfobox() local wikiInfobox = mw.html.create("div") StyleUtils.styleInfobox(wikiInfobox) wikiInfobox:newline() return wikiInfobox end --- --- Creates a standard way of displaying the top content of the infobox and --- returns the HTML node. Styles consistently. --- ---@param wikiInfobox table the overall context this is added to ---@return table the html node created function Infobox.startNewHeader(wikiInfobox) local header = wikiInfobox:tag("div") StyleUtils.styleInfoboxHeader(header) header:newline() return header end --- --- Finalizes the standard top content --- ---@param wikiInfobox table the overall context ---@param header table the header content to add to the outer context function Infobox.endInnerTable(wikiInfobox, header) header:done():newline() return wikiInfobox end --- --- Creates a standard way of displaying rows of headers and values and --- returns the HTML node. Styles consistently. --- ---@param wikiInfobox table the overall context this is added to ---@return table the html node created function Infobox.startNewInnerTable(wikiInfobox) local innerTable = wikiInfobox:tag("table") innerTable = StyleUtils.styleInfoboxInnerTable(innerTable) innerTable:newline() return innerTable end --- --- Finalizes the standard inner display of headers and values. --- ---@param wikiInfobox table the overall context ---@param innerTable table the inner content to add to the outer context function Infobox.endInnerTable(wikiInfobox, innerTable) innerTable:done():newline() return wikiInfobox end --endregion return Infobox