Module:Infobox

From Wikitia
Revision as of 11:34, 1 May 2026 by Wikitia (talk | contribs)
Jump to navigation Jump to search

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

local p = {}

local args = {}
local origArgs = {}
local root

local empty_row_categories = {}
local category_in_empty_row_pattern = '%[%[%s*[Cc][Aa][Tt][Ee][Gg][Oo][Rr][Yy]%s*:[^]]*]]'

local has_rows = false

local yesno = require("Module:Yesno")

local lists = {
	plainlist_t = {
		patterns = {
			'^plainlist$',
			'%splainlist$',
			'^plainlist%s',
			'%splainlist%s'
		},
		found = false,
		styles = 'Plainlist/styles.css'
	},
	hlist_t = {
		patterns = {
			'^hlist$',
			'%shlist$',
			'^hlist%s',
			'%shlist%s'
		},
		found = false,
		styles = 'Hlist/styles.css'
	}
}

-- Detect list classes
local function has_list_class(args_to_check)
	for _, list in pairs(lists) do
		if not list.found then
			for _, arg in pairs(args_to_check or {}) do
				for _, pattern in ipairs(list.patterns) do
					if arg and mw.ustring.find(arg, pattern) then
						list.found = true
						break
					end
				end
				if list.found then break end
			end
		end
	end
end

-- Fix nested child boxes
local function fixChildBoxes(sval, tt)
	if not sval or sval == '' then return sval end

	local marker = '<span class="special_infobox_marker">'

	local s = sval

	-- move categories and templatestyles inside rows safely
	local last
	repeat
		last = s
		s = mw.ustring.gsub(
			s,
			'(</[Tt][Rr]%s*>%s*)(%[%[%s*[Cc][Aa][Tt][Ee][Gg][Oo][Rr][Yy]%s*:[^]]*%]%])',
			'%2%1'
		)
		s = mw.ustring.gsub(
			s,
			'(</[Tt][Rr]%s*>%s*)(\127[^\127]*UNIQ%-%-templatestyles%-%x+%-QINU[^\127]*\127)',
			'%2%1'
		)
	until s == last

	return s
end

-- Clean empty tables
local function cleanInfobox()
	root = tostring(root or '')
	if not has_rows then
		root = mw.ustring.gsub(root, '<table[^<>]*>%s*</table>', '')
	end
end

-- Union helper
local function union(t1, t2)
	local vals = {}
	local out = {}

	for _, v in pairs(t1 or {}) do vals[v] = true end
	for _, v in pairs(t2 or {}) do vals[v] = true end

	for k in pairs(vals) do
		table.insert(out, k)
	end

	return out
end

-- Get argument numbers
local function getArgNums(prefix)
	local nums = {}
	for k in pairs(args) do
		local num = tostring(k):match('^' .. prefix .. '([1-9]%d*)$')
		if num then table.insert(nums, tonumber(num)) end
	end
	table.sort(nums)
	return nums
end

-- Add row
local function addRow(rowArgs)
	if rowArgs.header then
		has_rows = true

		root:tag('tr')
			:tag('th')
				:attr('colspan', '2')
				:addClass('infobox-header')
				:wikitext(fixChildBoxes(rowArgs.header, 'th'))
	else
		if rowArgs.data and rowArgs.data ~= '' then
			has_rows = true

			local tr = root:tag('tr')

			if rowArgs.label then
				tr:tag('th')
					:attr('scope', 'row')
					:addClass('infobox-label')
					:wikitext(rowArgs.label)
			end

			local td = tr:tag('td')
				:attr('colspan', rowArgs.label and nil or '2')
				:addClass('infobox-data')
				:wikitext(fixChildBoxes(rowArgs.data, 'td'))
		else
			table.insert(empty_row_categories, rowArgs.data or '')
		end
	end
end

local function renderTitle()
	if not args.title then return end

	root:tag('caption')
		:addClass('infobox-title')
		:wikitext(args.title)

	has_rows = true
end

local function renderRows()
	local rownums = union(getArgNums('header'), getArgNums('data'))
	table.sort(rownums)

	for _, num in ipairs(rownums) do
		addRow({
			header = args['header' .. num],
			label = args['label' .. num],
			data = args['data' .. num]
		})
	end
end

local function structure()
	renderTitle()
	renderRows()
	cleanInfobox()
end

local function _infobox()
	root = mw.html.create('table')
		:addClass('infobox')

	structure()

	return root
end

local function preprocessSingleArg(name)
	if origArgs[name] and origArgs[name] ~= '' then
		args[name] = origArgs[name]
	end
end

local function parseDataParameters()
	for k, v in pairs(origArgs) do
		if v ~= '' then
			args[k] = v
		end
	end
end

function p.infobox(frame)
	origArgs = frame:getParent().args
	parseDataParameters()
	return tostring(_infobox())
end

return p