Module:Building infobox: Difference between revisions

From Beyond These Stars Official Wiki
m WIP building infobox
adds generic category too
 
(13 intermediate revisions by the same user not shown)
Line 1: Line 1:
--[[
Test in Scribunto console with:
=p.render({ args = { page_name = "Ore Smelter" } })
]]--
local p = {}
local p = {}






local BuildingDataModule = require("Module:Building_data")
local Building_Data_Module = require("Module:Building_data")
local Resource_Data_Module = require("Module:Resource_data")




Line 9: Line 14:
--#region html building helper functions
--#region html building helper functions


---@diagnostic disable-next-line: duplicate-doc-alias
---@alias HtmlNode table
---@alias HtmlNode table


local INFOBOX_CLASS = "bts-infobox-building"
local INFOBOX_CLASS = "bts-infobox-building"
local HEADER_CLASS = INFOBOX_CLASS .. "-header"
local HEADER_CLASS = INFOBOX_CLASS .. "-header"
local HEADER_ICON_CLASS = HEADER_CLASS .. "-icon"
local TITLE_CLASS = INFOBOX_CLASS .. "-title"
local SUBTITLE_CLASS = INFOBOX_CLASS .. "-subtitle"
local SUBHEADER_CLASS = INFOBOX_CLASS .. "-subheader"
local DESCRIPTION_CLASS = INFOBOX_CLASS .. "-description"
local DESCRIPTION_CLASS = INFOBOX_CLASS .. "-description"
local TECH_TREE_CLASS = INFOBOX_CLASS .. "-techtree"
local CONSTRUCTION_CLASS = INFOBOX_CLASS .. "-construction"
local CONSTRUCTION_CLASS = INFOBOX_CLASS .. "-construction"
local CONSTRUCTION_TABLE_CLASS = CONSTRUCTION_CLASS .. "-table"
local CONSTRUCTION_TABLE_CLASS = CONSTRUCTION_CLASS .. "-table"
local RESOURCE_ICON_CLASS = "bts-resource-icon"
local LARGE_ICON_SIZE = "168px"
local MEDIUM_ICON_SIZE = "96px"
local SMALL_ICON_SIZE = "32px"
local TASKS_CLASS = INFOBOX_CLASS .. "-tasks"
local TASKS_CLASS = INFOBOX_CLASS .. "-tasks"
local TASKS_TABLE_CLASS = TASKS_CLASS .. "-table"
--- Renders wikitext for the building's icon.
---@param building Building
---@return string wikitext
local function render_icon_markup(building)
  local icon_filename
  local size = LARGE_ICON_SIZE
  if building.portrait_icon then
    icon_filename = building.portrait_icon .. ".png"
  elseif building.icon then
    icon_filename = building.icon .. ".png"
    size = MEDIUM_ICON_SIZE
  else
    return ""
  end
  local image_markup = "[[File:" .. icon_filename .. "|".. size .. "|" .. building.name .. "|link=]]"
  return image_markup
end


--- Adds the header of the infobox to the provided html node.
--- Adds the header of the infobox to the provided html node.
---@param div HtmlNode enclosing infobox div
---@param div HtmlNode enclosing infobox div
---@param building BuildingRecord
---@param building Building
local function build_header(div, building)
local function add_header(div, building)
   local header = div:tag("div"):addClass(HEADER_CLASS)
   local header = div:tag("div"):addClass(HEADER_CLASS)
   header:tag("h2"):wikitext(building.display_name):done()
   header:tag("div"):addClass(TITLE_CLASS):wikitext(building.display_name)
   header:tag("h3"):wikitext(building.category):done()
  header:tag("div"):addClass(HEADER_ICON_CLASS):wikitext(render_icon_markup(building))
   if building.category and building.category ~= "" then
    header:tag("div"):addClass(SUBTITLE_CLASS):wikitext(building.category .. " Building")
  end
end
end


--- Adds the building's description to the provided html node.
--- Adds the building's description to the provided html node.
---@param div HtmlNode enclosing infobox div
---@param div HtmlNode enclosing infobox div
---@param building BuildingRecord
---@param building Building
local function build_description(div, building)
local function add_description(div, building)
   local description = div:tag("div"):addClass(DESCRIPTION_CLASS)
   local inner_div = div:tag("div"):addClass(DESCRIPTION_CLASS)
   building.description = building.description:gsub("<hb>", ""):gsub("</hb>", "")
   local description = building.description:gsub("<hb>", ""):gsub("</hb>", "")
   description:tag("p"):wikitext(building.description):done()
   description = description:gsub("\n", "<br />")
   return description
  inner_div:wikitext(description)
  return inner_div
end
 
 
 
--- Adds a subheader to the provided html node.
---@param div HtmlNode enclosing infobox div
---@param text string
local function add_subheader(div, text)
   div:tag("div"):addClass(SUBHEADER_CLASS):wikitext(text)
end
end


--- Adds the construction resources to the provided html table row.
 
---@param tr HtmlNode table row
 
---@param building BuildingRecord
--- Adds the building's tech prerequisite to the provided html node.
local function add_construction_resource_row(tr, building)
---@param div HtmlNode enclosing infobox div
   for _, pair in ipairs(building.construction_resources) do
---@param building Building
    if pair.name and pair.name ~= "" and pair.amount and pair.amount ~= "" then
local function add_tech_prerequisite(div, building)
      tr:tag("td"):wikitext(pair.name):done()
   local inner_div = div:tag("div"):addClass(TECH_TREE_CLASS)
     end
  local check_icon = "[[File:UI teal open checkmark.png|x16px|link=]]"
  local link_markup = check_icon .. " [[" .. Building_Data_Module.get_name_by_id(building.tech_tree_previous) .. "]]"
  inner_div:tag("div"):wikitext(link_markup)
end
 
 
 
--- Adds an icon for a resource to the provided html table row.
---@param tr HtmlNode tr
---@param resource Resource
local function add_resource_icon(tr, resource)
  local icon_markup = ""
  if resource and resource.icon then
    local file_name = "File:" .. resource.icon .. ".png"
    local icon_size = "x" .. SMALL_ICON_SIZE
    local name = resource.display_name
    local link_attr = "link=" .. resource.display_name
     icon_markup = "[[" .. file_name .. "|" .. icon_size .. "|" .. name .. "|" .. link_attr .. "]]"
   end
   end
  tr:tag("td"):tag("span"):addClass(RESOURCE_ICON_CLASS)
      :wikitext(icon_markup)
end
end


--- Adds the construction amount to the provided html table row.
--- Adds a link for a resource to the provided html table row.
--- @param tr HtmlNode table row
---@param tr HtmlNode tr
--- @param building BuildingRecord
---@param resource Resource
local function add_construction_amount(tr, building)
local function add_resource_link(tr, resource)
   for _, pair in ipairs(building.construction_resources) do
   local link_markup = ""
    if pair.name and pair.name ~= "" and pair.amount and pair.amount ~= "" then
  if resource and resource.display_name then
      tr:tag("td"):wikitext(pair.amount):done()
    link_markup = "[[" .. resource.display_name .. "]]"
    end
   end
   end
  tr:tag("td"):wikitext(link_markup)
end
end


--- Lays out the construction resources in the provided html node.
--- Lays out the construction resources in the provided html node.
---@param div HtmlNode enclosing infobox div
---@param div HtmlNode enclosing infobox div
---@param building BuildingRecord
---@param building Building
local function build_construction(div, building)
local function add_construction(div, building)
  if not building.construction_resources or building.construction_resources == {} then return end
   local tbl = div:tag("div"):addClass(CONSTRUCTION_CLASS)
   local table = div:tag("div"):addClass(CONSTRUCTION_CLASS):tag("table"):addClass(CONSTRUCTION_TABLE_CLASS)
      :tag("table"):addClass(CONSTRUCTION_TABLE_CLASS)
   local tr_names = table:tag("tr")
   for _, pair in ipairs(building.construction_resources) do
  add_construction_resource_row(tr_names, building)
    local tr = tbl:tag("tr")
  tr_names:done()
    tr:tag("td"):wikitext(pair.amount)
  local tr_amounts = table:tag("tr")
    local resource = Resource_Data_Module.get_resource(pair.name)
  add_construction_amount(tr_amounts, building)
    add_resource_icon(tr, resource)
  tr_amounts:done()
    add_resource_link(tr, resource)
   return table
   end
end
end


--- Lays out the building's tasks in the provided html node.
--- Lays out the building's tasks in the provided html node.
---@param div HtmlNode enclosing infobox div
---@param div HtmlNode enclosing infobox div
---@param building BuildingRecord
---@param building Building
local function build_tasks(div, building)
local function add_tasks(div, building)
   if not building.tasks or building.tasks == {} then return end
   local tbl = div:tag("div"):addClass(TASKS_CLASS)
  local section = div:tag("div"):addClass(TASKS_CLASS)
      :tag("table"):addClass(TASKS_TABLE_CLASS)
  tbl:tag("tr")
          :tag("th"):wikitext("Task"):done()
          :tag("th"):wikitext("(Time)"):done()
      :done()
  for _, task in ipairs(building.tasks) do
    local tr = tbl:tag("tr")
    tr:tag("td"):wikitext(task.task_name)
    tr:tag("td"):wikitext("(" .. task.time .. "s)")
  end
end
end


--- Builds the infobox wikitext and html for the given building.
--- Builds the infobox wikitext and html for the given building.
---@param building BuildingRecord
---@param building Building
---@return string wikitext
---@return string wikitext
local function build_infobox(building)
local function build_infobox(building)
   ---@type HtmlNode
   ---@type HtmlNode
   local html = mw.html.create("div")
   local div = mw.html.create("div")
   html:addClass(INFOBOX_CLASS)
   div:addClass(INFOBOX_CLASS)
   build_header(html, building)
   add_header(div, building)
   build_description(html, building)
  if building.description and building.description ~= "" then
   build_construction(html, building)
    add_description(div, building)
   build_tasks(html, building)
   end
   return tostring(html)
  if building.tech_tree_previous and building.tech_tree_previous ~= "" then
    add_subheader(div, "Tech tree prerequisite")
    add_tech_prerequisite(div, building)
   end
  if building.construction_resources and #building.construction_resources > 0 then
    add_subheader(div, "Construction costs")
    add_construction(div, building)
   end
  if building.tasks and #building.tasks > 0 then
    add_subheader(div, "Work")
    add_tasks(div, building)
  end
   return tostring(div)
end
 
 
 
--- Appends the wiki category to the provided wikitext.
---@param wikitext string
---@param building Building
---@return string wikitext
local function append_wiki_category(wikitext, building)
  wikitext = wikitext .. "\n[[Category:Buildings]]"
  if building.category and building.category ~= "" then
    wikitext = wikitext .. "\n[[Category:" .. building.category .. " Buildings]]"
  end
  return wikitext
end
end


--#endregion
--#endregion
Line 103: Line 221:
--- template); falls back to the current page title.
--- template); falls back to the current page title.
---@param frame table Scribunto frame from `#invoke`.
---@param frame table Scribunto frame from `#invoke`.
---@return string|nil Infobox wikitext, or nil if no cargo row exists.
---@return string wikitext Infobox code or empty string if no building exists.
function p.render(frame)
function p.render(frame)
   local args = frame.args or {}
   local args = frame.args or {}
   ---@type string
   ---@type string
   local name = args[1] or args.page_name or mw.title.getCurrentTitle().fullText
   local name = args[1] or args.page_name or mw.title.getCurrentTitle().fullText
   local building = BuildingDataModule.get_building(name)
   local building = Building_Data_Module.get_building(name)
   if not building then return nil end
   if not building then return "" end
   local wikitext = build_infobox(building)
   local wikitext = build_infobox(building)
  wikitext = append_wiki_category(wikitext, building)
   return wikitext
   return wikitext
end
end

Latest revision as of 00:09, 11 October 2026

Documentation for this module may be created at Module:Building infobox/doc

--[[ 
Test in Scribunto console with:
=p.render({ args = { page_name = "Ore Smelter" } })
]]--
local p = {}



local Building_Data_Module = require("Module:Building_data")
local Resource_Data_Module = require("Module:Resource_data")



--#region html building helper functions

---@diagnostic disable-next-line: duplicate-doc-alias
---@alias HtmlNode table

local INFOBOX_CLASS = "bts-infobox-building"
local HEADER_CLASS = INFOBOX_CLASS .. "-header"
local HEADER_ICON_CLASS = HEADER_CLASS .. "-icon"

local TITLE_CLASS = INFOBOX_CLASS .. "-title"
local SUBTITLE_CLASS = INFOBOX_CLASS .. "-subtitle"
local SUBHEADER_CLASS = INFOBOX_CLASS .. "-subheader"

local DESCRIPTION_CLASS = INFOBOX_CLASS .. "-description"

local TECH_TREE_CLASS = INFOBOX_CLASS .. "-techtree"

local CONSTRUCTION_CLASS = INFOBOX_CLASS .. "-construction"
local CONSTRUCTION_TABLE_CLASS = CONSTRUCTION_CLASS .. "-table"

local RESOURCE_ICON_CLASS = "bts-resource-icon"

local LARGE_ICON_SIZE = "168px"
local MEDIUM_ICON_SIZE = "96px"
local SMALL_ICON_SIZE = "32px"

local TASKS_CLASS = INFOBOX_CLASS .. "-tasks"
local TASKS_TABLE_CLASS = TASKS_CLASS .. "-table"



--- Renders wikitext for the building's icon.
---@param building Building
---@return string wikitext
local function render_icon_markup(building)
  local icon_filename
  local size = LARGE_ICON_SIZE
  if building.portrait_icon then
    icon_filename = building.portrait_icon .. ".png"
  elseif building.icon then
    icon_filename = building.icon .. ".png"
    size = MEDIUM_ICON_SIZE
  else
    return ""
  end
  local image_markup = "[[File:" .. icon_filename .. "|".. size .. "|" .. building.name .. "|link=]]"
  return image_markup
end

--- Adds the header of the infobox to the provided html node.
---@param div HtmlNode enclosing infobox div
---@param building Building
local function add_header(div, building)
  local header = div:tag("div"):addClass(HEADER_CLASS)
  header:tag("div"):addClass(TITLE_CLASS):wikitext(building.display_name)
  header:tag("div"):addClass(HEADER_ICON_CLASS):wikitext(render_icon_markup(building))
  if building.category and building.category ~= "" then
    header:tag("div"):addClass(SUBTITLE_CLASS):wikitext(building.category .. " Building")
  end
end



--- Adds the building's description to the provided html node.
---@param div HtmlNode enclosing infobox div
---@param building Building
local function add_description(div, building)
  local inner_div = div:tag("div"):addClass(DESCRIPTION_CLASS)
  local description = building.description:gsub("<hb>", ""):gsub("</hb>", "")
  description = description:gsub("\n", "<br />")
  inner_div:wikitext(description)
  return inner_div
end



--- Adds a subheader to the provided html node.
---@param div HtmlNode enclosing infobox div
---@param text string
local function add_subheader(div, text)
  div:tag("div"):addClass(SUBHEADER_CLASS):wikitext(text)
end



--- Adds the building's tech prerequisite to the provided html node.
---@param div HtmlNode enclosing infobox div
---@param building Building
local function add_tech_prerequisite(div, building)
  local inner_div = div:tag("div"):addClass(TECH_TREE_CLASS)
  local check_icon = "[[File:UI teal open checkmark.png|x16px|link=]]"
  local link_markup = check_icon .. " [[" .. Building_Data_Module.get_name_by_id(building.tech_tree_previous) .. "]]"
  inner_div:tag("div"):wikitext(link_markup)
end



--- Adds an icon for a resource to the provided html table row.
---@param tr HtmlNode tr
---@param resource Resource
local function add_resource_icon(tr, resource)
  local icon_markup = ""
  if resource and resource.icon then
    local file_name = "File:" .. resource.icon .. ".png"
    local icon_size = "x" .. SMALL_ICON_SIZE
    local name = resource.display_name
    local link_attr = "link=" .. resource.display_name
    icon_markup = "[[" .. file_name .. "|" .. icon_size .. "|" .. name .. "|" .. link_attr .. "]]"
  end
  tr:tag("td"):tag("span"):addClass(RESOURCE_ICON_CLASS)
      :wikitext(icon_markup)
end

--- Adds a link for a resource to the provided html table row.
---@param tr HtmlNode tr
---@param resource Resource
local function add_resource_link(tr, resource)
  local link_markup = ""
  if resource and resource.display_name then
    link_markup = "[[" .. resource.display_name .. "]]"
  end
  tr:tag("td"):wikitext(link_markup)
end

--- Lays out the construction resources in the provided html node.
---@param div HtmlNode enclosing infobox div
---@param building Building
local function add_construction(div, building)
  local tbl = div:tag("div"):addClass(CONSTRUCTION_CLASS)
      :tag("table"):addClass(CONSTRUCTION_TABLE_CLASS)
  for _, pair in ipairs(building.construction_resources) do
    local tr = tbl:tag("tr")
    tr:tag("td"):wikitext(pair.amount)
    local resource = Resource_Data_Module.get_resource(pair.name)
    add_resource_icon(tr, resource)
    add_resource_link(tr, resource)
  end
end



--- Lays out the building's tasks in the provided html node.
---@param div HtmlNode enclosing infobox div
---@param building Building
local function add_tasks(div, building)
  local tbl = div:tag("div"):addClass(TASKS_CLASS)
      :tag("table"):addClass(TASKS_TABLE_CLASS)
  tbl:tag("tr")
          :tag("th"):wikitext("Task"):done()
          :tag("th"):wikitext("(Time)"):done()
      :done()
  for _, task in ipairs(building.tasks) do
    local tr = tbl:tag("tr")
    tr:tag("td"):wikitext(task.task_name)
    tr:tag("td"):wikitext("(" .. task.time .. "s)")
  end
end



--- Builds the infobox wikitext and html for the given building.
---@param building Building
---@return string wikitext
local function build_infobox(building)
  ---@type HtmlNode
  local div = mw.html.create("div")
  div:addClass(INFOBOX_CLASS)
  add_header(div, building)
  if building.description and building.description ~= "" then
    add_description(div, building)
  end
  if building.tech_tree_previous and building.tech_tree_previous ~= "" then
    add_subheader(div, "Tech tree prerequisite")
    add_tech_prerequisite(div, building)
  end
  if building.construction_resources and #building.construction_resources > 0 then
    add_subheader(div, "Construction costs")
    add_construction(div, building)
  end
  if building.tasks and #building.tasks > 0 then
    add_subheader(div, "Work")
    add_tasks(div, building)
  end
  return tostring(div)
end



--- Appends the wiki category to the provided wikitext.
---@param wikitext string
---@param building Building
---@return string wikitext
local function append_wiki_category(wikitext, building)
  wikitext = wikitext .. "\n[[Category:Buildings]]"
  if building.category and building.category ~= "" then
    wikitext = wikitext .. "\n[[Category:" .. building.category .. " Buildings]]"
  end
  return wikitext
end



--#endregion



--- `#invoke` entry point. Reads `page_name` from invoke args (not the parent 
--- template); falls back to the current page title.
---@param frame table Scribunto frame from `#invoke`.
---@return string wikitext Infobox code or empty string if no building exists.
function p.render(frame)
  local args = frame.args or {}
  ---@type string
  local name = args[1] or args.page_name or mw.title.getCurrentTitle().fullText
  local building = Building_Data_Module.get_building(name)
  if not building then return "" end
  local wikitext = build_infobox(building)
  wikitext = append_wiki_category(wikitext, building)
  return wikitext
end



return p