Toggle menu
Toggle preferences menu
Toggle personal menu
Not logged in
Your IP address will be publicly visible if you make any edits.

--[=[
This is a module to implement logic for [[Template:Header]] and [[Template:Translation header]]

TODO:
- centuries are defined as starting on XX01, but WS categorizes them as starting on XX00
-- check whether that's a considered policy choice
]=]

require('strict')

local p = {} --p stands for package

local yesno = require('Module:Yesno')
local getArgs = require('Module:Arguments').getArgs
local TableTools = require('Module:TableTools')
local ISO_639_language_name = require('Module:ISO 639').language_name
local parent_links = require('Module:Auto parents')._parent_links

local construct_header = require('Module:Header structure').construct_header
local headerAttributions = require('Module:Header/attribution')
local construct_defaultsort = require('Module:Header/sort')._construct_defaultsort
local construct_year = require('Module:Header/year').construct_year

local current_title = mw.title.getCurrentTitle()

--[=[
Wrap stylesheet in noexport div
]=]
local function get_noexport_stylesheet(template)
	return tostring(mw.html.create('div'):addClass('ws-noexport'):wikitext(mw.getCurrentFrame():extensionTag('templatestyles', '', {src = template .. '/styles.css'})))
end

--[=[
Get badge if any
]=]
local function badge()
	return ''
end

--[=[
Detect explicit formatting in fields like 'section' and 'title'
]=]
local function explicit_formatting(str)
	return str and (string.match(str, "\'\'\'?") or string.match(str, '<%s*/?%s*[iIbB]%s*>'))
	-- add more cases here or come up with a less silly way to do things
end

local function check_non_existent_author_pages(args, categories, checkArgs)
	-- check for cases that aren't supposed to produce a valid link
	
	local param = checkArgs.param
	local tracking_cat = checkArgs.tracking_cat or 'Works with non-existent author pages'
	
	if not param or not args[param] or yesno(args[param .. '-nolink']) then
		return
	end
	
	local lower_arg = string.lower(args[param])
	local attr_data = headerAttributions.attr_data[param] or headerAttributions.attr_data[string.gsub(param, 'section%-', '')]
	if attr_data and attr_data['special_cases'] and attr_data['special_cases'][lower_arg] then
		return
	end
	
	-- check if page exists
	local target = mw.title.makeTitle('Author', args[param])
	-- expensive function!
	if not target or not target.exists then
		table.insert(categories, tracking_cat)
	end
	
	return
end

--[=[
Dont make categories... we are not Wikisource!
]=]

local function construct_categories(args, argsWithBlanks)
	return ""
end

--[=[
For debugging
]=]
--[=[
function p.construct_categories(args)
	return construct_categories(args, args)
end
]=]

--[=[
Assemble the title
]=]
local function header_title(args)
	local title = args.title or ''
	local titleSpan = tostring(mw.html.create('span'):attr('id', 'header-title-text'):wikitext(title))
	
	local year = construct_year(args)
	local attr = headerAttributions.construct_attributions(args)
	local section = headerAttributions.construct_section(args)
	
	if attr ~= '' and title ~= '' then
		attr = tostring(mw.html.create('br'):attr('id', 'header-title-break')) .. attr
	end
	
	return table.concat({titleSpan, year, attr, section})
end

local function get_languages(args, prefix)
	prefix = (prefix and prefix .. '%-') or ''
	
	-- language handling
	local languages = {}
	for k, v in pairs(args) do
		local n
		local nText = string.match(k, '^' .. prefix .. 'language%d*$')
		if nText then
			n = string.gsub(nText, 'language(%d*)$', '%1')
			n = tonumber(n) or 1
			languages[n] = v
		end
	end
	languages = TableTools.compressSparseArray(languages)
	if #languages == 0 then
		return {}
	end
	
	local language_name
	local language_names = {}
	for i, lang in ipairs(languages) do
		local name = ISO_639_language_name(lang)
		if name then
			table.insert(language_names, name)
		end
	end
	
	if #language_names == 1 then
		language_name = language_names[1]
	elseif #language_names > 1 then
		language_name = table.concat(language_names, ', ', 1, #language_names - 1) .. ' and ' .. language_names[#language_names]
	end
	
	return {
		languages = languages,
		language_name = language_name
	}
end

--[=[
[[Template:Header]]
]=]
function p._header(args, argsWithBlanks)
	argsWithBlanks = argsWithBlanks or args
	
	-- aliases
	local dup_cat
	local newArgs = {}
	
	local aliases = {
		['section-author'] = 'contributor',
		['section-translator'] = 'contributing%-translator'
	}
	for k, v in pairs(args) do
		local newkey = string.lower(string.gsub(string.gsub(tostring(k), '_', '-'), ' ', '-'))
		for arg, alias in pairs(aliases) do
			newkey = string.gsub(newkey, alias, arg)
		end
		if newkey ~= tostring(k) then
			if argsWithBlanks[newkey] then
				dup_cat = 'Pages using duplicate arguments in template calls'
			end
			if not args[newkey] then
				newArgs[newkey] = newArgs[newkey] or v
			end
		end
		if newkey == 'testing' or newkey == 'nocat' or newkey == 'nolanguagecat' or newkey == 'language-required' or string.match(newkey, '%-nolink$') then
			newArgs[newkey] = newArgs[newkey] or yesno(v)
		end
	end
	for k, v in pairs(newArgs) do
		args[k] = v
		argsWithBlanks[k] = v
	end
	if dup_cat then
		table.insert(categories, dup_cat)
	end
	
	args.sortkey = args.defaultsort or args.sortkey
	
	-- default values
	args.template_name = args.template_name or 'Header'
	
	if args.testing == nil then
		args.testing = current_title.fullText == 'Template:Header/testcases' or current_title.fullText == 'Template:Translation header/testcases'
	end
	
	-- noyearcat has different behavior for nil and false
	args.noyearcat = args.nocat == true or nil
	
	local language_res = get_languages(args)
	args.languages = language_res.languages
	args.language_name = language_res.language_name
	
	local section_language_res = get_languages(args, 'section')
	args.section_languages = section_language_res.languages
	args.section_language_name = section_language_res.language_name
	
	if not args['interwiki-prefix'] and args['languages'] then
		if #(args['languages']) > 1 then
			args['interwiki-prefix'] = 'mul'
		else
			args['interwiki-prefix'] = args['languages'][1]
		end
	end
	
	-- add values to argsWithBlanks
	for k, v in pairs(args) do
		if not argsWithBlanks[k] then
			argsWithBlanks[k] = v
		end
	end
	
	-- default values for title and section (allow override by setting to blank)
	if not argsWithBlanks['title'] then
		args['title'] = parent_links({})
		argsWithBlanks['title'] = args['title']
	end
	if not argsWithBlanks['section'] and current_title.isSubpage then
		args['section'] = current_title.subpageText
		argsWithBlanks['section'] = args['section']
	end
	
	-- header args
	
	args.pre_container = badge()
	args.header_class = 'wst-header ws-header ws-noexport noprint dynlayout-exempt ' .. (args.header_class or '')
	args.main_class = 'headertemplate'

	-- title
	args.main_title = header_title(args)
	
	-- FIXME: just use Wikidata instead of interwiki links?
	local interwiki = ''
	if args.template_name == 'Translation header' and args['interwiki-prefix'] then
		interwiki = tostring(mw.html.create('span'):addClass('interwiki-info'):attr('id', args['interwiki-prefix']):attr('title', '(original)'))
		if args.original and (args['interwiki-prefix'] == 'ang' or args['interwiki-prefix'] == 'enm' or args['interwiki-prefix'] == 'sco') then
			-- cycle to mul.ws and back around to en.ws
			interwiki = interwiki .. '[[' .. args['interwiki-prefix'] .. ':en:' .. args.original .. ']]'
		elseif args.original then
			-- general interwiki link
			interwiki = interwiki .. '[[' .. args['interwiki-prefix'] .. ':' .. args.original .. ']]'
		end
	end
	
	-- set defaultsort tracking categories
	args.equalsortcat = '[[Category:' .. 'Headers with DefaultSort equal to page title' .. ']]'
	args.diffsortcat = '[[Category:' .. 'Headers applying DefaultSort key' .. ']]'
	
	args.post_notes = table.concat({
		headerAttributions.construct_microformat(args),
		construct_categories(args, argsWithBlanks),
		construct_defaultsort(args),
		interwiki
	})
	
	return get_noexport_stylesheet('Header') .. construct_header(args)
end

function p.header(frame)
	return p._header(
		getArgs(frame),
		getArgs(frame, {removeBlanks = false})
	)
end

--[=[
[[Template:Translation header]]
]=]
function p._translation_header(args, argsWithBlanks)
	argsWithBlanks = argsWithBlanks or args
	
	args.header_class = 'wst-translation-header'
	args.template_name = 'Translation header'
	args.notes_class = 'header-notes'
	args['language-required'] = true
	
	return get_noexport_stylesheet('Translation header') .. p._header(args, argsWithBlanks)
end

function p.translation_header(frame)
	return p._translation_header(
		getArgs(frame),
		getArgs(frame, {removeBlanks = false})
	)
end

return p