Module:Infobox/sandbox

From Progressbar95 Wiki
Revision as of 16:42, 26 April 2024 by Xemonix (talk | contribs) (simplified version test)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

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

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

--[[ UTILS ]]--

-- Returns a table containing the numbers of the arguments that exist
-- for the specified prefix. For example, if the prefix was 'data', and
-- 'data1', 'data2', and 'data5' exist, it would return {1, 2, 5}.
local function getArgNums(prefix)
	local nums = {}
	for k, v 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

--[[ RENDERING ]]--

local function renderTitle()
	local titleObject = mw.title.getCurrentTitle()
	local title = args.title or titleObject.baseText
	
	root
		:tag('caption')
			:addClass('pbwiki-header')
			:addClass('infobox-title')
			:addClass(args.titleclass)
			:cssText(args.titlestyle)
			:wikitext(title)
end

local function addImageRow(imageArgs)
	if imageArgs.data then
		local row = root:tag('tr')
		row:addClass(imageArgs.rowclass)

		local dataCell = row:tag('td')
		dataCell
			:attr('colspan', '2')
			:addClass('infobox-image')
			:addClass(imageArgs.class)
			:cssText(imageArgs.datastyle)
			:wikitext(imageArgs.data)
	end
end

local function renderImages()
	if args.image then
		args.image1 = args.image
	end
	if args.caption then
		args.caption1 = args.caption
	end

	local imagenums = getArgNums('image')
	for k, num in ipairs(imagenums) do
		local caption = args['caption' .. tostring(num)]
		local data = mw.html.create():wikitext(args['image' .. tostring(num)])
		if caption then
			data
				:tag('div')
					:addClass('infobox-caption')
					:cssText(args.captionstyle)
					:wikitext(caption)
		end
		addImageRow({
			data = tostring(data),
			datastyle = args.imagestyle,
			class = args.imageclass,
			rowclass = args['imagerowclass' .. tostring(num)]
		})
	end
end

-- Adds a row to the infobox, with either a header cell
-- or a label/data cell combination.
local function addRow(rowArgs)
	if rowArgs.header and rowArgs.header ~= '_BLANK_' then
		root
			:tag('tr')
				:addClass(rowArgs.rowclass)
				:cssText(rowArgs.rowstyle)
				:tag('th')
					:attr('colspan', '2')
					:addClass('infobox-header')
					:addClass(rowArgs.class)
					:addClass(args.headerclass)
					:cssText(args.headerstyle)
					:cssText(rowArgs.rowcellstyle)
					:wikitext(rowArgs.header)
	elseif rowArgs.data then
		local row = root:tag('tr')
		row:addClass(rowArgs.rowclass)
		row:cssText(rowArgs.rowstyle)
		if rowArgs.label then
			row
				:tag('th')
					:attr('scope', 'row')
					:addClass('infobox-label')
					:cssText(args.labelstyle)
					:cssText(rowArgs.rowcellstyle)
					:wikitext(rowArgs.label)
					:done()
		end

		local dataCell = row:tag('td')
		dataCell
			:attr('colspan', not rowArgs.label and '2' or nil)
			:addClass(not rowArgs.label and 'infobox-full-data' or 'infobox-data')
			:addClass(rowArgs.class)
			:cssText(rowArgs.datastyle)
			:cssText(rowArgs.rowcellstyle)
			:wikitext(fixChildBoxes(rowArgs.data, 'td'))
	end
end

-- Gets the union of the header and data argument numbers,
-- and renders them all in order
local function renderRows()
	local rownums = union(getArgNums('header'), getArgNums('data'))
	table.sort(rownums)
	for k, num in ipairs(rownums) do
		addRow({
			header = args['header' .. tostring(num)],
			label = args['label' .. tostring(num)],
			data = args['data' .. tostring(num)],
			datastyle = args.datastyle,
			class = args['class' .. tostring(num)],
			rowclass = args['rowclass' .. tostring(num)],
			rowstyle = args['rowstyle' .. tostring(num)],
		})
	end
end

local function renderFooter()
	if not args.footer then return end
	
	root
		:tag('tr')
			:tag('td')
				:attr('colspan', '2')
				:addClass('infobox-footer')
				:addClass(args.footerclass)
				:cssText(args.footerstyle)
				:wikitext(args.footer)
end

-- Render tracking categories. args.nocat == turns off tracking categories.
local function renderTrackingCategories()
	if args.nocat == 'yes' then return end

	if #(getArgNums('data')) == 0 and mw.title.getCurrentTitle().namespace == 0 then
		root:wikitext('[[Category:Articles using infobox templates with no data rows]]')
	end
end

--[=[
Loads the templatestyles for the infobox.

TODO: FINISH loading base templatestyles here rather than in
MediaWiki:Common.css.

]=]
local function loadTemplateStyles()
	local frame = mw.getCurrentFrame()
	
	-- See function description
	local base_templatestyles = frame:extensionTag{
		name = 'templatestyles', args = { src = 'Module:Infobox/sandbox/styles.css' }
	}

	local templatestyles = ''
	if args['templatestyles'] then
		templatestyles = frame:extensionTag{
			name = 'templatestyles', args = { src = args['templatestyles'] }
		}
	end
	
	return table.concat({
		base_templatestyles,
		templatestyles,
	})
end

--[[ ARGUMENTS PROCESSING ]]--

-- If the argument exists, add it to the argument table.
-- Blank arguments are treated as nil to match the behaviour of ParserFunctions.
local function preprocessSingleArg(argName)
	if origArgs[argName] then
		args[argName] = origArgs[argName]
	end
end

local function parseDataParameters()
	preprocessSingleArg('bodyclass')
	preprocessSingleArg('bodystyle')
	preprocessSingleArg('title')
	preprocessSingleArg('titleclass')
	preprocessSingleArg('titlestyle')
	preprocessArgs({
		{prefix = 'image', depend = {'caption'}}
	}, 10)
	preprocessSingleArg('captionstyle')
	preprocessSingleArg('imagestyle')
	preprocessSingleArg('imageclass')
	preprocessArgs({
		{prefix = 'header'},
		{prefix = 'data', depend = {'label'}},
		{prefix = 'rowclass'},
		{prefix = 'rowstyle'},
		{prefix = 'class'}
	}, 50)
	preprocessSingleArg('headerclass')
	preprocessSingleArg('headerstyle')
	preprocessSingleArg('labelstyle')
	preprocessSingleArg('datastyle')
	preprocessSingleArg('footer')
	preprocessSingleArg('footerclass')
	preprocessSingleArg('footerstyle')
	preprocessSingleArg('name')
	preprocessSingleArg('nocat')
	preprocessSingleArg('templatestyles')
end

--[[ MAIN ]]--

function p.infobox(frame)
	origArgs = require('Module:ProcessArgs').merge( true )
	parseDataParameters()
	
	root = mw.html.create('table')
	root
		:addClass('infobox')
		:addClass(args.bodyclass)
		:cssText(args.bodystyle)

	renderTitle()
	renderImages()
	renderRows()
	renderFooter()
	renderTrackingCategories()
	
	return loadTemplateStyles() .. root
end

return p