Supporting module for Module:Header. View test cases at Template:Header/testcases and Template:Translation header/testcases.


require('strict')

local p = {}

local yesno = require('Module:Yesno')
local TableTools = require('Module:TableTools')
local contrib_types = require('Module:Header/attribution data')

p.attr_data = {}
for k, v in pairs(contrib_types) do
	p.attr_data[v['param_name']] = v
end

local function get_attribution_params(args)
	local all_contributors = {
		title = {},
		section = {}
	}
	
	for k, v in pairs(args) do
		local base_param_name = string.gsub(string.gsub(k, '%-display$', ''), '%-nolink$', '')
		local arg_param_name = string.gsub(base_param_name, '^override%-', '')
		local param_name = string.gsub(arg_param_name, '%d*$', '')
		
		local section_key
		if string.match(arg_param_name, '^section%-') then
			section_key = 'section'
			param_name = string.gsub(param_name, '^section%-', '')
		else
			section_key = 'title'
		end
		
		if p['attr_data'][param_name] then
			local param_name_pattern = '^' .. string.gsub(string.gsub(base_param_name, '%d*$', ''), '%-', '%%%-')
			local nText = string.match(k, param_name_pattern .. '%d*$')
			local nDisplay = string.match(k, param_name_pattern .. '%d*%-display$')
			local nNoLink = string.match(k, param_name_pattern .. '%d*%-nolink$')
			
			local n
			local info
			
			if nText then
				n = string.gsub(nText, param_name_pattern .. '(%d*)$', '%1')
				n = tonumber(n) or 1
				info = 'text'
			elseif nDisplay then
				n = string.gsub(nDisplay, param_name_pattern .. '(%d*)%-display$', '%1')
				n = tonumber(n) or 1
				info = 'display'
			elseif nNoLink then
				n = string.gsub(nNoLink, param_name_pattern .. '(%d*)%-nolink$', '%1')
				n = tonumber(n) or 1
				info = 'nolink'
			end
			
			local index = p['attr_data'][param_name]['index']
			all_contributors[section_key][index] = all_contributors[section_key][index] or {}
			all_contributors[section_key][index]['param_name'] = all_contributors[section_key][index]['param_name'] or param_name
			all_contributors[section_key][index]['arg_param_name'] = all_contributors[section_key][index]['arg_param_name'] or arg_param_name
			all_contributors[section_key][index]['override'] = all_contributors[section_key][index]['override'] or args['override-' .. arg_param_name]
			
			if n and not (args.template_name == 'Translation header' and arg_param_name == 'translator' and info == 'text' and string.lower(v) == 'wikisource') then
				all_contributors[section_key][index]['values'] = all_contributors[section_key][index]['values'] or {}
				all_contributors[section_key][index]['values'][n] = all_contributors[section_key][index]['values'][n] or {}
				all_contributors[section_key][index]['values'][n][info] = all_contributors[section_key][index]['values'][n][info] or v
			end
		end
	end
	
	if args.template_name == 'Translation header' then
		local index = p['attr_data']['translator']['index']
		all_contributors['title'][index] = all_contributors['title'][index] or {}
		all_contributors['title'][index]['param_name'] = all_contributors['title'][index]['param_name'] or 'translator'
		all_contributors['title'][index]['arg_param_name'] = all_contributors['title'][index]['arg_param_name'] or 'translator'
		all_contributors['title'][index]['override'] = all_contributors['title'][index]['override'] or nil
		all_contributors['title'][index]['values'] = all_contributors['title'][index]['values'] or {}
		table.insert(all_contributors['title'][index]['values'], {text = 'wikisource'})
	end
	
	local contributors = {
		title = {},
		section = {}
	}
	for section_key, section_values in pairs(all_contributors) do
		for i, contrib in ipairs(TableTools.compressSparseArray(section_values)) do
			local new_contrib = {}
			for k, v in pairs(TableTools.shallowClone(contrib)) do
				if k == 'values' then
					new_contrib[k] = TableTools.compressSparseArray(v)
				else
					new_contrib[k] = v
				end
			end
			table.insert(contributors[section_key], new_contrib)
		end
	end
	
	return contributors
end

function p.get_attribution_params(args)
	return get_attribution_params(args)
end

local function construct_attribution_span(args)
	local aspan = mw.html.create('span')
		:addClass('vcard')
		:attr('id', 'header-' .. args.span_param_name .. '-text')
		:tag('span'):addClass('fn'):wikitext(args.atext)
	
	return tostring(mw.html.create('span')
		:addClass('contributor-text')
		:wikitext(args.prefix .. tostring(aspan))
	)
end

local function construct_attribution(args)
	local data = args.data
	local param_name = data['param_name']
	local span_param_name = param_name
	local prefix = p['attr_data'][param_name]['prefix'] .. ' '
	
	if data['arg_param_name'] == 'section-author' then
		span_param_name = 'contributor'
	end
	
	if data['arg_param_name'] == 'author' and data['override'] then
		prefix = '' -- legacy parameter
	elseif param_name == 'translator' and args.languages then
		prefix = 'translated from ' .. (args.language_name or 'unrecognized language') .. ' by '
	end
	
	-- override (legacy parameter)
	local atext = data['override']
	if atext then
		if args.template_name == 'Translation header' and param_name == 'translator' then
			atext = atext .. ' and ' .. p['attr_data']['translator']['special_cases']['wikisource']
		end
		return construct_attribution_span({span_param_name = span_param_name, prefix = prefix, atext = atext})
	end
	
	local contributors = {}
	for i, contributor in ipairs(data['values']) do
		local text = contributor['text']
		local display = contributor['display']
		local nolink = yesno(contributor['nolink']) or false
		
		if nolink then
			table.insert(contributors, display or text)
		elseif text then
			local special = false
			for k, v in pairs(p['attr_data'][param_name]['special_cases']) do
				if string.lower(text) == k then
					special = true
					if type(v) == 'function' then
						display = v(display)
					else
						display = v
					end
					break
				end
			end
			
			if not special then
				if not display then
					display = string.gsub(text, ' %(.*%)$', '')
				end
				display = '[[ਲੇਖਕ:' .. text .. '|' .. display .. ']]'
			end
			if display then
				table.insert(contributors, display)
			end
		else
			mw.logObject(contributor)
		end
	end
	
	if #contributors == 0 then
		return nil
	elseif #contributors == 1 then
		atext = contributors[1]
	else
		atext = table.concat(contributors, ', ', 1, #contributors - 1) .. ' and ' .. contributors[#contributors]
	end
	
	-- Temporary check for illustrator in subpages.
	-- TODO: remove once
	--       [[Special:PermanentLink/14324127#Replace illustrator header parameter with section illustrator in subpages of works]]
	--       has been addressed.
	local cat = ''
	if param_name == 'illustrator' and mw.title.getCurrentTitle().isSubpage then
		cat = '[[' .. 'Category:' .. 'Subpages using illustrator parameter' .. ']]'
	end
	
	local s = construct_attribution_span({span_param_name = span_param_name, prefix = prefix, atext = atext})
	
	return s .. cat
end

function p.construct_attributions(args)
	local attributions = {}
	
	local a_args = TableTools.shallowClone(args)
	local attr_params = get_attribution_params(args)['title']
	for i, data in ipairs(attr_params) do
		a_args['data'] = data
		local atext = construct_attribution(a_args)
		if atext then
			table.insert(attributions, atext)
		end
	end
	
	if #attributions == 0 then
		return ''
	end
	
	return table.concat(attributions, ', ')
end

-- section

function p.construct_section(args)
	local section_text = args['section']
	
	if not section_text or section_text == '' then
		return ''
	end
	
	local attributions = {}
	
	local a_args = TableTools.shallowClone(args)
	a_args.languages = a_args.section_languages or a_args.languages
	a_args.language_name = a_args.section_language_name or a_args.language_name
	
	local attr_params = get_attribution_params(args)['section']
	for i, data in ipairs(attr_params) do
		a_args['data'] = data
		local atext = construct_attribution(a_args)
		if atext then
			table.insert(attributions, atext)
		end
	end
	
	if #attributions > 0 then
		local sep = ' '
		if #attributions > 1 then
			sep = '<br/>'
		end
		section_text = section_text .. sep .. table.concat(attributions, ', ')
	end
	
	return tostring(mw.html.create('div')
		:addClass('header-section-text')
		:wikitext(section_text)
	)
end

--[=[
Construct the [[Help:Microformat]] for the page.

This is in the form:
<div id="ws-data" ...>
  <span id="ws-title">Title here...</span>
  ...
<div>
]=]
function p.construct_microformat(args)
	local mf_div =  mw.html.create('div')
		:addClass('ws-noexport')
		:attr('id', 'ws-data')
		:css({speak = 'none'})
	
	-- override to show the microformat
	if yesno(args['show-microformat']) then
		mf_div:addClass('ws-data-show')
	end
	
	-- collect the MF values here
	local mf = {};
	
	-- page ID
	mf['ws-article-id'] = mw.title.getCurrentTitle().id 
	
	-- title
	if args['title'] then
		mf['ws-title'] = args['title']
		
		-- append section if there is one
		if args['section'] then
			mf['ws-title'] = mf['ws-title'] .. " — " .. args['section']
		end
	end
	
	-- year
	mf['ws-year'] = args['year']
	
	-- cover
	mf['ws-cover'] = args['cover']
	
	-- use section values if available, otherwise use work values
	local attr_params = get_attribution_params(args)
	local joined_attr_params = {}
	for i, section_key in ipairs({'section', 'title'}) do
		for i, data in ipairs(attr_params[section_key]) do
			local index = p['attr_data'][data['param_name']]['index']
			joined_attr_params[index] = joined_attr_params[index] or data
		end
	end
	joined_attr_params = TableTools.compressSparseArray(joined_attr_params)
	
	for i, data in ipairs(joined_attr_params) do
		local atext = data['override']
		local ws_translator = args.template_name == 'Translation header' and data['param_name'] == 'translator'
		if atext and ws_translator then
			atext = atext .. ' and Wikisource'
		elseif not atext then
			local attr_text = {}
			for i, values in ipairs(data['values']) do
				local display = values['text']
				local special = false
				if values['text'] then
					for k, v in pairs(p['attr_data'][data['param_name']]['special_cases']) do
						if string.lower(values['text']) == k then
							special = true
							if k == 'anon' or k == 'anonymous' then
								display = 'Anonymous'
							elseif k == 'wikisource' then
								display = 'Wikisource'
							elseif type(v) == 'function' then
								display = v(display)
							else
								display = v
							end
							break
						end
					end
				else
					mw.logObject(values)
				end
				table.insert(attr_text, display)
			end
			if #attr_text == 1 then
				atext = attr_text[1]
			elseif #attr_text > 1 then
				atext = table.concat(attr_text, ', ', 1, #attr_text - 1) .. ' and ' .. attr_text[#attr_text]
			end
		end
		if atext then
			mf['ws-' .. data['param_name']] = atext
		end
	end
	
	for k, v in pairs(mf) do
		mf_div:tag('span'):attr('id', k):wikitext(v)
	end
	
	return tostring(mf_div)
end

return p