Module:Cs1 documentation support: Difference between revisions

script_lang_lister: 20em for lang cols wider than necessary; wastes too much space
m 1 revision imported: template update
 
(7 intermediate revisions by 4 users not shown)
Line 1: Line 1:
require('Module:No globals');
require('strict');
local getArgs = require ('Module:Arguments').getArgs;
local getArgs = require ('Module:Arguments').getArgs;


Line 172: Line 172:
2char – list of ISO 639-1 codes and names sorted by code
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
3char – list of ISO 639-2, -3 codes and names sorted by code
ietf – list of IETF language tags and names sorted by tag -- partial support for these by cs1|2 |language= parameter
ietf – list of IETF language tags and names sorted by tag
name – list of language names and codes sorted by name -- IETF tags omitted because not supported by cs1|2 |language= parameter
ietf2 – list of ISO 639-1 based IETF language tags and names sorted by tag
ietf3 – list of list of ISO 639-2, -3 based IETF language tags and names sorted by tag
name – list of language names and codes sorted by name
all - list all language codes/tags and names sorted by code/tag
all - list all language codes/tags and names sorted by code/tag


Line 185: Line 187:
local lang = (frame.args.lang and '' ~= frame.args.lang) and frame.args.lang or mw.getContentLanguage():getCode()
local lang = (frame.args.lang and '' ~= frame.args.lang) and frame.args.lang or mw.getContentLanguage():getCode()
local source_list = mw.language.fetchLanguageNames(lang, 'all');
local source_list = mw.language.fetchLanguageNames(lang, 'all');
local override = cfg.lang_code_remap;
local override = cfg.lang_tag_remap;
local code_1_list={};
local code_1_list={};
local code_2_list={};
local code_2_list={};
local ietf_list={};
local ietf_list={};
local ietf_list2={};
local ietf_list3={};
local name_list={};
local name_list={};
if not ({['2char']=true, ['3char']=true, ['ietf']=true, ['name']=true, ['all']=true})[frame.args.list] then
if not ({['2char']=true, ['3char']=true, ['ietf']=true, ['ietf2']=true, ['ietf3']=true, ['name']=true, ['all']=true})[frame.args.list] then
return '<span style="font-size:100%" class="error">unknown list selector: ' .. frame.args.list .. '</span>';
return '<span style="color:#d33">unknown list selector: ' .. frame.args.list .. '</span>';
end
end


Line 202: Line 206:
elseif 3 == code:len() then
elseif 3 == code:len() then
add_to_list (code_2_list, name_list, override, code, name);
add_to_list (code_2_list, name_list, override, code, name);
else -- ietf codes only partically supported by cs1|2 |language= parameter
elseif code:match ('^%a%a%-.+') then -- ietf with 2-character language tag
add_to_list (ietf_list, name_list, override, code, name);
add_to_list (ietf_list, name_list, override, code, name); -- add to main ietf list for |list=ietf
add_to_list (ietf_list2, name_list, override, code, name); -- add to ietf2 list
elseif code:match ('^%a%a%a%-.+') then -- ietf with 3-character language tag
add_to_list (ietf_list, name_list, override, code, name); -- add to main ietf list for |list=ietf
add_to_list (ietf_list3, name_list, override, code, name); -- add to ietf3 list
end
end
end
end
Line 210: Line 218:
local out = {};
local out = {};


if '2char' == frame.args.list or 'all' == frame.args.list then
if '2char' == frame.args.list or 'all' == frame.args.list then -- iso 639-1
list_format (result, code_1_list);
list_format (result, code_1_list);
elseif '3char' == frame.args.list then
elseif '3char' == frame.args.list then -- iso 639-2, 3
list_format (result, code_2_list);
list_format (result, code_2_list);
elseif 'ietf' == frame.args.list then
elseif 'ietf' == frame.args.list then -- all ietf tags
list_format (result, ietf_list);
list_format (result, ietf_list);
elseif 'ietf2' == frame.args.list then -- 2-character ietf tags
list_format (result, ietf_list2);
elseif 'ietf3' == frame.args.list then -- 3 character ietf tags
list_format (result, ietf_list3);
else --must be 'name'
else --must be 'name'
list_format (result, name_list);
list_format (result, name_list);
Line 247: Line 259:
local function script_lang_lister (frame)
local function script_lang_lister (frame)
local lang_code_src = cfg.script_lang_codes ; -- get list of allowed script language codes
local lang_code_src = cfg.script_lang_codes ; -- get list of allowed script language codes
local override = cfg.lang_code_remap;
local override = cfg.lang_tag_remap;
local this_wiki_lang = mw.language.getContentLanguage().code; -- get this wiki's language
local this_wiki_lang = mw.language.getContentLanguage().code; -- get this wiki's language


Line 663: Line 675:
local handlers = cfg.id_handlers; -- get id_handlers {} table from ~/Configuration
local handlers = cfg.id_handlers; -- get id_handlers {} table from ~/Configuration


return args[1] and handlers[args[1]:upper()].id_limit or ('<span style="font-size:100%" class="error">No limit defined for identifier: ' .. (args[1] or '<unknown name>') .. '</span>');
return args[1] and handlers[args[1]:upper()].id_limit or ('<span style="color:#d33">No limit defined for identifier: ' .. (args[1] or '<unknown name>') .. '</span>');
end
end


Line 683: Line 695:
local lang_list_t = mw.language.fetchLanguageNames ('en', 'all');
local lang_list_t = mw.language.fetchLanguageNames ('en', 'all');
   
   
local function script_cat_lister (script_lang_codes_t, lang_code_remap_t, cats_list_t)
local function script_cat_lister (script_lang_codes_t, lang_tag_remap_t, cats_list_t)
for _, lang_code in ipairs (script_lang_codes_t) do
for _, lang_code in ipairs (script_lang_codes_t) do
local lang_name = lang_code_remap_t[lang_code] or lang_list_t[lang_code]; -- use remap table to get Bengali instead of Bangla and the like; else use standard MediaWiki names
local lang_name = lang_tag_remap_t[lang_code] or lang_list_t[lang_code]; -- use remap table to get Bengali instead of Bangla and the like; else use standard MediaWiki names
local cat = 'CS1 uses ' .. lang_name .. '-language script (' .. lang_code .. ')'; -- build a category name
local cat = 'CS1 uses ' .. lang_name .. '-language script (' .. lang_code .. ')'; -- build a category name
cats_list_t[cat] = 1; -- and save it
cats_list_t[cat] = 1; -- and save it
Line 766: Line 778:
end
end


script_cat_lister (cfg.script_lang_codes, cfg.lang_code_remap, list_live_cats); -- get live module's foriegn language script cats
script_cat_lister (cfg.script_lang_codes, cfg.lang_tag_remap, list_live_cats); -- get live module's foriegn language script cats


if sandbox then -- if ~/sandbox module exists and |sandbox= not set to 'no'
if sandbox then -- if ~/sandbox module exists and |sandbox= not set to 'no'
Line 774: Line 786:
end
end


script_cat_lister (sb_cfg.script_lang_codes, sb_cfg.lang_code_remap, list_sbox_cats); -- get sandbox module's foriegn language script cats
script_cat_lister (sb_cfg.script_lang_codes, sb_cfg.lang_tag_remap, list_sbox_cats); -- get sandbox module's foriegn language script cats
end
end
else
else
return '<span style=\"font-size:100%; font-style:normal;\" class=\"error\">error: unknown selector: ' .. select .. '</span>'
return '<span style="color:#d33; font-style:normal;">error: unknown selector: ' .. select .. '</span>'
end
end


Line 877: Line 889:
with this:
with this:
{{#invoke:Cs1 documentation support|help_text_cats|err_bad_biorxiv}}
{{#invoke:Cs1 documentation support|help_text_cats|err_bad_biorxiv}}
where {{{1}}} is the error_conditions key from Module:Citation/CS1/Configuration


add |pages=yes to append the number of pages in the category
add |pages=yes to append the number of pages in the category
]=]
]=]


local function help_text_cats (frame)
local function help_text_cats (frame)
local args = getArgs (frame);
local args_t = getArgs (frame);
local error_conditions = mw.loadData ('Module:Citation/CS1/Configuration').error_conditions;
local error_conditions_t = cfg.error_conditions; -- get the table of error conditions
local out = {}; -- output goes here
local replacements_t = {}; -- table to hold replacement parameters for $1 etc placeholders in category names
for k, v in pairs (args_t) do -- look for |$1=<replacement> parameters
if args[1] and error_conditions[args[1]] then -- must have error_condition key and it must exist
if 'string' == type (k) and k:match ('^$%d+$') then -- if found
table.insert (out, '{{#ifeq:{{FULLPAGENAME}}|Category:'); -- the beginning with category prefix
replacements_t[k] = v; -- save key and value
table.insert (out, error_conditions[args[1]].category); -- fetch the error category name (the reference that {{FULLPAGENAME}} must equate to)
end
table.insert (out, '|Category:'); -- this category plain text when this invoke is on the category page
end
table.insert (out, error_conditions[args[1]].category); -- fetch the error category name
 
table.insert (out, '|'); -- the necessary pipe
if args_t[1] and error_conditions_t[args_t[1]] then -- must have error_condition key and it must exist
table.insert (out, cat_link_make (error_conditions[args[1]].category)); -- one the help page or elsewhere so link to the category
local error_cat = error_conditions_t[args_t[1]].category; -- get error category from cs1|2 configuration
table.insert (out, '}}'); -- and close the #ifeq
if error_cat:match ('$%d') then -- look for placeholders in <error_cat>
if 'yes' == args.pages then
error_cat = error_cat:gsub ('$%d', replacements_t) -- replace place holders with matching value from replacements_t
table.insert (out, ' ({{PAGESINCATEGORY:');
end
table.insert (out, error_conditions[args[1]].category); -- fetch the error category name
table.insert (out, '}} pages)');
local title_obj = mw.title.getCurrentTitle(); -- get a title object for the currently displayed page
local name_space = title_obj.nsText;
if ('Category' == name_space) and (error_cat == title_obj.text) then -- if this is the category page for the error message
return table.concat ({'Category:', error_cat}); -- no link; just category name
else -- here when currently displayed page is other than the error message category
local pages = ''; -- default empty strin for concatenation
if 'yes' == args_t.pages then -- if we should display category page count: TODO: do we need to keep this?
pages = mw.site.stats.pagesInCategory (error_cat, 'all'); -- get category page count
pages = table.concat ({' (', mw.language.getContentLanguage():formatNum (pages), ' page', (1 == pages) and ')' or 's)'}); -- make renderable text
end
return table.concat ({'[[:Category:', error_cat, ']]', pages}); -- link to category with or without page count
end
end
else
else
return '<span style="font-size:100%" class="error">unknown error_conditions key: ' .. (args[1] or 'key missing') .. '</span>';
return '<span style="color:#d33">unknown error_conditions key: ' .. (args_t[1] or 'key missing') .. '</span>';
end
end
return frame:preprocess (table.concat (out)); -- make a big string, preprocess, and done
end
end


Line 915: Line 937:
{{#invoke:Cs1 documentation support|help_text_error_messages|err_bad_issn|$1=_}} -> Check |issn= value
{{#invoke:Cs1 documentation support|help_text_error_messages|err_bad_issn|$1=_}} -> Check |issn= value
{{#invoke:Cs1 documentation support|help_text_error_messages|err_bad_issn|$1=e}} -> Check |eissn= value
{{#invoke:Cs1 documentation support|help_text_error_messages|err_bad_issn|$1=e}} -> Check |eissn= value
error message is rendered at 120% font size; to specify another font size use |size=; must include unit specifier (%, em, etc)
]]
]]


local function help_text_error_messages (frame)
local function help_text_error_messages (frame)
local args = getArgs (frame);
local args_t = getArgs (frame);
local error_conditions = mw.loadData ('Module:Citation/CS1/Configuration').error_conditions;
local error_conditions = mw.loadData ('Module:Citation/CS1/Configuration').error_conditions;
local span_o = '<span class="cs1-visible-error error citation-comment">';
-- local span_o = '<span class="cs1-visible-error citation-comment">';
local span_o = '<span class="citation-comment" style="color:#d33; font-size:' .. ((args_t.size and args_t.size) or '120%') .. '">';
local span_c = '</span>';
local span_c = '</span>';


Line 926: Line 952:
local out = {}; -- output goes here
local out = {}; -- output goes here
if args[1] and error_conditions[args[1]] then -- must have error_condition key and it must exist
if args_t[1] and error_conditions[args_t[1]] then -- must have error_condition key and it must exist
message = error_conditions[args[1]].message;
message = error_conditions[args_t[1]].message;
local i=1;
local i=1;
local count;
local count;
Line 933: Line 959:
repeat
repeat
rep = '$'..i
rep = '$'..i
args[rep] = args[rep] and args[rep]:gsub ('^%s*_%s*$', '') or nil; -- replace empty string marker with actual empty string
args_t[rep] = args_t[rep] and args_t[rep]:gsub ('^%s*_%s*$', '') or nil; -- replace empty string marker with actual empty string
message, count = message:gsub (rep, args[rep] or rep)
message, count = message:gsub (rep, args_t[rep] or rep)
i = i + 1;
i = i + 1;
until (0 == count);
until (0 == count);
Line 942: Line 968:
table.insert (out, span_c);
table.insert (out, span_c);
else
else
return '<span style="font-size:100%" class="error">unknown error_conditions key: ' .. (args[1] or 'key missing') .. '</span>';
return '<span style="color:#d33">unknown error_conditions key: ' .. (args_t[1] or 'key missing') .. '</span>';
end
end
local out_str = table.concat (out);
local out_str = table.concat (out);
out_str = frame:expandTemplate ({title='resize', args = {'120%', out_str} })
return table.concat ({frame:extensionTag ('templatestyles', '', {src='Module:Citation/CS1/styles.css'}), out_str});
return table.concat ({out_str, frame:extensionTag ('templatestyles', '', {src='Module:Citation/CS1/styles.css'})});
end
end


Line 959: Line 984:
Each subsequence table holds:
Each subsequence table holds:
[1] documentation page where the TemplateData json is stored ({{cite book}} is the oddball)
[1] documentation page where the TemplateData json is stored ({{cite book}} is the oddball)
[2] key to 'preprint_arguments' and unique_arguments' tables in Module:Citation/CS1/Whitelist; these keys
[2] key to 'preprint_arguments_t' and unique_arguments_t' tables in Module:Citation/CS1/Whitelist; these keys
dictate which of the basic or limited arguments and numbered arguments tables will be used to validate
dictate which of the basic or limited arguments and numbered arguments tables will be used to validate
the content of the TemplateData
the content of the TemplateData
Line 971: Line 996:
citebiorxiv = {'Template:Cite bioRxiv/doc', 'biorxiv'}, -- preprint arguments
citebiorxiv = {'Template:Cite bioRxiv/doc', 'biorxiv'}, -- preprint arguments
citebook = {'Template:Cite book/TemplateData'},
citebook = {'Template:Cite book/TemplateData'},
citeciteseerx = {'Template:Cite citeseerx/doc', 'citeseerx'}, -- no template data; preprint uses limited arguments
citeciteseerx = {'Template:Cite CiteSeerX/doc', 'citeseerx'}, -- no template data; preprint uses limited arguments
citeconference = {'Template:Cite conference/doc'},
citeconference = {'Template:Cite conference/doc', 'conference'}, -- unique arguments
citedocument = {'Template:Cite document/doc', 'document'}, -- special case; uses whitelist.document_parameters_t
citeencyclopedia = {'Template:Cite encyclopedia/doc'},
citeencyclopedia = {'Template:Cite encyclopedia/doc'},
citeepisode = {'Template:Cite episode/doc', 'episode'}, -- unique arguments
citeepisode = {'Template:Cite episode/doc', 'episode'}, -- unique arguments
Line 979: Line 1,005:
citemagazine = {'Template:Cite magazine/doc'},
citemagazine = {'Template:Cite magazine/doc'},
citemailinglist = {'Template:Cite mailing list/doc', 'mailinglist'}, -- unique arguments -- no template data
citemailinglist = {'Template:Cite mailing list/doc', 'mailinglist'}, -- unique arguments -- no template data
citemap = {'Template:Cite map/doc', 'map'}, -- unique arguments -- no template data
citemap = {'Template:Cite map/TemplateData', 'map'}, -- unique arguments
citemedrxiv = {'Template:Cite medRxiv/doc', 'medrxiv'}, -- preprint arguments
citenews = {'Template:Cite news/doc'},
citenews = {'Template:Cite news/doc'},
citenewsgroup = {'Template:Cite newsgroup/doc', 'newsgroup'}, -- unique arguments
citenewsgroup = {'Template:Cite newsgroup/doc', 'newsgroup'}, -- unique arguments
citepodcast = {'Template:Cite podcast/doc'},
citepodcast = {'Template:Cite podcast/doc'},
citepressrelease = {'Template:Cite press release/doc'},
citepressrelease = {'Template:Cite press release/doc'},
citereport = {'Template:Cite report/doc'},
citereport = {'Template:Cite report/doc', 'report'}, -- unique arguments
citeserial = {'Template:Cite serial/doc', 'serial'}, -- unique arguments -- no template data
citeserial = {'Template:Cite serial/doc', 'serial'}, -- unique arguments -- no template data
citesign = {'Template:Cite sign/doc'},
citesign = {'Template:Cite sign/doc'},
citespeech = {'Template:Cite speech/doc'}, -- no template data
citespeech = {'Template:Cite speech/doc', 'speech'}, -- unique arguments -- no template data
citessrn = {'Template:Cite ssrn/doc', 'ssrn'}, -- preprint arguments -- no template data
citessrn = {'Template:Cite SSRN/doc', 'ssrn'}, -- preprint arguments -- no template data
citetechreport = {'Template:Cite techreport/doc'},
citetechreport = {'Template:Cite tech report/doc'},
citethesis = {'Template:Cite thesis/doc'},
citethesis = {'Template:Cite thesis/doc', 'thesis'}, -- unique arguments
citeweb = {'Template:Cite web/doc'},
citeweb = {'Template:Cite web/doc'},
citation = {'Template:Citation/doc'},
citation = {'Template:Citation/doc'},
}
}
--[[--------------------------< N O _ P A G E _ T E M P L A T E S _ T >----------------------------------------
]]
local no_page_templates_t = {};




Line 1,025: Line 1,060:
json = json:match ('<[Tt]emplate[Dd]ata>(.-)</[Tt]emplate[Dd]ata>'); -- remove everything exept the content of the TemplatData tags
json = json:match ('<[Tt]emplate[Dd]ata>(.-)</[Tt]emplate[Dd]ata>'); -- remove everything exept the content of the TemplatData tags
return json and mw.text.jsonDecode (json); -- decode the json string and return as a table; nil if not found
return json and mw.text.jsonDecode (json); -- decode the json string and return as a table; nil if not found
end
--[[--------------------------< V A L I D A T E _ D O C U M E N T _ P A R A M >--------------------------------
looks for <param> (can be the canonical parameter name or can be an alias) in whitelist.document_parameters_t.
When found, returns true; nil else
<param> is the parameter's name as listed in the TemplateData
]]
local function validate_document_param (param)
if true == whitelist.document_parameters_t[param] then
return true;
end
end
end


Line 1,038: Line 1,089:


local function validate_basic_param (param)
local function validate_basic_param (param)
if true == whitelist.basic_arguments[param] or true == whitelist.numbered_arguments[param] then
if true == whitelist.common_parameters_t[param] then
return true;
return true;
end
end
Line 1,046: Line 1,097:
--[[--------------------------< V A L I D A T E _ P R E P R I N T _ P A R A M >--------------------------------
--[[--------------------------< V A L I D A T E _ P R E P R I N T _ P A R A M >--------------------------------


looks for <param> (can be the canonical parameter name or can be an alias) in whitelist.preprint_arguments{} or
looks for <param> (can be the canonical parameter name or can be an alias) in whitelist.preprint_arguments_t{} or
whitelist.limited_basic_arguments{} or whitelist.limited_numbered_arguments{}.  When found, returns true; nil else
whitelist.limited_basic_arguments{} or whitelist.limited_numbered_arguments{}.  When found, returns true; nil else


<param> is the parameter's name as listed in the TemplateData
<param> is the parameter's name as listed in the TemplateData
<key> is key neccessary to look in the appropriate subtable of whitelist.preprint_arguments{}
<key> is key neccessary to look in the appropriate subtable of whitelist.preprint_arguments_t{}


]]
]]


local function validate_preprint_param (param, key)
local function validate_preprint_param (param, key)
if true == whitelist.preprint_arguments[key][param] or  
if true == whitelist.preprint_arguments_t[key][param] or
true == whitelist.limited_basic_arguments[param] or
true == whitelist.limited_parameters_t[param] then
true == whitelist.limited_numbered_arguments[param] then
-- true == whitelist.limited_basic_arguments_t[param] or
-- true == whitelist.limited_numbered_arguments_t[param] then
return true;
return true;
end
end
Line 1,065: Line 1,117:
--[[--------------------------< V A L I D A T E _ U N I Q U E _ P A R A M >------------------------------------
--[[--------------------------< V A L I D A T E _ U N I Q U E _ P A R A M >------------------------------------


looks for <param> (can be the canonical parameter name or can be an alias) in whitelist.unique_arguments{} or
looks for <param> (can be the canonical parameter name or can be an alias) in whitelist.unique_arguments_t{} or
whitelist.basic_arguments{} or whitelist.numbered_arguments{}.  When found, returns true; nil else
whitelist.basic_arguments{} or whitelist.numbered_arguments{}.  When found, returns true; nil else


<param> is the parameter's name as listed in the TemplateData
<param> is the parameter's name as listed in the TemplateData
<key> is key neccessary to look in the appropriate subtable of whitelist.unique_arguments{}
<key> is key neccessary to look in the appropriate subtable of whitelist.unique_arguments_t{}


]]
]]


local function validate_unique_param (param, key)
local function validate_unique_param (param, key, cfg_aliases_t)
if true == whitelist.unique_arguments[key][param] or true == validate_basic_param (param) then
if true == whitelist.unique_arguments_t[key][param] or true == validate_basic_param (param) then
return true;
return true;
end
end
Line 1,100: Line 1,152:


local function param_error_msg (param)
local function param_error_msg (param)
return '<code style="color: inherit; background: inherit; border: none; padding: inherit">|' .. param .. '=</code> not valid parameter';
return '<span style="font-family:"monospace">|' .. param .. '=</span> is not a valid parameter';
end
 
 
--[[--------------------------< D U P _ A L I A S _ E R R O R_ M S G >-----------------------------------------
 
 
]]
 
local function dup_alias_error_msg (param, alias)
return '<span style="font-family:"monospace">|' .. param .. '=</span> has duplicate aliases: <span font-family:"monospace";>|' .. alias .. '=</span>';
end
 
 
--[[--------------------------< D U P _ A L I A S E S _ C H E C K >--------------------------------------------
 
create an associative array of <param> aliases. if <alias> already present in <aliases_t> add an error message
to <out>
 
]]
 
local function dup_aliases_check (param, alias, aliases_t, out_t)
if not aliases_t[alias] then
aliases_t[alias] = true;
else
table.insert (out_t, dup_alias_error_msg (param, alias));
end
end
end


Line 1,110: Line 1,188:


local function alias_error_msg (param, alias)
local function alias_error_msg (param, alias)
return '<code style="color: inherit; background: inherit; border: none; padding: inherit">|' .. alias .. '=</code> not valid alias of: <code style="color: inherit; background: inherit; border: none; padding: inherit">|' .. param .. '=</code>';
return '<code style="color: inherit; background: inherit; border: none; padding: inherit">|' .. alias .. '=</code> is not a valid alias of: <code style="color: inherit; background: inherit; border: none; padding: inherit">|' .. param .. '=</code>';
end
 
 
--[[--------------------------< C F G _ A L I A S E S _ T _ M A K E >------------------------------------------
 
convert this from cfg.aliases{}:
['AccessDate'] = {'access-date', 'accessdate'}
 
to this in out_t{}
['access-date'] = 'AccessDate',
['accessdate'] = 'AccessDate',
 
to test if |accessdate= is an aliases of |access-date=:
if out_t['access-date'] == out_t['accessdate']
]]
 
local function cfg_aliasts_t_make ()
local out_t = {};
for meta, params_t in pairs (cfg.aliases) do
if 'table' == type (params_t) then -- metaparameters that are assigned string values do not have aliases
for _, param in ipairs (params_t) do -- for each alias
param = param:gsub ('#', ''); -- get rid of enumerators
out_t[param] = meta; -- add it to the output table
end
end
end
--error (mw.dumpObject (out_t))
return out_t;
end
end


Line 1,122: Line 1,228:


When called from a different page:
When called from a different page:
{{#invoke:Sandbox/trappist the monk/template data|template_data_validate|<canonical template name>}}
{{#invoke:cs1 documentation support|template_data_validate|<canonical template name>}}
where the <canonical template name> is the template's canonical name with or without namespace and or subpages
where the <canonical template name> is the template's canonical name with or without namespace and or subpages


Line 1,129: Line 1,235:
local function template_data_validate (frame)
local function template_data_validate (frame)
local args_t = getArgs (frame);
local args_t = getArgs (frame);
 
if not args_t[1] then
if not args_t[1] then
return '<span style=\"font-size: 100%; font-style: normal;\" class=\"error\">Error: cs1|2 template name required</span>';
return '<span style="color:#d33">Error: cs1|2 template name required</span>';
end
end


local template_idx = args_t[1]:lower():match ('cit[ae][^/]+'); -- args_t[1] has something
local template_idx = args_t[1]:lower():match ('cit[ae][^/]+'); -- args_t[1] has something
if not template_idx then -- but if not a cs1|2 template abandon with error message
if not template_idx then -- but if not a cs1|2 template abandon with error message
return '<span style=\"font-size: 100%; font-style: normal;\" class=\"error\">Error: cs1|2 template name required</span>';
return '<span style="color:#d33">Error: cs1|2 template name required</span>';
else
else
template_idx = template_idx:gsub (' ', ''); -- is what appears to be a cs1|2 template so strip spaces
template_idx = template_idx:gsub (' ', ''); -- is what appears to be a cs1|2 template so strip spaces
end
end
local cfg_aliases_t = cfg_aliasts_t_make ();


local template_t = templates_t[template_idx];
local template_t = templates_t[template_idx];
Line 1,151: Line 1,259:
else
else
for param, param_t in pairs (json_t['params']) do
for param, param_t in pairs (json_t['params']) do
local param_i = param:gsub ('%d+', '#'); -- in case an enumerated parameter, convert the enumerate digits to a single '#' character
local param_i; -- this will be the parameter name that gets validated
if param:find ('[Ss]2[Cc][Ii][Dd]') then -- |s2cid*= parameters are not enumerated ...
param_i = param; -- ... so don't convert the '2' to '#'
else
param_i = param:gsub ('%d+', '#'); -- for enumerated parameters, convert the enumerator digits to a single '#' character; all others unmolested
end
 
local param_is_valid; -- boolean true when param is valid; nil else
local param_is_valid; -- boolean true when param is valid; nil else
if template_t[2] then -- if template is a preprint or uses unique parameters
if template_t[2] then -- if template is a preprint or uses unique parameters of 'document' parameters
if whitelist.preprint_arguments[template_t[2]] then -- if a preprint template
if 'document' == template_t[2] then -- if a {{cite document}} template
param_is_valid = validate_document_param (param_i, template_t[2]);
if param_is_valid then
local aliases_t = {}; -- used by dup_aliases_check
if param_t['aliases'] then
for _, alias in ipairs (param_t['aliases']) do
dup_aliases_check (param, alias, aliases_t, out);
local alias_i = alias:gsub ('%d+', '#'); -- in case an enumerated parameter, convert the enumerator digits to a single '#' character
if not validate_document_param (alias_i, template_t[2]) then -- is 'alias' a known parameter?
table.insert (out, alias_error_msg (param, alias)); -- may be known but is not supported
elseif cfg_aliases_t[param_i:gsub ('#', '')] ~= cfg_aliases_t[alias_i:gsub ('#', '')] then -- is 'alias' known to be an alias of 'param'?
table.insert (out, alias_error_msg (param, alias));
end
end
end
else -- here when param not valid preprint param
table.insert (out, param_error_msg (param))
end
elseif whitelist.preprint_arguments_t[template_t[2]] then -- if a preprint template
param_is_valid = validate_preprint_param (param_i, template_t[2]);
param_is_valid = validate_preprint_param (param_i, template_t[2]);
if param_is_valid then
if param_is_valid then
local aliases_t = {}; -- used by dup_aliases_check
if param_t['aliases'] then
if param_t['aliases'] then
for _, alias in ipairs (param_t['aliases']) do
for _, alias in ipairs (param_t['aliases']) do
dup_aliases_check (param, alias, aliases_t, out);
local alias_i = alias:gsub ('%d+', '#'); -- in case an enumerated parameter, convert the enumerator digits to a single '#' character
local alias_i = alias:gsub ('%d+', '#'); -- in case an enumerated parameter, convert the enumerator digits to a single '#' character
if not validate_preprint_param (alias_i, template_t[2]) then
if not validate_preprint_param (alias_i, template_t[2]) then -- is 'alias' a known parameter?
table.insert (out, alias_error_msg (param, alias));
table.insert (out, alias_error_msg (param, alias)); -- may be known but is not supported
elseif cfg_aliases_t[param_i:gsub ('#', '')] ~= cfg_aliases_t[alias_i:gsub ('#', '')] then -- is 'alias' known to be an alias of 'param'?
table.insert (out, alias_error_msg (param, alias));
  end
  end
end
end
Line 1,168: Line 1,304:
table.insert (out, param_error_msg (param))
table.insert (out, param_error_msg (param))
  end
  end
elseif whitelist.unique_arguments[template_t[2]] then -- if a unique parameters template
elseif whitelist.unique_arguments_t[template_t[2]] then -- if a unique parameters template
param_is_valid = validate_unique_param (param_i, template_t[2]);
param_is_valid = validate_unique_param (param_i, template_t[2]);
if param_is_valid then
if param_is_valid then
local aliases_t = {}; -- used by dup_aliases_check
if param_t['aliases'] then
if param_t['aliases'] then
for _, alias in ipairs (param_t['aliases']) do
for _, alias in ipairs (param_t['aliases']) do
dup_aliases_check (param, alias, aliases_t, out);
local alias_i = alias:gsub ('%d+', '#'); -- in case an enumerated parameter, convert the enumerate digits to a single '#' character
local alias_i = alias:gsub ('%d+', '#'); -- in case an enumerated parameter, convert the enumerate digits to a single '#' character
if not validate_unique_param (alias_i, template_t[2]) then
if not validate_unique_param (alias_i, template_t[2]) then -- is 'alias' a known parameter?
table.insert (out, alias_error_msg (param, alias));
elseif cfg_aliases_t[param_i:gsub ('#', '')] ~= cfg_aliases_t[alias_i:gsub ('#', '')] then -- is 'alias' known to be an alias of 'param'?
table.insert (out, alias_error_msg (param, alias));
table.insert (out, alias_error_msg (param, alias));
  end
  end
Line 1,189: Line 1,329:
param_is_valid = validate_basic_param (param_i);
param_is_valid = validate_basic_param (param_i);
if param_is_valid then
if param_is_valid then
local aliases_t = {}; -- used by dup_aliases_check
if param_t['aliases'] then
if param_t['aliases'] then
for _, alias in ipairs (param_t['aliases']) do
for _, alias in ipairs (param_t['aliases']) do
dup_aliases_check (param, alias, aliases_t, out)
local alias_i = alias:gsub ('%d+', '#'); -- in case an enumerated parameter, convert the enumerate digits to a single '#' character
local alias_i = alias:gsub ('%d+', '#'); -- in case an enumerated parameter, convert the enumerate digits to a single '#' character
if not validate_basic_param (alias_i) and not validate_id_alias (param, alias) then -- for isbn13 (while still supported) must not mask the digits
if not validate_basic_param (alias_i) and not validate_id_alias (param, alias) then -- for isbn13 (while still supported) must not mask the digits
  table.insert (out, alias_error_msg (param, alias));
  table.insert (out, alias_error_msg (param, alias));
elseif cfg_aliases_t[param_i:gsub ('#', '')] ~= cfg_aliases_t[alias_i:gsub ('#', '')] then -- is 'alias' known to be an alias of 'param'?
table.insert (out, alias_error_msg (param, alias));
  end
  end
end
end
Line 1,203: Line 1,347:
end
end
end
end
---------- this emits errors when page/pages/at listed in templatedata of templates that don't support those parameters ----------
-- if json_t then
-- if ({['citeavmedia']=true, ['citeepisode']=true, ['citemailinglist']=true, ['citenewsgroup']=true, ['citepodcast']=true, ['citeserial']=true, ['citesign']=true, ['citespeech']=true})[template_idx] then
-- local insource_params_t = {}; -- build sequence of pagination params not supported by these templates
-- for _, meta_param in ipairs ({'At', 'Page', 'Pages', 'QuotePage', 'QuotePages'}) do
-- if 'table' == type (cfg.aliases[meta_param]) then
-- for _, alias in ipairs (cfg.aliases[meta_param]) do -- metaparameter is a sequence
-- table.insert (insource_params_t, alias); -- add the aliases from the metaparameter sequence to the table
-- end
-- else -- metaparameter is plain text
-- table.insert (insource_params_t, cfg.aliases[meta_param]); -- add the alias to the table
-- end
-- end
--
-- for _, param in ipairs (insource_params_t) do
-- if json_t.params[param] then
-- table.insert (out, param_error_msg (param)); -- error; this parameter not supported by this template
-- end
-- end
-- end
-- end
---------- end page/pages/at error detection ----------


if 0 ~= #out then
if 0 ~= #out then
table.sort (out);
table.sort (out);
out[1] = '*' .. out[1]; -- add a splat to the first error message
out[1] = '*' .. out[1]; -- add a splat to the first error message
return table.concat ({'[[' .. template_doc .. ']] TemplateData has errors:<div style=\"font-size: 100%; font-style: normal;\" class=\"error\">\n', table.concat (out, '\n*'), '</div>'});
 
-- return table.concat ({'[[' .. template_doc .. ']] TemplateData has errors:<div style="color:#d33; font-style: normal">\n', table.concat (out, '\n*'), '</div>'});
return table.concat ({
'[[Template:' .. args_t[1] .. ']]  uses ',
whitelist.preprint_arguments_t[template_t[2]] and 'preprint and limited parameter sets' or (whitelist.unique_arguments_t[template_t[2]] and 'unique and standard parameter sets' or 'standard parameter set'),
'; TemplateData has errors:\n',
'<div style="color:#d33; font-style: normal">\n', table.concat (out, '\n*'), '</div>'
});
else
else
return; -- no errors detected; return nothing
return; -- no errors detected; return nothing
end
end
--[[--------------------------< E R R O R _ C A T _ P A G E _ T A L L Y >--------------------------------------
loop through Module:Citation/CS1/Configuration error_conditions {} fetching error category names.  For each error
category add the number of pages in the category to the tally.  Render the number when done.
{{#invoke:cs1 documentation support|error_cat_page_tally}}
]]
local function error_cat_page_tally ()
local error_conditions_t = cfg.error_conditions; -- get the table of error conditions
local tally = 0;
local cat_t = {}; -- some error message share a category; save tallied cats here so we don't recount the already counted
local i = 0; -- number of categories
for k, v_t in pairs (error_conditions_t) do
if k:match ('^err') then
if not cat_t[v_t.category] then
cat_t[v_t.category] = true;
tally = tally +  mw.site.stats.pagesInCategory (v_t.category, 'pages'); -- get category page count; ignore subcats and files
i = i + 1;
end
end
end
return mw.language.getContentLanguage():formatNum (tally)
end
--[[--------------------------< M A I N T _ C A T _ P A G E _ T A L L Y >--------------------------------------
loop through Module:Citation/CS1/Configuration error_conditions {} fetching error category names.  For each error
category add the number of pages in the category to the tally.  Render the number when done.
{{#invoke:cs1 documentation support|maint_cat_page_tally}}
Dynamic subcats of CS1 maint: DOI inactive not counted because these names come and go as time goes by.
]]
local function maint_cat_page_tally ()
local error_conditions_t = cfg.error_conditions; -- get the table of error conditions
local tally = 0;
local cat_t = {}; -- some error message share a category; save tallied cats here so we don't recount the already counted
local i = 0; -- number of categories
for k, v_t in pairs (error_conditions_t) do
if not k:match ('^err') then -- if not an error key its a maint key
if not cat_t[v_t.category] then
cat_t[v_t.category] = true;
if 'maint_mult_names' == k or 'maint_numeric_names' == k then
local special_case_translation_t = cfg.special_case_translation;
for _, name in ipairs ({'AuthorList', 'ContributorList', 'EditorList', 'InterviewerList', 'TranslatorList'}) do
local cat_name = v_t.category:gsub ('$1', special_case_translation_t[name]); -- replace $1 with translated list name
tally = tally +  mw.site.stats.pagesInCategory (cat_name, 'pages'); -- get category page count; ignore subcats and files
i = i + 1;
end
else
tally = tally +  mw.site.stats.pagesInCategory (v_t.category, 'pages'); -- get category page count; ignore subcats and files
i = i + 1;
end
end
end
end
return mw.language.getContentLanguage():formatNum (tally)
end
--[[--------------------------< U N C A T E G O R I Z E D _ N A M E S P A C E _ L I S T E R >------------------
For use in the Help:CS1 error §Notes
Get namespace names and identifiers from MediaWiki.  Make a human readable list of namespace names and identifiers
that cs1|2 does not categorize.
{{#invoke:cs1 documentation support|uncategorized_namespace_lister}}
For convenience,
{{#invoke:cs1 documentation support|uncategorized_namespace_lister|all=<anything>}}
returns a list of all namespace names and identifiers used on the current wiki.  Any namespace with an
identifier less than 1, currently Mainspace (0), Special (-1), and Media (-2), is excluded from the list.
]]
local function uncategorized_namespace_lister (frame)
local list_t = {};
local function compare (a, b) -- local function to sort namespaces numerically by the identifiers
local a_num = tonumber (a:match ('%d+')); -- get identifiers and convert to numbers
local b_num = tonumber (b:match ('%d+'));
return a_num < b_num; -- do the comparison
end
for i, _ in pairs (mw.site.namespaces) do -- for each namespace in the table
if '' == frame.args.all or not frame.args.all then -- when |all= not set, make a list of uncategorized namespaces
if cfg.uncategorized_namespaces[i] then -- if the identifier is listed in our uncategorized namespace list
table.insert (list_t, table.concat ({mw.site.namespaces[i].name, ' (', i, ')'})) -- add name and identifier to our local list
end
elseif 0 < i then -- |all=<anything>: all namespace names and identifiers; ignore identifiers less than 1
table.insert (list_t, table.concat ({'*', mw.site.namespaces[i].name, ' (', i, ')'})) -- add name and identifier as an unordered list item
end
end
table.sort (list_t, compare); -- ascending numerical sort by identifier
if not frame.args.all then -- when |all= not set, format list of uncategorized namespaces and identifiers
list_t[#list_t] = 'and ' .. list_t[#list_t]; -- add 'and ' to the last name/identifier pair
return table.concat (list_t, ', '); -- make a big string and done
else -- make list of all namespaces and identifiers
return table.concat (list_t, '\n'); -- make a big string and done
end
end
--[[--------------------------< S I N G L E _ L T R _ 2 N D _ L V L _ D O M A I N  _ L I S T E R >-------------
for Help:CS1_errors#bad_url, list the supported top level domains that support single-letter 2nd level names
{{#invoke:Module:cs1 documentation support|single_ltr_2nd_lvl_domain_lister}}
]]
local function single_ltr_2nd_lvl_domain_lister ()
local out_t = {}; -- output goes here
for _, tld in ipairs (cfg.single_letter_2nd_lvl_domains_t) do -- fetch each tld
table.insert (out_t, '.' .. tld); -- prefix with a dot and save in out_t{}
end
return table.concat (out_t, ', '); -- make a big string and done
end
--[[--------------------------< C O D E _ N A M E _ P A I R _ E X I S T S >----------------------------------------
Returns language code if pair exists, nil if either code doesn't exist or the name doesn't match.
Intended for use by Template:CS1 language sources/core
args[1] is language code
args[2] is language name
]]
local function code_name_pair_exists(frame)
local wiki_language = mw.getContentLanguage():getCode()
local source_list = mw.language.fetchLanguageNames(wiki_language, 'all');
local code_list = {};
local name_list = {};
local override = cfg.lang_tag_remap;
for code, name in pairs(source_list) do
add_to_list(code_list, name_list, override, code, name);
end
local args = getArgs(frame);
local language_code = args[1]
local language_name = args[2]
-- Check if the language code exists and the corresponding name matches
if code_list[language_code] == language_name then
-- Both code and name are a valid pair
return language_code
else
-- Either code doesn't exist or the name doesn't match
return nil
end
end
end
end
Line 1,223: Line 1,564:
canonical_name_get = canonical_name_get,
canonical_name_get = canonical_name_get,
cat_lister = cat_lister,
cat_lister = cat_lister,
code_name_pair_exists = code_name_pair_exists,
error_cat_page_tally = error_cat_page_tally,
header_make = header_make,
header_make = header_make,
help_text_cats = help_text_cats,
help_text_cats = help_text_cats,
Line 1,230: Line 1,573:
is_limited_param_template = is_limited_param_template,
is_limited_param_template = is_limited_param_template,
lang_lister = lang_lister,
lang_lister = lang_lister,
maint_cat_page_tally = maint_cat_page_tally,
script_lang_lister = script_lang_lister,
script_lang_lister = script_lang_lister,
single_ltr_2nd_lvl_domain_lister = single_ltr_2nd_lvl_domain_lister,
template_data_validate = template_data_validate,
template_data_validate = template_data_validate,
uncategorized_namespace_lister = uncategorized_namespace_lister,
};
};