Permanently protected module

Module:Header structure

From Wikisource
Jump to navigation Jump to search

--[=[
This is a module to implement logic for header templates
]=]

require('strict')

local p = {} --p stands for package

local getArgs = require('Module:Arguments').getArgs
local plain_sister = require('Module:Plain sister')._plain_sister

-- return true if any value in list is not nil or empty in args
-- (nil means not present; empty string is not nil)
local function has_any_arg(args, list)
	for k, v in pairs(list) do
		if args[v] ~= nil then
			return true
		end
	end
	return false
end

--[=[
Construct the main block
]=]
local function construct_main_block(args, prefix)
	-- header and tracking categories
	local main_div = mw.html.create('div')
		:addClass('wst-header-mainblock')
		:addClass('header-mainblock')
		:addClass(prefix .. '-mainblock')

	-- If an extra main class was provided, add it
	-- TODO: Is this used? Is it needed?
	if args.main_class ~= nil and args.main_class ~= "" then
		main_div:addClass(args.main_class)
	end

	-- If an extra main id was provided, add it
	-- TODO: Is this used? Is it needed?
	if args.main_id then
		main_div:attr('id', args.main_id)
	end

	-- The categories we'll need
	local cats = {}
	
	-- previous and next fields
	local prev_div = ''
	local next_div = ''
	if args.previous or args['next'] then
		prev_div = mw.html.create('div')
			:addClass('wst-header-back')
			:addClass('gen_header_backlink')
			:addClass('searchaux')
			:addClass(prefix .. '-back')
		if args.previous then
			prev_div:node(mw.html.create('div'):addClass('wst-header-back-arrow'):wikitext('←'))
			prev_div:node(mw.html.create('div')
				:attr('id', 'headerprevious')
				:addClass('wst-header-backlink wst-header-previous')
				:wikitext(args.previous)
			)
		else
			prev_div:wikitext('')
		end
		prev_div = tostring(prev_div)
		
		next_div = mw.html.create('div')
			:addClass('wst-header-forward')
			:addClass('gen_header_forelink')
			:addClass('searchaux')
			:addClass(prefix .. '-forward')
		if args['next'] then
			next_div:node(mw.html.create('div')
				:attr('id', 'headernext')
				:addClass('wst-header-forwardlink wst-header-forward')
				:wikitext(args['next'])
			)
			next_div:node(mw.html.create('div'):addClass('wst-header-forward-arrow'):wikitext('→'))
		else
			next_div:wikitext('')
		end
		next_div = tostring(next_div)
	end
	
	-- central cell
	local center_div = mw.html.create('div')
		:addClass('wst-header-central-cell')
		:addClass('gen_header_central_cell')
		:addClass(prefix .. '-central-cell')
	
	-- special case to manage exceptional formatting in disambiguation-like pages; not otherwise documented
	local pretitle = ''
	if args.pretitle then
		local pretitlespan = mw.html.create('span')
			:addClass('wst-header-pretitle')
			:addClass('gen_header_pretitle')
			:wikitext(args.pretitle)
		
		local br = '<br/>'
		if not args.main_title or args.main_title == '' then
			br = ''
		end
		
		pretitle = tostring(pretitlespan) .. br
	end
	
	local titlespan = mw.html.create('span')
		:addClass('wst-header-title')
		:addClass('gen_header_title')
		:addClass(prefix .. '-title')
		:wikitext(args.main_title or '')
	local title = tostring(titlespan)
	
	center_div:wikitext(pretitle .. title)
	center_div = tostring(center_div)
	
	-- assemble
	main_div:wikitext(prev_div .. center_div .. next_div)
	main_div = tostring(main_div)
	
	return main_div .. table.concat(cats)
end

--[=[
Construct the notes block
]=]
local function construct_notes_block(args, prefix)
	local main_div = mw.html.create('div')
		:addClass('wst-header-notes')
		:addClass('header_notes')
		:addClass('searchaux')
		:addClass(prefix .. '-notes')

	-- If an extra main class was provided, add it
	-- TODO: Is this used? Is it needed?
	if args.notes_class ~= nil and args.notes_class ~= "" then
		main_div:addClass(args.notes_class)
	end

	-- If an extra main id was provided, add it
	-- TODO: Is this used? Is it needed?
	if args.notes_id then
		main_div:attr('id', args.notes_id)
	end
	
	-- Left-floated content has to come first, or it may float below the sisters.
	local notes_left_content = ''
	if args.notes_left_content then
		local notes_left_content_div = mw.html.create('div')
			:addClass('wst-header-left')
			:addClass('header_notes_left_content')
			:addClass(prefix .. '-left')
			:wikitext(args.notes_left_content)
		notes_left_content = tostring(notes_left_content_div)
	end
	
	local shortcut = ''
	if args.shortcut then
		shortcut = mw.getCurrentFrame():expandTemplate {
			title = 'shortcut',
			args = {args.shortcut}
		}
	end
	
	local notes_content = ''
	if args.notes then
		args.notes = mw.getCurrentFrame():preprocess(args.notes)
		-- linebreaks are so notes get paragraph formatting
		local notes_content_div = mw.html.create('div')
			:addClass('wst-header-content')
			:addClass('header_notes_content')
			:addClass('wst-header-notes-content')
			:addClass(prefix .. '-notes-content')
			:wikitext('\n' .. args.notes .. '\n')
		notes_content = tostring(notes_content_div)
	end
	
	local wdid = mw.wikibase.getEntityIdForCurrentPage()
	local sister = plain_sister(args)
	
	if not sister and not args.notes and not args.notes_left_content then
		return ''
	end
	
	return tostring(main_div:wikitext(notes_left_content .. (sister or '') .. shortcut .. notes_content))
end

--[=[
Construct header
]=]

function p.construct_header(args)
	-- Make sure the main identifying class for the client template is set
	local prefix = "wst-unknown"
	if args.template ~= nil and args.template ~= "" then
		prefix = "wst-" .. args.template
	end

	local headerContainer = mw.html.create('div')
		:addClass("ws-header")
		:addClass("wst-header-structure")
		:addClass(prefix)

	-- header_class from client modules, class from individual uses
	if args.header_class then
		headerContainer:addClass(args.header_class)
	end
	if args.class then
		headerContainer:addClass(args.class)
	end
	
	headerContainer:wikitext(table.concat({
		(args.pre_main or ''),
		construct_main_block(args, prefix),
		construct_notes_block(args, prefix),
		(args.post_notes or '')
	}))
	
	local stylesheet = mw.getCurrentFrame():extensionTag('templatestyles', '', {src = 'Header structure/styles.css'})
	
	return stylesheet .. (args.pre_container or '') .. tostring(headerContainer)
end

function p.header_structure(frame)
	return p.construct_header(getArgs(frame))
end

return p