Module:Cs1 documentation support

From All Skies Encyclopaedia
Revision as of 21:15, 7 April 2020 by imported>Trappist the monk

Documentation for this module may be created at Module:Cs1 documentation support/doc

require('Module:No globals');

local cfg = mw.loadData ('Module:Citation/CS1/Configuration');					-- load the configuration module

local exclusion_lists = {
	['cite book'] = {
		['agency'] = true,
		['air-date'] = true,
		['arxiv'] = true,
		['biorxiv'] = true,
		['citeseerx'] = true,
		['class'] = true,
		['conference'] = true,
		['conference-format'] = true,
		['conference-url'] = true,
		['degree'] = true,
		['department'] = true,
		['display-interviewers'] = true,
		['docket'] = true,
		['episode'] = true,
		['interviewer#'] = true,
		['interviewer-first#'] = true,
		['interviewer-link#'] = true,
		['interviewer-mask#'] = true,
		['ismn'] = true,
		['issn'] = true,
		['issue'] = true,
		['jfm'] = true,
		['journal'] = true,
		['jstor'] = true,
		['mailinglist'] = true,
		['message-id'] = true,
		['minutes'] = true,
		['MR'] = true,
		['network'] = true,
		['number'] = true,
		['RFC'] = true,
		['script-journal'] = true,
		['season'] = true,
		['section'] = true,
		['sections'] = true,
		['series-link'] = true,
		['series-number'] = true,
		['series-separator'] = true,
		['sheet'] = true,
		['sheets'] = true,
		['SSRN'] = true,
		['station'] = true,
		['time'] = true,
		['time-caption'] = true,
		['trans-article'] = true,
		['trans-journal'] = true,
		['transcript'] = true,
		['transcript-format'] = true,
		['transcript-url'] = true,
		['ZBL'] = true,
		},
	['cite journal'] = {
		['agency'] = true,
		['air-date'] = true,
		['book-title'] = true,
		['chapter'] = true,
		['chapter-format'] = true,
		['chapter-url'] = true,
		['chapter-url-access'] = true,
		['class'] = true,
		['conference'] = true,
		['conference-format'] = true,
		['conference-url'] = true,
		['contribution'] = true,
		['contributor#'] = true,
		['contributor-first#'] = true,
		['contributor-link#'] = true,
		['contributor-mask#'] = true,
		['degree'] = true,
		['department'] = true,
		['display-interviewers'] = true,
		['docket'] = true,
		['edition'] = true,
		['editor#'] = true,
		['editor-first#'] = true,
		['editor-link#'] = true,
		['editor-mask#'] = true,
		['editors'] = true,
		['encyclopedia'] = true,
		['episode'] = true,
		['ignore-isbn-error'] = true,
		['interviewer#'] = true,
		['interviewer-first#'] = true,
		['interviewer-link#'] = true,
		['interviewer-mask#'] = true,
		['isbn'] = true,
		['ismn'] = true,
		['LCCN'] = true,
		['mailinglist'] = true,
		['message-id'] = true,
		['minutes'] = true,
		['network'] = true,
		['script-chapter'] = true,
		['season'] = true,
		['section'] = true,
		['sections'] = true,
		['series-link'] = true,
		['series-number'] = true,
		['series-separator'] = true,
		['sheet'] = true,
		['sheets'] = true,
		['station'] = true,
		['time'] = true,
		['time-caption'] = true,
		['trans-article'] = true,
		['transcript'] = true,
		['transcript-format'] = true,
		['transcript-url'] = true,
		},
	}

--[[-------------------------< A D D _ T O _ L I S T >---------------------------------------------------------

adds code/name pair to code_list and name/code pair to name_list; code/name pairs in override_list replace those
taken from the MediaWiki list; these are marked with a superscripted dagger.

|script-<param>= lang codes always use override names so dagger is omitted

]]

local function add_to_list (code_list, name_list, override_list, code, name, dagger)
	if false == dagger then
		dagger = '';															-- no dagger for |script-<param>= codes and names
	else
		dagger = '<sup>†</sup>';												-- dagger for all other lists using override
	end

	if override_list[code] then													-- look in the override table for this code
		code_list[code] = override_list[code] .. dagger;						-- use the name from the override table; mark with dagger
		name_list[override_list[code]] = code .. dagger;
	else
		code_list[code] = name;													-- use the MediaWiki name and code
		name_list[name] = code;
	end
end


--[[-------------------------< L I S T _ F O R M A T >---------------------------------------------------------

formats key/value pair into a string for rendering
	['k'] = 'v'	→ k: v

]]

local function list_format (result, list)
	for k, v in pairs (list)	do
		table.insert (result, k .. ': ' .. v);
	end
end


--[[-------------------------< L A N G _ L I S T E R >---------------------------------------------------------

Module entry point

Crude documentation tool that returns one of several lists of language codes and names.

Used in Template:Citation Style documentation/language/doc

{{#invoke:cs1 documentation support|lang_lister|list=<selector>}}

where <selector> is one of the values:
	2char – list of ISO 639-1 codes and names sorted by code
	3char – list of ISO 639-2, -3 codes and names sorted by code
	ietf – list of IETF language tags and names sorted by tag -- not supported by cs1|2 |language= parameter
	name – list of language names and codes sorted by name -- IETF tags omitted because not supported by cs1|2 |language= parameter

]]

local function lang_lister (frame)
	local source_list = mw.language.fetchLanguageNames(mw.getContentLanguage():getCode(), 'all');
	local override = cfg.lang_code_remap;
	local code_1_list={};
	local code_2_list={};
	local ietf_list={};
	local name_list={};
	
	if not ({['2char']=true, ['3char']=true, ['ietf']=true, ['name']=true})[frame.args.list] then
		return '<span style="font-size:100%" class="error">unknown list selector: ' .. frame.args.list .. '</span>';
	end

--	if 'ietf' == frame.args.list then											-- ietf codes not currently supported by cs1|2 |language= parameter
--		return '<span style="font-size:100%" class="error">ietf language tags not supported by cs1|2</span>'
--	end

	for code, name in pairs (source_list) do
		if 2 == code:len() then
			add_to_list (code_1_list, name_list, override, code, name);
		elseif 3 == code:len() then
			add_to_list (code_2_list, name_list, override, code, name);
		else																	-- ietf codes not currently supported by cs1|2 |language= parameter
			add_to_list (ietf_list, name_list, override, code, name);
		end
	end
	
	local result = {};
	local out = {};

	if '2char' == frame.args.list then
		list_format (result, code_1_list);
	elseif '3char' == frame.args.list then
		list_format (result, code_2_list);
	elseif 'ietf' == frame.args.list then
		list_format (result, ietf_list);
	else																		--must be 'name'
		list_format (result, name_list);
	end
	
	table.sort (result);
	table.insert (result, 1, '<div class="div-col columns column-width" style="column-width:20em">');
	table.insert (out, table.concat (result, '\n*'));
	table.insert (out, '</div>');
	
	return table.concat (out, '\n');
end


--[[--------------------------< S C R I P T _ L A N G _ L I S T E R >------------------------------------------

Module entry point

Crude documentation tool that returns list of language codes and names supported by the various |script-<param>= parameters.

used in Help:CS1 errors

{{#invoke:cs1 documentation support|script_lang_lister}}

]]

local function script_lang_lister ()
	local lang_code_src = cfg.script_lang_codes ;								-- get list of allowed script language codes
	local override = cfg.lang_code_remap;
	local this_wiki_lang = mw.language.getContentLanguage().code;				-- get this wiki's language

	local code_list = {};														-- interim list of aliases
	local name_list={};															-- not used; defined here so that we can reuse add_to_list() 
	local out = {};																-- final output (for now an unordered list)
	
	for _, code in ipairs (lang_code_src) do									-- loop throu the list of code
		local name = mw.language.fetchLanguageName (code, this_wiki_lang);		-- get the language name associated with this code
		add_to_list (code_list, name_list, override, code, name, false);		-- name_list{} not used but provided so that we can reuse add_to_list(); don't add superscript dagger
	end
	
	local result = {};
	local out = {};

	list_format (result, code_list);

	table.sort (result);
	table.insert (result, 1, '<div class="div-col columns column-width" style="column-width:20em">');
	table.insert (out, table.concat (result, '\n*'));
	table.insert (out, '</div>');
	
	return table.concat (out, '\n');
end


--[[--------------------------< A L I A S _ L I S T E R >------------------------------------------------------

experimental code that lists parameters and their aliases.  Perhaps basis for some sort of documentation?

{{#invoke:cs1 documentation support|alias_lister}}

]]

local function alias_lister ()
	local alias_src = cfg.aliases;												-- get master list of aliases
	local key;																	-- key for k/v in a new table
	local list = {};															-- interim list of aliases
	local out = {};																-- final output (for now an unordered list)
	
	for _, aliases in pairs (alias_src) do										-- loop throu the master list of aliases
		if 'table' == type (aliases) then										-- table only when there are aliases
			for i, alias in ipairs (aliases) do									-- loop through all of the aliases
				if 1 == i then													-- first 'alias' is the canonical parameter name
					key = alias;												-- so it becomes the key in list
				else
					list[key] = list[key] and (list[key] .. ', ' .. alias) or alias;	-- make comma-separated list of aliases
					list[alias] = 'see ' .. key;								-- make a back reference from this alias to the canonical parameter
				end
			end
		end
	end
	
	for k, v in pairs (list) do													-- loop through the list to make a simple unordered list
		table.insert (out, table.concat ({'*', k, ': ', v}));
	end
	
	table.sort (out);															-- sort it
	return table.concat (out, '\010');											-- concatenate with \n
--	return (mw.dumpObject (list))
end


--[[--------------------------< C A N O N I C A L _ P A R A M _ L I S T E R >----------------------------------

experimental code that lists canonical parameter names.  Perhaps basis for some sort of documentation?

{{#invoke:cs1 documentation support|canonical_param_lister}}

]]

local function canonical_param_lister (frame)
	local template = frame.args[1];
	if '' == template then
		template = nil;
	end

	if template then
		template = mw.text.trim (template:lower());
	end

	local alias_src = cfg.aliases;												-- get master list of aliases
	local id_src = cfg.id_handlers;												-- get master list of identifiers
	
	local list = {};															-- interim list of aliases
	local out = {};																-- final output (for now an unordered list)
	
	for _, aliases in pairs (alias_src) do										-- loop through the master list of aliases
		local name;
		if 'table' == type (aliases) then										-- table only when there are aliases
			name = aliases[1];
--			table.insert (list, aliases[1]);									-- first member of an aliases table is declared canonical
		else
			name = aliases;
--			table.insert (list, aliases);										-- for those parameters that do not have any aliases, the parameter is declared canonical
		end

		if not template then													-- no template name, add this parameter
			table.insert (list, name);
		elseif not exclusion_lists[template] then								-- template name but no exclusion list
			table.insert (list, name);
		elseif not exclusion_lists[template][name] then							-- template name and exclusion list but name not in list
			table.insert (list, name);
		end
	end
	
	for k, ids in pairs (id_src) do
		local name = id_src[k].parameters[1];
		local access = id_src[k].custom_access;
		if not template then													-- no template name, add this parameter
			table.insert (list, name);
			if access then
				table.insert (list, access);
			end
		elseif not exclusion_lists[template] then								-- template name but no exclusion list
			table.insert (list, name);
			if access then
				table.insert (list, access);
			end
		elseif not exclusion_lists[template][name] then							-- template name and exclusion list but name not in list
			table.insert (list, name);
			if access then
				table.insert (list, access);
			end
		end
	end
	
	for _, param in ipairs (list) do											-- loop through the list to make a simple unordered list
		table.insert (out, table.concat ({'*', param}));
	end
	
	local function comp( a, b )													-- used in following table.sort()
		return a:lower() < b:lower();
	end
	
	table.sort (out, comp);														-- sort it
	return table.concat (out, '\010');											-- concatenate with \n
--	return (mw.dumpObject (list))
end


--[[--------------------------< C A N O N I C A L _ N A M E _ G E T >------------------------------------------

experimental code that fetches the canonical parameter name for the metaparameter.  Perhaps basis for some sort of documentation?

returns first (canonical) name when metaparameter is assigned a table of names
returns name when metaparameter is assigned a single name
returns empty string when metaparameter name not found in alias_src{}

{{#invoke:cs1 documentation support|canonical_name_get|<metaparam>}}

]]

local function canonical_name_get (frame)
	local alias_src = cfg.aliases;												-- get master list of aliases
	local id_src = cfg.id_handlers;												-- get master list of identifiers

	local name;
	local meta = frame.args[1]

	local access;																-- for id-access parameters
	if meta:match ('^(%u+)access') then											-- the metaparameter (which is not used in ~/Configuration) is id_handlers key concatenated with access: BIBCODEaccess
		meta, access = meta:gsub ('^(%u+)access', '%1');						-- strip 'access' text from meta and use returned count value as a flag
	end

	if alias_src[meta] then
		name = alias_src[meta];													-- name is a string or a table
		if 'table' == type (name) then											-- table only when there are aliases
			name = name[1];														-- first member of an aliases table is declared canonical
		end

	elseif id_src[meta]then														-- if there is an id handler
		if access then															-- and if this is a request for the handler's custom access parameter
			if id_src[meta].custom_access then									-- if there is a custom access parameter
				name = id_src[meta].custom_access;								-- use it
			else
				return '';														-- nope, return empty string
			end
		else
			name = id_src[meta].parameters[1];									-- get canonical id handler parameter
		end
	else
		return '';
	end
	return string.format ("'''%s'''", name);									-- because csdoc bolds param names
end


--[[--------------------------< A L I A S _ N A M E S _ G E T >------------------------------------------------

experimental code that fetches the alias parameter name for the metaparameter; canonical name not fetched.  Perhaps basis for some sort of documentation?

returns list of aliases for metaparameter
returns empty string when there are no aliases
returns empty string when metaparameter name not found in alias_src{}

{{#invoke:cs1 documentation support|alias_name_get|<metaparam>}}

]]

local function alias_names_get (frame)
	local alias_src = cfg.aliases;												-- get master list of aliases
	local id_src = cfg.id_handlers;												-- get master list of identifiers

	local names;
	local meta = frame.args[1];
	local out = {};
	local aliases;

	if alias_src[meta] then
		aliases = alias_src[meta];
	elseif id_src[meta] then
		aliases = id_src[meta].parameters;
	end
	
	if 'table' == type (aliases) then											-- table only when there are aliases
		for i, alias in ipairs (aliases) do
			if 1 ~= i then
				table.insert (out, string.format ("'''%s'''", alias));			-- aliases[1] is the canonical name; don't include it; because csdoc bolds param names
			end
		end
		
		return table.concat (out, ', ');										-- make pretty list and quit
	end

	return '';																	-- no meta param with that name or no aliases
end


--[[--------------------------< I D _ L I M I T S _ G E T >----------------------------------------------------

return the limit values for named identifier parameters that have id limits (pmc, pmid, ssrn); the return value
used in template documentation and error message help-text

]]

local function id_limits_get (frame)
	local id_limits = mw.loadData ('Module:Citation/CS1/Configuration/sandbox').id_limits;		-- get id_limits {} table from ~/Configuration
--	local id_limits = cfg.id_limits;											-- get id_limits {} table from ~/Configuration; TODO: use this after next cs1|2 update
	return id_limits[frame.args[1]];
end


--[[-------------------------< E X P O R T E D   F U N C T I O N S >------------------------------------------
]]

return {
	alias_lister = alias_lister,
	alias_names_get = alias_names_get,
	canonical_param_lister = canonical_param_lister,
	canonical_name_get = canonical_name_get,
	id_limits_get = id_limits_get,
	lang_lister = lang_lister,
	script_lang_lister = script_lang_lister,
	};