Protected page

Module:Simple navbox

From Uncyclopedia, the content-free encyclopedia
Jump to navigation Jump to search

local p = {}
local getArgs = require('Module:Arguments').getArgs

-- Utilities
local function lc(v)
	return type(v) == 'string' and mw.ustring.lower(v) or v
end

local function hasBackground(s)
	return type(s) == 'string' and (
		s:find('background', 1, true) or
		s:find('background%-color', 1, true)
	)
end

local function hasColor(s)
	if type(s) ~= 'string' then return false end
	s = s:lower()
	return s:match('^%s*color%s*:') or s:match('[;%s]color%s*:')
end

-- Helper to prepend basestyle if present
local function prependBaseStyle(basestyle, otherstyle)
	if not basestyle or basestyle == '' then
		return otherstyle or ''
	end
	if not otherstyle or otherstyle == '' then
		return basestyle
	end
	return basestyle .. ';' .. otherstyle
end

-- Main entry point
function p.main(frame)
	local args = getArgs(frame, {
		removeBlanks = false
	})

	-- Stylesheets (these must be raw strings, not mw.html nodes)
	local stylesheets = {}
	table.insert(stylesheets, frame:extensionTag{ name = 'templatestyles', args = { src = 'Simple navbox/styles.css' } })
	table.insert(stylesheets, frame:extensionTag{ name = 'templatestyles', args = { src = 'Hlist/styles.css' } })

	if args.templatestyles then
		table.insert(stylesheets, frame:extensionTag{ name = 'templatestyles', args = { src = args.templatestyles } })
	end

	-- Get basestyle parameter
	local basestyle = args.basestyle or ''

	-- State logic: collapse/collapsible take precedence over state for legacy compatibility
	local state = lc(args.collapse or args.collapsible or args.state or '')
	
	-- Treat "no" as an alias for "plain"
	if state == 'no' then
		state = 'plain'
	end

	local collapsible = state ~= 'plain'
	local allowOuterImages = not collapsible
	local userSetOuterImage = args['image-outer'] or args.imageouter or args.imageouterleft or args['image-outer-right'] or args.imageouterright or args.imageouter2
	if userSetOuterImage and collapsible then
		mw.addWarning("<code>imageouter</code> type images will not be shown unless <code>|state = plain</code> or <code>|collapse = no</code>.")
	end
	
	-- Outer image args
	local imageOuterLeft = allowOuterImages and (args['image-outer'] or args.imageouter or args.imageouterleft)
	local imageOuterRight = allowOuterImages and (args['image-outer-right'] or args.imageouterright or args.imageouter2)
	local hasOuterImages = imageOuterLeft or imageOuterRight

	-- Inner images
	local imageLeftArg = args.image2 or args.imageleft
	local hasInnerImages = args.image or imageLeftArg
	if hasOuterImages and hasInnerImages then
		mw.addWarning("When <code>|state = plain</code> or <code>|collapse = no</code>, <code>image</code> ''or'' <code>imageouter</code> type images can be used, but ''not'' both.")
	end

	-- Classes
	local bodyclass = args.bodyclass or args.class or ''
	local classes = { 'simple-navbox', bodyclass, 'noprint' }

	if collapsible then
		table.insert(classes, 'NavFrame')
		if state == 'collapsed' or state == 'closed' then
			table.insert(classes, 'NavClosed')
		elseif state == 'expanded' or state == 'uncollapsed' or state == 'open' then
			table.insert(classes, 'NavOpen')
		end
	elseif hasOuterImages then
		table.insert(classes, 'simple-outer')
	end

	-- Add simple-basestyle class if basestyle is present
	if basestyle ~= '' then
		table.insert(classes, 'simple-basestyle')
	end

	-- Check for modified groups early
	if args.group1 and (hasBackground(args.groupstyle) or hasBackground(args.oddgroupstyle) or hasBackground(args.evengroupstyle)) then
		table.insert(classes, 'simple-has-modified-groups')
	end

	-- Body style
	local bodystyle = args.bodystyle or ''

	-- Build the outer div
	local outerDiv = mw.html.create('div')
		:addClass(table.concat(classes, ' '))
		:cssText(bodystyle)

	-- Outer left image
	if imageOuterLeft then
		outerDiv:tag('div')
			:addClass('simple-outer-image')
			:wikitext(imageOuterLeft)
	end

	-- Header (prepend basestyle before headerstyle/titlestyle)
	local headerstyle = prependBaseStyle(basestyle, args.headerstyle or args.titlestyle or '')
	local headerClass = 'simple-header NavHead'
	if headerstyle ~= '' and hasColor(headerstyle) then
		headerClass = headerClass .. ' simple-header-modified'
	end

	local headerContent = {}
	if args.name then
		table.insert(headerContent, frame:expandTemplate{ title = 'simple navbar', args = { args.name } })
	end
	table.insert(headerContent, args.title or 'Default title: add a value for <code>title</code> in the template.')

	outerDiv:tag('div')
		:addClass(headerClass)
		:cssText(headerstyle)
		:wikitext(table.concat(headerContent))

	-- Nav content wrapper
	local navContent = outerDiv:tag('div')
		:addClass('simple-navcontent NavContent')
		:cssText(args.navcontentstyle or '')

	-- Above block (prepend basestyle before abovestyle)
	if args.above then
		local abovestyle = prependBaseStyle(basestyle, args.abovestyle or '')
		navContent:tag('div')
			:addClass('simple-group-above')
			:cssText(abovestyle)
			:wikitext('\n' .. frame:preprocess(args.above) .. '\n')
	end

	-- Flex container
	local imageAlign = lc(args['image-align'] or args.imagealign or '')
	local flex = 'display:flex; flex-flow:row;'
	if imageAlign == 'left' then
		flex = 'display:flex; flex-flow:row-reverse; justify-content:flex-end;'
	end

	local container = navContent:tag('div')
		:addClass('simple-content-container')
		:cssText(flex .. ' ' .. (args.containerstyle or ''))

	-- Left inner image
	local imageLeft = args.image2 or args.imageleft
	local imageValign = args['image-valign'] or args.imagevalign or 'center'
	if not hasOuterImages and imageLeft then
		container:tag('div')
			:addClass('simple-image')
			:css('align-self', imageValign)
			:wikitext(imageLeft)
	end

	-- Content div
	local contentDiv = container:tag('div')
		:addClass('simple-content')
		:addClass(args.listclass or '')
		:cssText(args.contentstyle or '')

	-- Grouped mode
	if args.group1 then
		-- Prepend basestyle to groupstyle base
		local groupstyleBase = prependBaseStyle(basestyle, args.groupstyle or '')
		local oddGStyle = groupstyleBase .. (args.oddgroupstyle and ';' .. args.oddgroupstyle or '')
		local evenGStyle = groupstyleBase .. (args.evengroupstyle and ';' .. args.evengroupstyle or '')
		local oddLStyle = (args.liststyle or '') .. (args.oddliststyle and ';' .. args.oddliststyle or '')
		local evenLStyle = (args.liststyle or '') .. (args.evenliststyle and ';' .. args.evenliststyle or '')

		local tableClass = 'simple-group-container'
		if hasBackground(args.groupstyle) or hasBackground(args.oddgroupstyle) or hasBackground(args.evengroupstyle) then
			tableClass = tableClass .. ' simple-group-modified'
		end
		if hasBackground(args.liststyle) or hasBackground(args.oddliststyle) or hasBackground(args.evenliststyle) then
			tableClass = tableClass .. ' simple-list-modified'
		end
		if hasColor(oddGStyle) or hasColor(evenGStyle) then
			tableClass = tableClass .. ' simple-group-inherit'
		end

		local groupTable = contentDiv:tag('table')
			:addClass(tableClass)
			:cssText(args.tablestyle or '')

		local batchLists, groupIndices = {}, {}
		for i = 1, 50 do
			if args['group' .. i] then
				table.insert(batchLists, args['list' .. i] or '')
				table.insert(groupIndices, i)
			end
		end

		local preprocessedLists = {}
		if #batchLists > 0 then
			local sep = '@@SIMPLE_SEPARATOR@@'
			local concatenated = table.concat(batchLists, sep)
			local processed = frame:preprocess(concatenated)
			for part in mw.ustring.gmatch(processed, '(.-)' .. sep) do
				table.insert(preprocessedLists, part)
			end
			if #preprocessedLists < #batchLists then
				table.insert(preprocessedLists, mw.ustring.match(processed, '.*' .. sep .. '(.*)') or batchLists[#batchLists])
			end
		end

		for idx, i in ipairs(groupIndices) do
			local group = args['group' .. i]
			local listContent = preprocessedLists[idx] or ''
			local odd = (i % 2 == 1)
			local gstyle = (odd and oddGStyle or evenGStyle) .. ';' .. (args['group' .. i .. 'style'] or '')
			local lstyle = (odd and oddLStyle or evenLStyle) .. ';' .. (args['list' .. i .. 'style'] or '')

			local row = groupTable:tag('tr')
				:addClass('simple-group-row')
				:cssText(args.rowstyle or '')

			row:tag('td')
				:addClass('simple-group')
				:cssText(gstyle)
				:wikitext(group)

			row:tag('td')
				:addClass('simple-list')
				:cssText(lstyle)
				:wikitext('\n' .. listContent .. '\n')
		end
	else
		local list = args.list or args.list1 or 'Error: <code>list</code> is empty!'
		if list ~= '' then
			list = frame:preprocess(list)
		end
		contentDiv:tag('div')
			:addClass('simple-list simple-list-only')
			:cssText(args.liststyle or '')
			:wikitext('\n' .. list .. '\n')
	end

	-- Right inner image
	if not hasOuterImages and args.image then
		container:tag('div')
			:addClass('simple-image')
			:css('align-self', imageValign)
			:wikitext(args.image)
	end

	-- Below block (prepend basestyle before belowstyle)
	if args.below then
		local belowstyle = prependBaseStyle(basestyle, args.belowstyle or args.abovestyle or '')
		navContent:tag('div')
			:addClass('simple-group-above simple-group-below')
			:cssText(belowstyle)
			:wikitext('\n' .. frame:preprocess(args.below) .. '\n')
	end

	-- Outer right image
	if imageOuterRight then
		outerDiv:tag('div')
			:addClass('simple-outer-imageright')
			:wikitext(imageOuterRight)
	end

	-- Combine stylesheets with the HTML structure
	return table.concat(stylesheets) .. tostring(outerDiv)
end

return p