Toggle menu
Toggle preferences menu
Toggle personal menu
Not logged in
Your IP address will be publicly visible if you make any edits.

Module:Infobox

From Piñata Journal
Revision as of 12:42, 6 February 2026 by Admin Jeremy (talk | contribs)

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

-- Utility: Title Case (capitalize every word)
local function titleCase(s)
	if not s then return nil end
	local lang = mw.language.getContentLanguage()
	s = s:gsub("(%S+)", function(word)
		return lang:ucfirst(word)
	end)
	return s
end


local p = {}

local journalLabels = {
	journal_tip = "Trouble in Paradise",
	journal_pp  = "Pocket Paradise",
	journal_vp1 = "Viva Piñata"
}


-- Utility: trim whitespace
local function trim(s)
	if not s then return nil end
	s = mw.text.trim(s)
	if s == "" then return nil end
	return s
end

-- Utility: escape HTML
local function esc(s)
	return mw.text.nowiki(s)
end

-- Render journal section
local function renderJournal(args, frame)
    local journals = {}

    for k, v in pairs(args) do
        if type(k) == "string" and k:match("^journal_") then
            local val = trim(v)
            if val then
                table.insert(journals, {
                    label = journalLabels[k] or titleCase(
                        k:gsub("^journal_", ""):gsub("_", " ")
                    ),
                    text = val
                })
            end
        end
    end

    if #journals == 0 then
        return nil
    end

    -- SINGLE
    if #journals == 1 then
        return frame:preprocess(journals[1].text)
    end

    -- MULTI (emit wikitext!)
    local out = {}

    for i, j in ipairs(journals) do
        table.insert(out, string.format([[
<details class="vp-journal-block"%s>
<summary>%s</summary>
<div class="vp-journal-text">
%s
</div>
</details>
]], i == 1 and " open" or "", j.label, j.text))
    end

    return frame:preprocess(table.concat(out, "\n"))
end


-- Main renderer
function p.render(frame)
	local args = frame:getParent().args

	local name = trim(args.name) or mw.title.getCurrentTitle().text
	local image = trim(args.image)

	-- reserved params
	local reserved = {
		name = true,
		image = true,
		journal = true
	}
	for k, _ in pairs(args) do
		if type(k) == "string" and k:match("^journal_") then
			reserved[k] = true
		end
	end

	-- build table
	local tableNode = mw.html.create('table')
	tableNode:addClass('infobox')
	tableNode:addClass('infobox-generic')

	-- header
	tableNode:tag('tr')
		:tag('th')
			:attr('colspan', 2)
			:addClass('infobox-header')
			:wikitext(name)

	-- image
	if image then
		tableNode:tag('tr')
			:tag('td')
				:attr('colspan', 2)
				:addClass('infobox-image')
				:wikitext(string.format('[[File:%s|250px|center|%s]]', image, name))
	end

	-- journal
	local journalHTML = renderJournal(args, frame)
	if journalHTML then
		tableNode:tag('tr')
			:tag('td')
				:attr('colspan', 2)
				:addClass('infobox-section')
				:addClass('infobox-journal-cell')
				:node(journalHTML)  -- ← IMPORTANT
	end

	-- rows
	for k, v in pairs(args) do
		if not reserved[k] then
			local val = trim(v)
			if val then
				local row = tableNode:tag('tr')

				row:tag('td')
					:addClass('infobox-section')
					:addClass('infobox-label-cell')
					:tag('span')
						:addClass('infobox-label')
						:wikitext(titleCase(k:gsub("_", " ")))

				row:tag('td')
					:addClass('infobox-section')
					:addClass('infobox-value-cell')
					:wikitext(val)
			end
		end
	end

	return tostring(tableNode)
end


return p