Module:InfoboxConceptSection

From No Subject
Jump to navigation Jump to search

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

--------------------------------------------------------------------------------
-- Module:InfoboxConceptSection
--
-- Purpose:
--   Renders a single collapsible section inside Infobox_concept with
--   auto-collapse logic based on semantic row count.
--
-- Design principles:
--   • Zero JS
--   • Server-side decision making
--   • Structural guarantees (no broken DOM)
--   • Future-compatible with Cargo / Lua-generated content
--
-- How auto-collapse works:
--   - Counts occurrences of semantic row markers in provided wikitext:
--       * concept-row
--       * concept-block
--   - If count >= collapse_threshold → section starts collapsed
--
-- Usage (via template):
--   {{Infobox_concept_section
--     | title = Etymology & Translation
--     | collapse_threshold = 3
--     | content = <div class="concept-data-grid"> ... </div>
--   }}
--------------------------------------------------------------------------------

local p = {}

--------------------------------------------------------------------------------
-- Utility: count semantic rows inside section content
--
-- We count *class names*, not DOM nodes:
--   • robust against formatting changes
--   • works for wikitext, Lua output, or Cargo output
--   • ignores empty parameters automatically
--------------------------------------------------------------------------------
local function countRows(wikitext)
	if not wikitext or wikitext == '' then
		return 0
	end

	local rows = 0

	-- Count standard rows
	rows = rows + select(2, wikitext:gsub('concept%-row', ''))

	-- Count block-style entries (long text, interpretations, etc.)
	rows = rows + select(2, wikitext:gsub('concept%-block', ''))

	return rows
end

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

	-- Section title (required)
	local title = args.title or ''

	-- Raw section body (required)
	local content = args.content or ''

	-- Collapse threshold (optional)
	-- If rowCount >= threshold → collapsed
	local threshold = tonumber(args.collapse_threshold) or 999

	-- Optional override flags
	local force_open = args.force_open == 'yes'
	local force_closed = args.force_closed == 'yes'

	-- Count semantic rows
	local rowCount = countRows(content)

	--------------------------------------------------------------------------------
	-- Determine CSS classes
	--------------------------------------------------------------------------------
	local classes = {
		'concept-section',
		'mw-collapsible'
	}

	-- Decide collapsed state
	if force_open then
		-- do nothing; explicitly expanded
	elseif force_closed then
		table.insert(classes, 'mw-collapsed')
	elseif rowCount >= threshold then
		table.insert(classes, 'mw-collapsed')
	end

	--------------------------------------------------------------------------------
	-- Render HTML
	--------------------------------------------------------------------------------
	return string.format([[
<div class="%s">
	<div class="concept-section-header">%s</div>
	<div class="mw-collapsible-content">
		%s
	</div>
</div>
]],
		table.concat(classes, ' '),
		title,
		content
	)
end

return p