Modifica di Modulo:Citation/CS1
Vai alla navigazione
Vai alla ricerca
Questa modifica può essere annullata. Controlla le differenze mostrate sotto fra le due versioni per essere certo che il contenuto corrisponda a quanto desiderato, e quindi pubblicare le modifiche per completare la procedura di annullamento.
Versione attuale | Il tuo testo | ||
Riga 1: | Riga 1: | ||
require(' | |||
require('Module:No globals'); | |||
--[[--------------------------< F O R W A R D D E C L A R A T I O N S >-------------------------------------- | --[[--------------------------< F O R W A R D D E C L A R A T I O N S >-------------------------------------- | ||
each of these counts against the Lua upvalue limit | each of these counts against the Lua upvalue limit | ||
]] | ]] | ||
Riga 10: | Riga 9: | ||
local utilities; -- functions in Module:Citation/CS1/Utilities | local utilities; -- functions in Module:Citation/CS1/Utilities | ||
local z = {}; -- table of tables in Module:Citation/CS1/Utilities | local z ={}; -- table of tables in Module:Citation/CS1/Utilities | ||
local identifiers; -- functions and tables in Module:Citation/CS1/Identifiers | local identifiers; -- functions and tables in Module:Citation/CS1/Identifiers | ||
Riga 16: | Riga 15: | ||
local cfg = {}; -- table of configuration tables that are defined in Module:Citation/CS1/Configuration | local cfg = {}; -- table of configuration tables that are defined in Module:Citation/CS1/Configuration | ||
local whitelist = {}; -- table of tables listing valid template parameter names; defined in Module:Citation/CS1/Whitelist | local whitelist = {}; -- table of tables listing valid template parameter names; defined in Module:Citation/CS1/Whitelist | ||
--[[------------------< P A G E S C O P E V A R I A B L E S >--------------- | --[[------------------< P A G E S C O P E V A R I A B L E S >--------------- | ||
declare variables here that have page-wide scope that are not brought in from | declare variables here that have page-wide scope that are not brought in from | ||
other modules; that are created here and used here | other modules; that are created here and used here | ||
]] | ]] | ||
local added_deprecated_cat; -- Boolean flag so that the category is added only once | local added_deprecated_cat; -- Boolean flag so that the category is added only once | ||
local added_discouraged_cat; -- Boolean flag so that the category is added only once | |||
local added_vanc_errs; -- Boolean flag so we only emit one Vancouver error / category | local added_vanc_errs; -- Boolean flag so we only emit one Vancouver error / category | ||
local Frame; -- holds the module's frame table | local Frame; -- holds the module's frame table | ||
--[[--------------------------< F I R S T _ S E T >------------------------------------------------------------ | --[[--------------------------< F I R S T _ S E T >------------------------------------------------------------ | ||
Riga 68: | Riga 60: | ||
added_vanc_errs = true; -- note that we've added this category | added_vanc_errs = true; -- note that we've added this category | ||
utilities.set_message ('err_vancouver', {source, position}); | table.insert( z.message_tail, { utilities.set_message ( 'err_vancouver', {source, position}, true ) } ); | ||
end | end | ||
Riga 154: | Riga 146: | ||
end | end | ||
for _, d in ipairs ( | for _, d in ipairs ({'cash', 'company', 'today', 'org'}) do -- look for single letter second level domain names for these top level domains | ||
if domain:match ('%f[%w][%w]%.' .. d) then | if domain:match ('%f[%w][%w]%.' .. d) then | ||
return true | return true | ||
Riga 265: | Riga 257: | ||
local function link_title_ok (link, lorig, title, torig) | local function link_title_ok (link, lorig, title, torig) | ||
local orig; | |||
if utilities.is_set (link) then -- don't bother if <param>-link doesn't have a value | if utilities.is_set (link) then -- don't bother if <param>-link doesn't have a value | ||
if not link_param_ok (link) then -- check |<param>-link= markup | if not link_param_ok (link) then -- check |<param>-link= markup | ||
Riga 282: | Riga 274: | ||
if utilities.is_set (orig) then | if utilities.is_set (orig) then | ||
link = ''; -- unset | link = ''; -- unset | ||
utilities.set_message ('err_bad_paramlink', orig); | table.insert( z.message_tail, { utilities.set_message ( 'err_bad_paramlink', orig)}); -- URL or wikilink in |title= with |title-link=; | ||
end | end | ||
Riga 357: | Riga 349: | ||
]] | ]] | ||
local function check_for_url (parameter_list | local function check_for_url (parameter_list) | ||
local error_message = ''; | |||
for k, v in pairs (parameter_list) do -- for each parameter in the list | for k, v in pairs (parameter_list) do -- for each parameter in the list | ||
if is_parameter_ext_wikilink (v) then -- look at the value; if there is a URL add an error message | if is_parameter_ext_wikilink (v) then -- look at the value; if there is a URL add an error message | ||
if utilities.is_set(error_message) then -- once we've added the first portion of the error message ... | |||
error_message = error_message .. ", "; -- ... add a comma space separator | |||
end | |||
error_message = error_message .. "|" .. k .. "="; -- add the failed parameter | |||
end | end | ||
end | |||
if utilities.is_set (error_message) then -- done looping, if there is an error message, display it | |||
table.insert( z.message_tail, { utilities.set_message ( 'err_param_has_ext_link', {error_message}, true ) } ); | |||
end | end | ||
end | end | ||
Riga 374: | Riga 373: | ||
local function safe_for_url( str ) | local function safe_for_url( str ) | ||
if str:match( "%[%[.-%]%]" ) ~= nil then | if str:match( "%[%[.-%]%]" ) ~= nil then | ||
utilities.set_message ('err_wikilink_in_url', {}); | table.insert( z.message_tail, { utilities.set_message ( 'err_wikilink_in_url', {}, true ) } ); | ||
end | end | ||
Riga 390: | Riga 389: | ||
]] | ]] | ||
local function external_link (URL, label, source, access) | local function external_link( URL, label, source, access) | ||
local | local error_str = ""; | ||
local domain; | local domain; | ||
local path; | local path; | ||
local base_url; | local base_url; | ||
if not utilities.is_set (label) then | if not utilities.is_set ( label ) then | ||
label = URL; | label = URL; | ||
if utilities.is_set (source) then | if utilities.is_set ( source ) then | ||
utilities.set_message ('err_bare_url_missing_title', {utilities.wrap_style ('parameter', source)}); | error_str = utilities.set_message ( 'err_bare_url_missing_title', { utilities.wrap_style ('parameter', source) }, false, " " ); | ||
else | else | ||
error (cfg.messages["bare_url_no_origin"]); | error( cfg.messages["bare_url_no_origin"] ); | ||
end | end | ||
end | end | ||
if not check_url (URL) then | if not check_url( URL ) then | ||
utilities.set_message ('err_bad_url', {utilities.wrap_style ('parameter', source)}); | error_str = utilities.set_message ( 'err_bad_url', {utilities.wrap_style ('parameter', source)}, false, " " ) .. error_str; | ||
end | end | ||
Riga 414: | Riga 413: | ||
end | end | ||
base_url = table.concat ({ "[", URL, " ", safe_for_url (label), "]" }); -- assemble a wiki-markup URL | base_url = table.concat({ "[", URL, " ", safe_for_url (label), "]" }); -- assemble a wiki-markup URL | ||
if utilities.is_set (access) then -- access level (subscription, registration, limited) | if utilities.is_set (access) then -- access level (subscription, registration, limited) | ||
base_url = utilities.substitute (cfg.presentation['ext-link-access-signal'], {cfg.presentation[access].class, cfg.presentation[access].title, base_url}); -- add the appropriate icon | base_url = utilities.substitute (cfg.presentation['ext-link-access-signal'], {cfg.presentation[access].class, cfg.presentation[access].title, base_url}); -- add the appropriate icon | ||
end | end | ||
return base_url; | return table.concat ({base_url, error_str}); | ||
end | end | ||
Riga 437: | Riga 436: | ||
if not added_deprecated_cat then | if not added_deprecated_cat then | ||
added_deprecated_cat = true; -- note that we've added this category | added_deprecated_cat = true; -- note that we've added this category | ||
utilities.set_message ('err_deprecated_params', {name}); | table.insert( z.message_tail, { utilities.set_message ( 'err_deprecated_params', {name}, true ) } ); -- add error message | ||
end | |||
end | |||
--[[--------------------------< D I S C O U R A G E D _ P A R A M E T E R >------------------------------------ | |||
Categorize and emit an maintenance message when the citation contains one or more discouraged parameters. Only | |||
one error message is emitted regardless of the number of discouraged parameters in the citation. | |||
added_discouraged_cat is a Boolean declared in page scope variables above | |||
]] | |||
local function discouraged_parameter(name) | |||
if not added_discouraged_cat then | |||
added_discouraged_cat = true; -- note that we've added this category | |||
table.insert( z.message_tail, { utilities.set_message ( 'maint_discouraged', {name}, true ) } ); -- add maint message | |||
end | end | ||
end | end | ||
Riga 461: | Riga 477: | ||
local function kern_quotes (str) | local function kern_quotes (str) | ||
local cap = ''; | local cap = ''; | ||
local cap2 = ''; | |||
local wl_type, label, link; | local wl_type, label, link; | ||
Riga 467: | Riga 484: | ||
if 1 == wl_type then -- [[D]] simple wikilink with or without quote marks | if 1 == wl_type then -- [[D]] simple wikilink with or without quote marks | ||
if mw.ustring.match (str, '%[%[[\"“”\'‘’].+[\"“”\'‘’]%]%]') then -- leading and trailing quote marks | if mw.ustring.match (str, '%[%[[\"“”\'‘’].+[\"“”\'‘’]%]%]') then -- leading and trailing quote marks | ||
str = utilities.substitute (cfg.presentation['kern- | str = utilities.substitute (cfg.presentation['kern-wl-both'], str); | ||
elseif mw.ustring.match (str, '%[%[[\"“”\'‘’].+%]%]') then -- leading quote marks | elseif mw.ustring.match (str, '%[%[[\"“”\'‘’].+%]%]') then -- leading quote marks | ||
str = utilities.substitute (cfg.presentation['kern-left'], str); | str = utilities.substitute (cfg.presentation['kern-wl-left'], str); | ||
elseif mw.ustring.match (str, '%[%[.+[\"“”\'‘’]%]%]') then -- trailing quote marks | elseif mw.ustring.match (str, '%[%[.+[\"“”\'‘’]%]%]') then -- trailing quote marks | ||
str = utilities.substitute (cfg.presentation['kern-right'], str); | str = utilities.substitute (cfg.presentation['kern-wl-right'], str); | ||
end | end | ||
Riga 479: | Riga 495: | ||
label = mw.ustring.gsub (label, '[‘’]', '\''); -- replace ‘’ (U+2018 & U+2019) with ' (typewriter single quote mark) | label = mw.ustring.gsub (label, '[‘’]', '\''); -- replace ‘’ (U+2018 & U+2019) with ' (typewriter single quote mark) | ||
cap = mw.ustring.match (label, "^([\"\'][^\'].+)"); | cap, cap2 = mw.ustring.match (label, "^([\"\'])([^\'].+)"); -- match leading double or single quote but not doubled single quotes (italic markup) | ||
if utilities.is_set (cap) then | if utilities.is_set (cap) then | ||
label = utilities.substitute (cfg.presentation['kern-left'], cap); | label = utilities.substitute (cfg.presentation['kern-left'], {cap, cap2}); | ||
end | end | ||
cap = mw.ustring.match (label, "^(.+[^\'][\"\'])$") | cap, cap2 = mw.ustring.match (label, "^(.+[^\'])([\"\'])$") -- match trailing double or single quote but not doubled single quotes (italic markup) | ||
if utilities.is_set (cap) then | if utilities.is_set (cap) then | ||
label = utilities.substitute (cfg.presentation['kern-right'], cap); | label = utilities.substitute (cfg.presentation['kern-right'], {cap, cap2}); | ||
end | end | ||
Riga 529: | Riga 545: | ||
lang = script_value:match('^(%l%l%l?)%s*:%s*%S.*'); -- get the language prefix or nil if there is no script | lang = script_value:match('^(%l%l%l?)%s*:%s*%S.*'); -- get the language prefix or nil if there is no script | ||
if not utilities.is_set (lang) then | if not utilities.is_set (lang) then | ||
utilities.set_message ('err_script_parameter', {script_param, | table.insert( z.message_tail, { utilities.set_message ( 'err_script_parameter', {script_param, 'missing title part'}, true ) } ); -- prefix without 'title'; add error message | ||
return ''; -- script_value was just the prefix so return empty string | return ''; -- script_value was just the prefix so return empty string | ||
end | end | ||
Riga 538: | Riga 554: | ||
-- is prefix one of these language codes? | -- is prefix one of these language codes? | ||
if utilities.in_array (lang, cfg.script_lang_codes) then | if utilities.in_array (lang, cfg.script_lang_codes) then | ||
utilities.add_prop_cat (' | utilities.add_prop_cat ('script_with_name', {name, lang}) | ||
else | else | ||
utilities.set_message ('err_script_parameter', {script_param, | table.insert( z.message_tail, { utilities.set_message ( 'err_script_parameter', {script_param, 'unknown language code'}, true ) } ); -- unknown script-language; add error message | ||
end | end | ||
lang = ' lang="' .. lang .. '" '; -- convert prefix into a lang attribute | lang = ' lang="' .. lang .. '" '; -- convert prefix into a lang attribute | ||
else | else | ||
utilities.set_message ('err_script_parameter', {script_param, | table.insert( z.message_tail, { utilities.set_message ( 'err_script_parameter', {script_param, 'invalid language code'}, true ) } ); -- invalid language code; add error message | ||
lang = ''; -- invalid so set lang to empty string | lang = ''; -- invalid so set lang to empty string | ||
end | end | ||
else | else | ||
utilities.set_message ('err_script_parameter', {script_param, | table.insert( z.message_tail, { utilities.set_message ( 'err_script_parameter', {script_param, 'missing prefix'}, true ) } ); -- no language code prefix; add error message | ||
end | end | ||
script_value = utilities.substitute (cfg.presentation['bdi'], {lang, script_value}); -- isolate in case script is RTL | script_value = utilities.substitute (cfg.presentation['bdi'], {lang, script_value}); -- isolate in case script is RTL | ||
Riga 558: | Riga 574: | ||
--[[--------------------------< S C R I P T _ C O N C A T E N A T E >------------------------------------------ | --[[--------------------------< S C R I P T _ C O N C A T E N A T E >------------------------------------------ | ||
Initially for |title= and |script-title=, this function concatenates those two parameter values after the script | Initially for |title= and |script-title=, this function concatenates those two parameter values after the script value has been | ||
value has been wrapped in <bdi> tags. | wrapped in <bdi> tags. | ||
]] | ]] | ||
Riga 658: | Riga 673: | ||
local function format_periodical (script_periodical, script_periodical_source, periodical, trans_periodical) | local function format_periodical (script_periodical, script_periodical_source, periodical, trans_periodical) | ||
local periodical_error = ''; | |||
if not utilities.is_set (periodical) then | if not utilities.is_set (periodical) then | ||
Riga 673: | Riga 689: | ||
else -- here when trans-periodical without periodical or script-periodical | else -- here when trans-periodical without periodical or script-periodical | ||
periodical = trans_periodical; | periodical = trans_periodical; | ||
utilities.set_message ('err_trans_missing_title', {'periodical'}); | periodical_error = ' ' .. utilities.set_message ('err_trans_missing_title', {'periodical'}); | ||
end | end | ||
end | end | ||
return periodical; | return periodical .. periodical_error; | ||
end | end | ||
Riga 690: | Riga 706: | ||
local function format_chapter_title (script_chapter, script_chapter_source, chapter, chapter_source, trans_chapter, trans_chapter_source, chapter_url, chapter_url_source, no_quotes, access) | local function format_chapter_title (script_chapter, script_chapter_source, chapter, chapter_source, trans_chapter, trans_chapter_source, chapter_url, chapter_url_source, no_quotes, access) | ||
local chapter_error = ''; | |||
local ws_url, ws_label, L = wikisource_url_make (chapter); -- make a wikisource URL and label from a wikisource interwiki link | local ws_url, ws_label, L = wikisource_url_make (chapter); -- make a wikisource URL and label from a wikisource interwiki link | ||
if ws_url then | if ws_url then | ||
Riga 721: | Riga 739: | ||
chapter = trans_chapter; | chapter = trans_chapter; | ||
chapter_source = trans_chapter_source:match ('trans%-?(.+)'); -- when no chapter, get matching name from trans-<param> | chapter_source = trans_chapter_source:match ('trans%-?(.+)'); -- when no chapter, get matching name from trans-<param> | ||
utilities.set_message ('err_trans_missing_title', {chapter_source}); | chapter_error = ' ' .. utilities.set_message ('err_trans_missing_title', {chapter_source}); | ||
end | end | ||
end | end | ||
return chapter; | return chapter .. chapter_error; | ||
end | end | ||
Riga 764: | Riga 782: | ||
if mw.ustring.find (v, cfg.indic_script) then -- it's ok if one of the Indic scripts | if mw.ustring.find (v, cfg.indic_script) then -- it's ok if one of the Indic scripts | ||
position = nil; -- unset position | position = nil; -- unset position | ||
elseif cfg. | elseif cfg.emoji[mw.ustring.codepoint (v, position+1)] then -- is zwj followed by a character listed in emoji{}? | ||
position = nil; -- unset position | position = nil; -- unset position | ||
end | end | ||
Riga 783: | Riga 801: | ||
end | end | ||
utilities.set_message ('err_invisible_char', {err_msg, utilities.wrap_style ('parameter', param), position}); -- add error message | table.insert (z.message_tail, {utilities.set_message ('err_invisible_char', {err_msg, utilities.wrap_style ('parameter', param), position}, true)}); -- add error message | ||
return; -- and done with this parameter | return; -- and done with this parameter | ||
end | end | ||
Riga 889: | Riga 907: | ||
--[[--------------------------< | --[[--------------------------< H Y P H E N _ T O _ D A S H >-------------------------------------------------- | ||
Converts a hyphen to a dash under certain conditions. The hyphen must separate | |||
like items; unlike items are returned unmodified. These forms are modified: | |||
letter - letter (A - B) | |||
digit - digit (4-5) | |||
digit separator digit - digit separator digit (4.1-4.5 or 4-1-4-5) | |||
letterdigit - letterdigit (A1-A5) (an optional separator between letter and | |||
digit is supported – a.1-a.5 or a-1-a-5) | |||
digitletter - digitletter (5a - 5d) (an optional separator between letter and | |||
digit is supported – 5.a-5.d or 5-a-5-d) | |||
any other forms are returned unmodified. | |||
str may be a comma- or semicolon-separated list | |||
]] | ]] | ||
local function safe_join( tbl, duplicate_char ) | local function hyphen_to_dash( str ) | ||
local f = {}; -- create a function table appropriate to type of 'duplicate character' | if not utilities.is_set (str) then | ||
if 1 == #duplicate_char then -- for single byte ASCII characters use the string library functions | return str; | ||
f.gsub = string.gsub | end | ||
f.match = string.match | |||
f.sub = string.sub | local accept; -- Boolean | ||
else -- for multi-byte characters use the ustring library functions | |||
f.gsub = mw.ustring.gsub | str = str:gsub ('&[nm]dash;', {['–'] = '–', ['—'] = '—'}); -- replace — and – entities with their characters; semicolon mucks up the text.split | ||
f.match = mw.ustring.match | str = str:gsub ('-', '-'); -- replace HTML numeric entity with hyphen character | ||
f.sub = mw.ustring.sub | |||
end | str = str:gsub (' ', ' '); -- replace entity with generic keyboard space character | ||
local out = {}; | |||
local list = mw.text.split (str, '%s*[,;]%s*'); -- split str at comma or semicolon separators if there are any | |||
for _, item in ipairs (list) do -- for each item in the list | |||
item, accept = utilities.has_accept_as_written (item); -- remove accept-this-as-written markup when it wraps all of item | |||
if not accept and mw.ustring.match (item, '^%w*[%.%-]?%w+%s*[%-–—]%s*%w*[%.%-]?%w+$') then -- if a hyphenated range or has endash or emdash separators | |||
if item:match ('^%a+[%.%-]?%d+%s*%-%s*%a+[%.%-]?%d+$') or -- letterdigit hyphen letterdigit (optional separator between letter and digit) | |||
item:match ('^%d+[%.%-]?%a+%s*%-%s*%d+[%.%-]?%a+$') or -- digitletter hyphen digitletter (optional separator between digit and letter) | |||
item:match ('^%d+[%.%-]%d+%s*%-%s*%d+[%.%-]%d+$') or -- digit separator digit hyphen digit separator digit | |||
item:match ('^%d+%s*%-%s*%d+$') or -- digit hyphen digit | |||
item:match ('^%a+%s*%-%s*%a+$') then -- letter hyphen letter | |||
item = item:gsub ('(%w*[%.%-]?%w+)%s*%-%s*(%w*[%.%-]?%w+)', '%1–%2'); -- replace hyphen, remove extraneous space characters | |||
else | |||
item = mw.ustring.gsub (item, '%s*[–—]%s*', '–'); -- for endash or emdash separated ranges, replace em with en, remove extraneous whitespace | |||
end | |||
end | |||
table.insert (out, item); -- add the (possibly modified) item to the output table | |||
end | |||
local temp_str = ''; -- concatenate the output table into a comma separated string | |||
temp_str, accept = utilities.has_accept_as_written (table.concat (out, ', ')); -- remove accept-this-as-written markup when it wraps all of concatenated out | |||
if accept then | |||
temp_str = utilities.has_accept_as_written (str); -- when global markup removed, return original str; do it this way to suppress boolean second return value | |||
return temp_str; | |||
else | |||
return temp_str; -- else, return assembled temp_str | |||
end | |||
end | |||
--[[--------------------------< S A F E _ J O I N >----------------------------- | |||
Joins a sequence of strings together while checking for duplicate separation characters. | |||
]] | |||
local function safe_join( tbl, duplicate_char ) | |||
local f = {}; -- create a function table appropriate to type of 'duplicate character' | |||
if 1 == #duplicate_char then -- for single byte ASCII characters use the string library functions | |||
f.gsub = string.gsub | |||
f.match = string.match | |||
f.sub = string.sub | |||
else -- for multi-byte characters use the ustring library functions | |||
f.gsub = mw.ustring.gsub | |||
f.match = mw.ustring.match | |||
f.sub = mw.ustring.sub | |||
end | |||
local str = ''; -- the output string | local str = ''; -- the output string | ||
Riga 975: | Riga 1 053: | ||
--[[--------------------------< I S _ S U F F I X >----------------------------- | --[[--------------------------< I S _ S U F F I X >----------------------------- | ||
returns true | returns true is suffix is properly formed Jr, Sr, or ordinal in the range 1–9. | ||
Puncutation not allowed. | Puncutation not allowed. | ||
Riga 1 108: | Riga 1 186: | ||
--[[--------------------------< I | --[[--------------------------< L I S T _ P E O P L E >-------------------------- | ||
Formats a list of people (authors, contributors, editors, interviewers, translators) | |||
names in the list will be linked when | |||
|<name>-link= has a value | |||
|<name>-mask- does NOT have a value; masked names are presumed to have been | |||
rendered previously so should have been linked there | |||
when |<name>-mask=0, the associated name is not rendered | |||
when |<name>-mask=0, the associated name is not rendered | |||
]] | ]] | ||
Riga 1 242: | Riga 1 253: | ||
one = utilities.make_wikilink (person.link, one); -- link author/editor | one = utilities.make_wikilink (person.link, one); -- link author/editor | ||
end | end | ||
if one then -- if <one> has a value (name, mdash replacement, or mask text replacement) | if one then -- if <one> has a value (name, mdash replacement, or mask text replacement) | ||
table.insert (name_list, one); -- add it to the list of names | table.insert (name_list, one); -- add it to the list of names | ||
table.insert (name_list, sep_one); -- add the proper name-list separator | table.insert (name_list, sep_one); -- add the proper name-list separator | ||
Riga 1 295: | Riga 1 283: | ||
return result, count; -- return name-list string and count of number of names (count used for editor names only) | return result, count; -- return name-list string and count of number of names (count used for editor names only) | ||
end | end | ||
--[[--------------------< M A K E _ C I T E R E F _ I D >----------------------- | --[[--------------------< M A K E _ C I T E R E F _ I D >----------------------- | ||
Riga 1 320: | Riga 1 307: | ||
return ''; -- return an empty string; no reason to include CITEREF id in this citation | return ''; -- return an empty string; no reason to include CITEREF id in this citation | ||
end | end | ||
end | end | ||
Riga 1 371: | Riga 1 332: | ||
etal = true; -- set flag (may have been set previously here or by |display-<names>=etal) | etal = true; -- set flag (may have been set previously here or by |display-<names>=etal) | ||
if not nocat then -- no categorization for |vauthors= | if not nocat then -- no categorization for |vauthors= | ||
utilities.set_message ('err_etal', {param}); | table.insert( z.message_tail, {utilities.set_message ('err_etal', {param})}); -- and set an error if not added | ||
end | end | ||
end | end | ||
Riga 1 395: | Riga 1 356: | ||
if mw.ustring.match (name, '^[%A]+$') then -- when name does not contain any letters | if mw.ustring.match (name, '^[%A]+$') then -- when name does not contain any letters | ||
utilities.set_message ('maint_numeric_names', cfg.special_case_translation [list_name]); -- add a maint cat for this template | utilities.set_message ('maint_numeric_names', cfg.special_case_translation [list_name]); -- add a maint cat for this template | ||
end | |||
end | |||
end | |||
--[[-------------------< N A M E _ H A S _ E D _ M A R K U P >------------------ | |||
Evaluates the content of author and editor parameters for extraneous editor annotations: | |||
ed, ed., eds, (Ed.), etc. These annotations do not belong in author parameters and | |||
are redundant in editor parameters. If found, the function adds the editor markup | |||
maintenance category. | |||
returns nothing | |||
]] | |||
local function name_has_ed_markup (name, list_name) | |||
local patterns = cfg.editor_markup_patterns; -- get patterns from configuration | |||
if utilities.is_set (name) then | |||
for _, pattern in ipairs (patterns) do -- spin through patterns table and | |||
if name:match (pattern) then | |||
utilities.set_message ('maint_extra_text_names', cfg.special_case_translation [list_name]); -- add a maint cat for this template | |||
break; | |||
end | |||
end | end | ||
end | end | ||
Riga 1 433: | Riga 1 419: | ||
--[ | --[[------------------------< N A M E _ C H E C K S >--------------------------- | ||
This function calls various name checking functions used to validate the content | |||
of the various name-holding parameters. | |||
]] | |||
local function name_checks (last, first, list_name) | |||
local accept_name; | |||
if utilities.is_set (last) then | |||
last, accept_name = utilities.has_accept_as_written (last); -- remove accept-this-as-written markup when it wraps all of <last> | |||
if not accept_name then -- <last> not wrapped in accept-as-written markup | |||
name_has_mult_names (last, list_name); -- check for multiple names in the parameter (last only) | |||
name_has_ed_markup (last, list_name); -- check for extraneous 'editor' annotation | |||
name_is_numeric (last, list_name); -- check for names that are composed of digits and punctuation | |||
end | |||
end | |||
if utilities.is_set (last) then | |||
last, accept_name = utilities.has_accept_as_written (last); -- remove accept-this-as-written markup when it wraps all of <last> | |||
if not accept_name then -- <last> not wrapped in accept-as-written markup | |||
name_has_mult_names (last, list_name); -- check for multiple names in the parameter (last only) | |||
end | |||
end | |||
if utilities.is_set (first) then | if utilities.is_set (first) then | ||
Riga 1 531: | Riga 1 443: | ||
if not accept_name then -- <first> not wrapped in accept-as-written markup | if not accept_name then -- <first> not wrapped in accept-as-written markup | ||
name_has_ed_markup (first, list_name); -- check for extraneous 'editor' annotation | |||
name_is_numeric (first, list_name); -- check for names that are composed of digits and punctuation | name_is_numeric (first, list_name); -- check for names that are composed of digits and punctuation | ||
end | end | ||
end | end | ||
Riga 1 546: | Riga 1 453: | ||
--[[----------------------< E X T R A C T _ N A M E S >------------------------- | --[[----------------------< E X T R A C T _ N A M E S >------------------------- | ||
Gets name list from the input arguments | Gets name list from the input arguments | ||
Riga 1 584: | Riga 1 490: | ||
link, link_alias = utilities.select_one ( args, cfg.aliases[list_name .. '-Link'], 'err_redundant_parameters', i ); | link, link_alias = utilities.select_one ( args, cfg.aliases[list_name .. '-Link'], 'err_redundant_parameters', i ); | ||
mask = utilities.select_one ( args, cfg.aliases[list_name .. '-Mask'], 'err_redundant_parameters', i ); | mask = utilities.select_one ( args, cfg.aliases[list_name .. '-Mask'], 'err_redundant_parameters', i ); | ||
last, etal = name_has_etal (last, etal, false, last_alias); -- find and remove variations on et al. | last, etal = name_has_etal (last, etal, false, last_alias); -- find and remove variations on et al. | ||
first, etal = name_has_etal (first, etal, false, first_alias); -- find and remove variations on et al. | first, etal = name_has_etal (first, etal, false, first_alias); -- find and remove variations on et al. | ||
last, first = name_checks (last, first, list_name | last, first = name_checks (last, first, list_name); -- multiple names, extraneous annotation, etc. checks | ||
if first and not last then -- if there is a firstn without a matching lastn | if first and not last then -- if there is a firstn without a matching lastn | ||
local alias = first_alias:find ('given', 1, true) and 'given' or 'first'; -- get first or given form of the alias | local alias = first_alias:find ('given', 1, true) and 'given' or 'first'; -- get first or given form of the alias | ||
utilities.set_message ('err_first_missing_last', { | table.insert (z.message_tail, { utilities.set_message ( 'err_first_missing_last', { | ||
first_alias, -- param name of alias missing its mate | first_alias, -- param name of alias missing its mate | ||
first_alias:gsub (alias, {['first'] = 'last', ['given'] = 'surname'}), -- make param name appropriate to the alias form | first_alias:gsub (alias, {['first'] = 'last', ['given'] = 'surname'}), -- make param name appropriate to the alias form | ||
}); | }, true ) } ); -- add this error message | ||
elseif not first and not last then -- if both firstn and lastn aren't found, are we done? | elseif not first and not last then -- if both firstn and lastn aren't found, are we done? | ||
count = count + 1; -- number of times we haven't found last and first | count = count + 1; -- number of times we haven't found last and first | ||
Riga 1 620: | Riga 1 509: | ||
local result; | local result; | ||
link = link_title_ok (link, link_alias, last, last_alias); -- check for improper wiki-markup | link = link_title_ok (link, link_alias, last, last_alias); -- check for improper wiki-markup | ||
if first then | if first then | ||
link = link_title_ok (link, link_alias, first, first_alias); -- check for improper wiki-markup | link = link_title_ok (link, link_alias, first, first_alias); -- check for improper wiki-markup | ||
Riga 1 628: | Riga 1 516: | ||
n = n + 1; -- point to next location in the names table | n = n + 1; -- point to next location in the names table | ||
if 1 == count then -- if the previous name was missing | if 1 == count then -- if the previous name was missing | ||
utilities.set_message ('err_missing_name', {list_name:match ("(%w+)List"):lower(), i - 1}); -- add this error message | table.insert( z.message_tail, { utilities.set_message ( 'err_missing_name', {list_name:match ("(%w+)List"):lower(), i - 1}, true ) } ); -- add this error message | ||
end | end | ||
count = 0; -- reset the counter, we're looking for two consecutive missing names | count = 0; -- reset the counter, we're looking for two consecutive missing names | ||
Riga 1 639: | Riga 1 527: | ||
--[[ | --[[---------------------< G E T _ I S O 6 3 9 _ C O D E >---------------------- | ||
Validates language names provided in |language= parameter if not an ISO639-1 or 639-2 code. | |||
Returns the language name and associated two- or three-character code. Because | |||
case of the source may be incorrect or different from the case that WikiMedia uses, | |||
the name comparisons are done in lower case and when a match is found, the Wikimedia | |||
version (assumed to be correct) is returned along with the code. When there is no | |||
match, we return the original language name string. | |||
mw.language.fetchLanguageNames(<local wiki language>, 'all') returns a list of | |||
languages that in some cases may include extensions. For example, code 'cbk-zam' | |||
and its associated name 'Chavacano de Zamboanga' (MediaWiki does not support | |||
code 'cbk' or name 'Chavacano'. Most (all?) of these languages are not used a | |||
'language' codes per se, rather they are used as sub-domain names: cbk-zam.wikipedia.org. | |||
A list of language names and codes supported by fetchLanguageNames() can be found | |||
at Template:Citation Style documentation/language/doc | |||
Names that are included in the list will be found if that name is provided in the | |||
|language= parameter. For example, if |language=Chavacano de Zamboanga, that name | |||
will be found with the associated code 'cbk-zam'. When names are found and the | |||
associated code is not two or three characters, this function returns only the | |||
WikiMedia language name. | |||
Some language names have multiple entries under different codes: | |||
Aromanian has code rup and code roa-rup | |||
When this occurs, this function returns the language name and the 2- or 3-character code | |||
Adapted from code taken from Module:Check ISO 639-1. | |||
]] | |||
if cfg.lang_name_remap[ | local function get_iso639_code (lang, this_wiki_code) | ||
return cfg.lang_name_remap[ | if cfg.lang_name_remap[lang:lower()] then -- if there is a remapped name (because MediaWiki uses something that we don't think is correct) | ||
return cfg.lang_name_remap[lang:lower()][1], cfg.lang_name_remap[lang:lower()][2]; -- for this language 'name', return a possibly new name and appropriate code | |||
end | end | ||
local ietf_code; -- because some languages have both IETF-like codes and ISO 639-like codes | |||
local ietf_name; | |||
local langlc = mw.ustring.lower (lang); -- lower-case version for comparisons | |||
name | for code, name in pairs (cfg.languages) do -- scan the list to see if we can find our language | ||
if langlc == mw.ustring.lower (name) then | |||
if 2 == #code or 3 == #code then -- two- or three-character codes only; IETF extensions not supported | |||
return name, code; -- so return the name and the code | |||
end | |||
ietf_code = code; -- remember that we found an IETF-like code and save its name | |||
ietf_name = name; -- but keep looking for a 2- or 3-char code | |||
end | end | ||
end | end | ||
-- didn't find name with 2- or 3-char code; if IETF-like code found return | |||
return ietf_code and ietf_name or lang; -- associated name; return original language text else | |||
end | end | ||
Riga 1 722: | Riga 1 605: | ||
local function language_parameter (lang) | local function language_parameter (lang) | ||
local | local code; -- the two- or three-character language code | ||
local name; -- the language name | local name; -- the language name | ||
local language_list = {}; -- table of language names to be rendered | local language_list = {}; -- table of language names to be rendered | ||
local | local names_table = {}; -- table made from the value assigned to |language= | ||
local this_wiki_name = mw.language.fetchLanguageName (cfg.this_wiki_code, cfg.this_wiki_code); -- get this wiki's language name | local this_wiki_name = mw.language.fetchLanguageName (cfg.this_wiki_code, cfg.this_wiki_code); -- get this wiki's language name | ||
names_table = mw.text.split (lang, '%s*,%s*'); -- names should be a comma separated list | |||
for _, lang in ipairs ( | for _, lang in ipairs (names_table) do -- reuse lang | ||
name = cfg.lang_code_remap[lang:lower()]; -- first see if this is a code that is not supported by MediaWiki but is in remap | |||
if name then -- there was a remapped code so | |||
if not lang:match ('^%a%a%a?%-x%-%a+$') then -- if not a private IETF tag | |||
lang = lang:gsub ('^(%a%a%a?)%-.*', '%1'); -- strip IETF tags from code | |||
end | |||
else | |||
lang = lang:gsub ('^(%a%a%a?)%-.*', '%1'); -- strip any IETF-like tags from code | |||
if 2 == lang:len() or 3 == lang:len() then -- if two-or three-character code | |||
name = mw.language.fetchLanguageName (lang:lower(), cfg.this_wiki_code); -- get language name if |language= is a proper code | |||
end | |||
end | |||
if utilities.is_set ( | if utilities.is_set (name) then -- if |language= specified a valid code | ||
code = lang:lower(); -- save it | |||
else | |||
name, code = get_iso639_code (lang, cfg.this_wiki_code); -- attempt to get code from name (assign name here so that we are sure of proper capitalization) | |||
end | |||
if utilities.is_set (code) then -- only 2- or 3-character codes | |||
name = cfg.lang_code_remap[code] or name; -- override wikimedia when they misuse language codes/names | |||
if cfg.this_wiki_code ~= | if cfg.this_wiki_code ~= code then -- when the language is not the same as this wiki's language | ||
if 2 == | if 2 == code:len() then -- and is a two-character code | ||
utilities.add_prop_cat (' | utilities.add_prop_cat ('foreign_lang_source' .. code, {name, code}); -- categorize it; code appended to allow for multiple language categorization | ||
else -- or is a recognized language (but has a three-character | else -- or is a recognized language (but has a three-character code) | ||
utilities.add_prop_cat (' | utilities.add_prop_cat ('foreign_lang_source_2' .. code, {code}); -- categorize it differently TODO: support multiple three-character code categories per cs1|2 template | ||
end | end | ||
elseif cfg.local_lang_cat_enable then -- when the language and this wiki's language are the same and categorization is enabled | elseif cfg.local_lang_cat_enable then -- when the language and this wiki's language are the same and categorization is enabled | ||
utilities.add_prop_cat (' | utilities.add_prop_cat ('local_lang_source', {name, code}); -- categorize it | ||
end | end | ||
else | else | ||
utilities.set_message ('maint_unknown_lang'); -- add maint category if not already added | utilities.set_message ('maint_unknown_lang'); -- add maint category if not already added | ||
end | end | ||
Riga 1 757: | Riga 1 655: | ||
name = utilities.make_sep_list (#language_list, language_list); | name = utilities.make_sep_list (#language_list, language_list); | ||
if | |||
if this_wiki_name == name then | |||
return ''; -- if one language and that language is this wiki's return an empty string (no annotation) | return ''; -- if one language and that language is this wiki's return an empty string (no annotation) | ||
end | end | ||
Riga 1 765: | Riga 1 664: | ||
]] | ]] | ||
end | end | ||
--[[-----------------------< S E T _ C S _ S T Y L E >-------------------------- | --[[-----------------------< S E T _ C S _ S T Y L E >-------------------------- | ||
Gets the default CS style configuration for the given mode. | Gets the default CS style configuration for the given mode. | ||
Returns default separator and either postscript as passed in or the default. | Returns default separator and either postscript as passed in or the default. | ||
In CS1, the default postscript and separator are '.'. | In CS1, the default postscript and separator are '.'. | ||
In CS2, the default postscript is the empty string and the default separator is ','. | In CS2, the default postscript is the empty string and the default separator is ','. | ||
]] | ]] | ||
local function set_cs_style (postscript, mode) | local function set_cs_style (postscript, mode) | ||
if utilities.is_set(postscript) then | if utilities.is_set(postscript) then | ||
Riga 1 788: | Riga 1 683: | ||
return cfg.presentation['sep_' .. mode], postscript; | return cfg.presentation['sep_' .. mode], postscript; | ||
end | end | ||
--[[--------------------------< S E T _ S T Y L E >----------------------------- | --[[--------------------------< S E T _ S T Y L E >----------------------------- | ||
Sets the separator and postscript styles. Checks the |mode= first and the | Sets the separator and postscript styles. Checks the |mode= first and the | ||
#invoke CitationClass second. Removes the postscript if postscript == none. | #invoke CitationClass second. Removes the postscript if postscript == none. | ||
]] | ]] | ||
local function set_style (mode, postscript, cite_class) | local function set_style (mode, postscript, cite_class) | ||
local sep; | local sep; | ||
Riga 1 820: | Riga 1 711: | ||
return sep, postscript | return sep, postscript | ||
end | end | ||
--[=[-------------------------< I S _ P D F >----------------------------------- | --[=[-------------------------< I S _ P D F >----------------------------------- | ||
Riga 1 852: | Riga 1 742: | ||
format = utilities.wrap_style ('format', format); -- add leading space, parentheses, resize | format = utilities.wrap_style ('format', format); -- add leading space, parentheses, resize | ||
if not utilities.is_set (url) then | if not utilities.is_set (url) then | ||
utilities.set_message ('err_format_missing_url', {fmt_param, url_param}); -- add an error message | format = format .. ' ' .. utilities.set_message ( 'err_format_missing_url', {fmt_param, url_param} ); -- add an error message | ||
end | end | ||
elseif is_pdf (url) then -- format is not set so if URL is a PDF file then | elseif is_pdf (url) then -- format is not set so if URL is a PDF file then | ||
Riga 1 894: | Riga 1 784: | ||
max = tonumber (max); -- make it a number | max = tonumber (max); -- make it a number | ||
if max >= count then -- if |display-xxxxors= value greater than or equal to number of authors/editors | if max >= count then -- if |display-xxxxors= value greater than or equal to number of authors/editors | ||
utilities.set_message ('err_disp_name', {param, max}); | table.insert( z.message_tail, {utilities.set_message ('err_disp_name', {param, max}, true)}); -- add error message | ||
max = nil; | max = nil; | ||
end | end | ||
else -- not a valid keyword or number | else -- not a valid keyword or number | ||
utilities.set_message ('err_disp_name', {param, max}); -- add error message | table.insert( z.message_tail, {utilities.set_message ('err_disp_name', {param, max}, true)}); -- add error message | ||
max = nil; -- unset; as if |display-xxxxors= had not been set | max = nil; -- unset; as if |display-xxxxors= had not been set | ||
end | end | ||
Riga 1 923: | Riga 1 813: | ||
for _, pattern in ipairs (cfg.vol_iss_pg_patterns.bad_ppatterns) do -- spin through the selected sequence table of patterns | for _, pattern in ipairs (cfg.vol_iss_pg_patterns.bad_ppatterns) do -- spin through the selected sequence table of patterns | ||
if val:match (pattern) then -- when a match, error so | if val:match (pattern) then -- when a match, error so | ||
utilities.set_message ('err_extra_text_pages', name); | table.insert (z.message_tail, {utilities.set_message ('err_extra_text_pages', {name}, true)}); -- add error message | ||
return; -- and done | return; -- and done | ||
end | end | ||
Riga 1 966: | Riga 1 856: | ||
for _, pattern in ipairs (patterns) do -- spin through the selected sequence table of patterns | for _, pattern in ipairs (patterns) do -- spin through the selected sequence table of patterns | ||
if val:match (pattern) then -- when a match, error so | if val:match (pattern) then -- when a match, error so | ||
utilities.set_message (handler, name); | table.insert (z.message_tail, {utilities.set_message (handler, {name}, true)}); -- add error message | ||
return; -- and done | return; -- and done | ||
end | end | ||
Riga 2 138: | Riga 2 028: | ||
err_name = 'editor'; | err_name = 'editor'; | ||
end | end | ||
utilities.set_message ('err_redundant_parameters', err_name .. '-name-list parameters'); -- add error message | table.insert( z.message_tail, { utilities.set_message ( 'err_redundant_parameters', | ||
{err_name .. '-name-list parameters'}, true ) } ); -- add error message | |||
end | end | ||
Riga 2 155: | Riga 2 046: | ||
of the list of allowed values returns the translated value; else, emits an error message and returns the value | of the list of allowed values returns the translated value; else, emits an error message and returns the value | ||
specified by ret_val. | specified by ret_val. | ||
]] | ]] | ||
local function is_valid_parameter_value (value, name, possible, ret_val | local function is_valid_parameter_value (value, name, possible, ret_val) | ||
if not utilities.is_set (value) then | if not utilities.is_set (value) then | ||
return ret_val; -- an empty parameter is ok | return ret_val; -- an empty parameter is ok | ||
elseif utilities.in_array (value, possible) then | |||
return cfg.keywords_xlate[value]; -- return translation of parameter keyword | return cfg.keywords_xlate[value]; -- return translation of parameter keyword | ||
else | else | ||
utilities.set_message ('err_invalid_param_val', {name, value}); | table.insert( z.message_tail, { utilities.set_message ( 'err_invalid_param_val', {name, value}, true ) } ); -- not an allowed value so add error message | ||
return ret_val; | return ret_val; | ||
end | end | ||
Riga 2 196: | Riga 2 081: | ||
--[[-------------------------< F O R M A T _ V O L U M E _ I S S U E > | --[[-------------------------< F O R M A T _ V O L U M E _ I S S U E >---------------------------------------- | ||
returns the concatenation of the formatted volume and issue | returns the concatenation of the formatted volume and issue parameters as a single string; or formatted volume | ||
string; or formatted volume or formatted issue, or an empty string if neither are set. | or formatted issue, or an empty string if neither are set. | ||
]] | ]] | ||
local function format_volume_issue (volume, issue | local function format_volume_issue (volume, issue, cite_class, origin, sepc, lower) | ||
if not utilities.is_set (volume) and not utilities.is_set (issue | if not utilities.is_set (volume) and not utilities.is_set (issue) then | ||
return ''; | return ''; | ||
end | end | ||
if volume and ( | if 'magazine' == cite_class or (utilities.in_array (cite_class, {'citation', 'map'}) and 'magazine' == origin) then | ||
utilities. | if utilities.is_set (volume) and utilities.is_set (issue) then | ||
return wrap_msg ('vol-no', {sepc, hyphen_to_dash (volume), issue}, lower); | |||
elseif utilities.is_set (volume) then | |||
return wrap_msg ('vol', {sepc, hyphen_to_dash (volume)}, lower); | |||
else | |||
return wrap_msg ('issue', {sepc, issue}, lower); | |||
end | |||
end | end | ||
if 'podcast' == cite_class and utilities.is_set (issue) then | if 'podcast' == cite_class and utilities.is_set (issue) then | ||
return wrap_msg ('issue', {sepc, issue}, lower); | return wrap_msg ('issue', {sepc, issue}, lower); | ||
end | end | ||
if | local vol = ''; -- here for all cites except magazine | ||
if utilities.is_set (volume) then | |||
if volume:match ('^[MDCLXVI]+$') or volume:match ('^%d+$') then -- volume value is all digits or all uppercase Roman numerals | |||
vol = utilities.substitute (cfg.presentation['vol-bold'], {sepc, volume}); -- render in bold face | |||
elseif (4 < mw.ustring.len(volume)) then -- not all digits or Roman numerals and longer than 4 characters | |||
vol = utilities.substitute (cfg.messages['j-vol'], {sepc, hyphen_to_dash (volume)}); -- not bold | |||
utilities.add_prop_cat ('long_vol'); | |||
else -- four or less characters | |||
vol = utilities.substitute (cfg.presentation['vol-bold'], {sepc, hyphen_to_dash (volume)}); -- bold | |||
end | end | ||
end | end | ||
if utilities.is_set (issue) then | |||
return vol .. utilities.substitute (cfg.messages['j-issue'], issue); | |||
if | |||
return | |||
end | end | ||
return vol; | |||
end | end | ||
Riga 2 375: | Riga 2 243: | ||
if utilities.is_set (archive) then | if utilities.is_set (archive) then | ||
if archive == url or archive == c_url then | if archive == url or archive == c_url then | ||
utilities.set_message ('err_bad_url', {utilities.wrap_style ('parameter', source)}); -- add error message | table.insert (z.message_tail, {utilities.set_message ('err_bad_url', {utilities.wrap_style ('parameter', source)}, true)}); -- add error message | ||
return '', ''; -- unset |archive-url= and |archive-date= because same as |url= or |chapter-url= | return '', ''; -- unset |archive-url= and |archive-date= because same as |url= or |chapter-url= | ||
end | end | ||
Riga 2 432: | Riga 2 300: | ||
else | else | ||
path, timestamp, flag = url:match('//web%.archive%.org/([^%d]*)(%d+)([^/]*)/'); -- split out some of the URL parts for evaluation | path, timestamp, flag = url:match('//web%.archive%.org/([^%d]*)(%d+)([^/]*)/'); -- split out some of the URL parts for evaluation | ||
if not | |||
if not utilities.is_set (timestamp) or 14 ~= timestamp:len() then -- path and flag optional, must have 14-digit timestamp here | |||
err_msg = cfg.err_msg_supl.timestamp; | err_msg = cfg.err_msg_supl.timestamp; | ||
if '*' ~= flag then | if '*' ~= flag then | ||
url=url:gsub ('(//web%.archive%.org/[^%d]*%d?%d?%d?%d?%d?%d?)[^/]*', '%1*', 1) -- for preview, modify ts to be yearmo* max (0-6 digits plus splat) | |||
end | end | ||
elseif utilities.is_set (path) and 'web/' ~= path then -- older archive URLs do not have the extra 'web/' path element | elseif utilities.is_set (path) and 'web/' ~= path then -- older archive URLs do not have the extra 'web/' path element | ||
Riga 2 454: | Riga 2 317: | ||
end | end | ||
-- if here, something not right so | -- if here, something not right so | ||
utilities.set_message ('err_archive_url', {err_msg}); | table.insert( z.message_tail, { utilities.set_message ( 'err_archive_url', {err_msg}, true ) } ); -- add error message and | ||
if utilities.is_set (Frame:preprocess('{{REVISIONID}}')) then | |||
if | return '', ''; -- return empty strings for ArchiveURL and ArchiveDate | ||
else | |||
return url, date; -- preview mode so return ArchiveURL and ArchiveDate | return url, date; -- preview mode so return ArchiveURL and ArchiveDate | ||
end | end | ||
end | end | ||
Riga 2 486: | Riga 2 348: | ||
--[[--------------------------< I S _ | --[[--------------------------< I S _ G E N E R I C _ T I T L E >---------------------------------------------- | ||
compares |title= value against list of known generic title patterns. Returns true when pattern matches; nil else | |||
the k/v pairs in 'generic_titles' each contain two tables, one for English and one for another 'local' language | |||
Each of those tables contain another table that holds the string or pattern (whole title or title fragment) in | |||
index [1]. index [2] is a Boolean that tells string.find() or mw.ustring.find() to do plain-text search (true) | |||
or a pattern search (false). The intent of all this complexity is to make these searches as fast as possible so | |||
that we don't run out of processing time on very large articles. | |||
]] | ]] | ||
local function | local function is_generic_title (title) | ||
title = mw.ustring.lower(title); -- switch title to lower case | title = mw.ustring.lower(title); -- switch title to lower case | ||
if title:find (cfg.special_case_translation.archived_copy.en) then -- if title is 'Archived copy' | for _, generic_title in ipairs (cfg.special_case_translation['generic_titles']) do -- spin through the list of known generic title fragments | ||
return true; | if title:find (generic_title['en'][1], 1, generic_title['en'][2]) then | ||
elseif cfg.special_case_translation.archived_copy['local'] then | return true; -- found English generic title so done | ||
if mw.ustring.find (title, cfg.special_case_translation.archived_copy['local']) then -- mw.ustring() because might not be Latin script | elseif generic_title['local'] then -- to keep work load down, generic_title['local'] should be nil except when there is a local version of the generic title | ||
return true; | if mw.ustring.find (title, generic_title['local'][1], 1, generic_title['local'][2]) then -- mw.ustring() because might not be Latin script | ||
return true; -- found local generic title so done | |||
end | |||
end | |||
end | |||
end | |||
--[[--------------------------< I S _ A R C H I V E D _ C O P Y >---------------------------------------------- | |||
compares |title= to 'Archived copy' (placeholder added by bots that can't find proper title); if matches, return true; nil else | |||
]] | |||
local function is_archived_copy (title) | |||
title = mw.ustring.lower(title); -- switch title to lower case | |||
if title:find (cfg.special_case_translation.archived_copy.en) then -- if title is 'Archived copy' | |||
return true; | |||
elseif cfg.special_case_translation.archived_copy['local'] then | |||
if mw.ustring.find (title, cfg.special_case_translation.archived_copy['local']) then -- mw.ustring() because might not be Latin script | |||
return true; | |||
end | end | ||
end | end | ||
Riga 2 571: | Riga 2 459: | ||
if 0 < #c then | if 0 < #c then | ||
if not utilities.is_set (Contribution) then -- |contributor= requires |contribution= | if not utilities.is_set (Contribution) then -- |contributor= requires |contribution= | ||
utilities.set_message ('err_contributor_missing_required_param', 'contribution'); -- add missing contribution error message | table.insert( z.message_tail, { utilities.set_message ( 'err_contributor_missing_required_param', 'contribution')}); -- add missing contribution error message | ||
c = {}; -- blank the contributors' table; it is used as a flag later | c = {}; -- blank the contributors' table; it is used as a flag later | ||
end | end | ||
if 0 == #a then -- |contributor= requires |author= | if 0 == #a then -- |contributor= requires |author= | ||
utilities.set_message ('err_contributor_missing_required_param', 'author'); -- add missing author error message | table.insert( z.message_tail, { utilities.set_message ( 'err_contributor_missing_required_param', 'author')}); -- add missing author error message | ||
c = {}; -- blank the contributors' table; it is used as a flag later | c = {}; -- blank the contributors' table; it is used as a flag later | ||
end | end | ||
Riga 2 581: | Riga 2 469: | ||
else -- if not a book cite | else -- if not a book cite | ||
if utilities.select_one (args, cfg.aliases['ContributorList-Last'], 'err_redundant_parameters', 1 ) then -- are there contributor name list parameters? | if utilities.select_one (args, cfg.aliases['ContributorList-Last'], 'err_redundant_parameters', 1 ) then -- are there contributor name list parameters? | ||
utilities.set_message ('err_contributor_ignored'); | table.insert( z.message_tail, { utilities.set_message ( 'err_contributor_ignored')}); -- add contributor ignored error message | ||
end | end | ||
Contribution = nil; -- unset | Contribution = nil; -- unset | ||
Riga 2 591: | Riga 2 479: | ||
local auto_select = ''; -- default is auto | local auto_select = ''; -- default is auto | ||
local accept_link; | local accept_link; | ||
TitleLink, accept_link = utilities.has_accept_as_written (TitleLink, true); -- test for accept-this-as-written markup | TitleLink, accept_link = utilities.has_accept_as_written(TitleLink, true); -- test for accept-this-as-written markup | ||
if (not accept_link) and utilities.in_array (TitleLink, {'none', 'pmc', 'doi'}) then -- check for special keywords | if (not accept_link) and utilities.in_array (TitleLink, {'none', 'pmc', 'doi'}) then -- check for special keywords | ||
auto_select = TitleLink; -- remember selection for later | auto_select = TitleLink; -- remember selection for later | ||
Riga 2 612: | Riga 2 500: | ||
Periodical, i = utilities.strip_apostrophe_markup (Periodical); -- strip apostrophe markup so that metadata isn't contaminated | Periodical, i = utilities.strip_apostrophe_markup (Periodical); -- strip apostrophe markup so that metadata isn't contaminated | ||
if i then -- non-zero when markup was stripped so emit an error message | if i then -- non-zero when markup was stripped so emit an error message | ||
utilities.set_message ('err_apostrophe_markup', {Periodical_origin}); | table.insert( z.message_tail, {utilities.set_message ('err_apostrophe_markup', {Periodical_origin}, true)}); | ||
end | end | ||
end | end | ||
if 'mailinglist' == config.CitationClass then -- special case for {{cite mailing list}} | if 'mailinglist' == config.CitationClass then -- special case for {{cite mailing list}} | ||
if utilities.is_set (Periodical) and utilities.is_set (A ['MailingList']) then -- both set emit an error | if utilities.is_set (Periodical) and utilities.is_set (A ['MailingList']) then -- both set emit an error | ||
utilities.set_message ('err_redundant_parameters', {utilities.wrap_style ('parameter', Periodical_origin) .. | table.insert( z.message_tail, {utilities.set_message ('err_redundant_parameters', {utilities.wrap_style ('parameter', Periodical_origin) .. ' and ' .. utilities.wrap_style ('parameter', 'mailinglist')}, true )}); | ||
end | end | ||
Riga 2 633: | Riga 2 521: | ||
local p = {['journal'] = 'journal', ['magazine'] = 'magazine'}; -- for error message | local p = {['journal'] = 'journal', ['magazine'] = 'magazine'}; -- for error message | ||
if p[config.CitationClass] then | if p[config.CitationClass] then | ||
utilities.set_message ('err_missing_periodical', {config.CitationClass, p[config.CitationClass]}); | table.insert( z.message_tail, {utilities.set_message ('err_missing_periodical', {config.CitationClass, p[config.CitationClass]}, true)}); | ||
end | end | ||
end | end | ||
Riga 2 641: | Riga 2 529: | ||
if 'citation' == config.CitationClass then | if 'citation' == config.CitationClass then | ||
if utilities.is_set (Periodical) then | if utilities.is_set (Periodical) then | ||
if not utilities.in_array (Periodical_origin, | if not utilities.in_array (Periodical_origin, {'website', 'mailinglist'}) then -- {{citation}} does not render volume for these 'periodicals' | ||
Volume = A['Volume']; -- but does for all other 'periodicals' | Volume = A['Volume']; -- but does for all other 'periodicals' | ||
end | end | ||
Riga 2 658: | Riga 2 546: | ||
local Issue; | local Issue; | ||
if 'citation' == config.CitationClass then | if 'citation' == config.CitationClass then | ||
if utilities.is_set (Periodical) and utilities.in_array (Periodical_origin, | if utilities.is_set (Periodical) and utilities.in_array (Periodical_origin, {'journal', 'magazine', 'newspaper', 'periodical', 'work'}) or -- {{citation}} renders issue for these 'periodicals' | ||
Issue = | utilities.is_set (ScriptPeriodical) and utilities.in_array (ScriptPeriodical_origin, {'script-journal', 'script-magazine', 'script-newspaper', 'script-periodical', 'script-work'}) then -- and these 'script-periodicals' | ||
Issue = hyphen_to_dash (A['Issue']); | |||
end | end | ||
elseif utilities.in_array (config.CitationClass, cfg.templates_using_issue) then -- conference & map books do not support issue; {{citation}} listed here because included in settings table | elseif utilities.in_array (config.CitationClass, cfg.templates_using_issue) then -- conference & map books do not support issue; {{citation}} listed here because included in settings table | ||
if not (utilities.in_array (config.CitationClass, {'conference', 'map', 'citation'}) and not (utilities.is_set (Periodical) or utilities.is_set (ScriptPeriodical))) then | if not (utilities.in_array (config.CitationClass, {'conference', 'map', 'citation'}) and not (utilities.is_set (Periodical) or utilities.is_set (ScriptPeriodical))) then | ||
Issue = | Issue = hyphen_to_dash (A['Issue']); | ||
end | end | ||
end | end | ||
extra_text_in_vol_iss_check (Issue, A:ORIGIN ('Issue'), 'i'); | extra_text_in_vol_iss_check (Issue, A:ORIGIN ('Issue'), 'i'); | ||
Riga 2 678: | Riga 2 560: | ||
local Pages; | local Pages; | ||
local At; | local At; | ||
if not utilities.in_array (config.CitationClass, cfg.templates_not_using_page) then | |||
if not utilities.in_array (config.CitationClass, cfg.templates_not_using_page) then | |||
Page = A['Page']; | Page = A['Page']; | ||
Pages = | Pages = hyphen_to_dash (A['Pages']); | ||
At = A['At']; | At = A['At']; | ||
end | end | ||
Riga 2 698: | Riga 2 576: | ||
PublisherName, i = utilities.strip_apostrophe_markup (PublisherName); -- strip apostrophe markup so that metadata isn't contaminated; publisher is never italicized | PublisherName, i = utilities.strip_apostrophe_markup (PublisherName); -- strip apostrophe markup so that metadata isn't contaminated; publisher is never italicized | ||
if i then -- non-zero when markup was stripped so emit an error message | if i then -- non-zero when markup was stripped so emit an error message | ||
utilities.set_message ('err_apostrophe_markup', {PublisherName_origin}); | table.insert( z.message_tail, {utilities.set_message ('err_apostrophe_markup', {PublisherName_origin}, true)}); | ||
end | end | ||
end | end | ||
Riga 2 707: | Riga 2 585: | ||
if 'newsgroup' == config.CitationClass then | if 'newsgroup' == config.CitationClass then | ||
if utilities.is_set (PublisherName) then -- general use parameter |publisher= not allowed in cite newsgroup | if utilities.is_set (PublisherName) then -- general use parameter |publisher= not allowed in cite newsgroup | ||
utilities.set_message ('err_parameter_ignored', {PublisherName_origin}); | local error_text, error_state = utilities.set_message ('err_parameter_ignored', {PublisherName_origin}, true); | ||
if utilities.is_set (error_text) then | |||
table.insert( z.message_tail, {error_text, error_state} ); | |||
end | |||
end | end | ||
Riga 2 713: | Riga 2 594: | ||
end | end | ||
local URL = A['URL'] | local URL = A['URL'] | ||
local UrlAccess = is_valid_parameter_value (A['UrlAccess'], A:ORIGIN('UrlAccess'), cfg.keywords_lists['url-access'], nil); | local UrlAccess = is_valid_parameter_value (A['UrlAccess'], A:ORIGIN('UrlAccess'), cfg.keywords_lists['url-access'], nil); | ||
if not utilities.is_set (URL) and utilities.is_set (UrlAccess) then | if not utilities.is_set (URL) and utilities.is_set (UrlAccess) then | ||
UrlAccess = nil; | UrlAccess = nil; | ||
utilities.set_message ('err_param_access_requires_param', 'url'); | table.insert( z.message_tail, { utilities.set_message ( 'err_param_access_requires_param', {'url'}, true ) } ); | ||
end | end | ||
Riga 2 725: | Riga 2 606: | ||
if not utilities.is_set (ChapterURL) and utilities.is_set (ChapterUrlAccess) then | if not utilities.is_set (ChapterURL) and utilities.is_set (ChapterUrlAccess) then | ||
ChapterUrlAccess = nil; | ChapterUrlAccess = nil; | ||
utilities.set_message ('err_param_access_requires_param', {A:ORIGIN('ChapterUrlAccess'):gsub ('%-access', '')}); | table.insert( z.message_tail, { utilities.set_message ( 'err_param_access_requires_param', {A:ORIGIN('ChapterUrlAccess'):gsub ('%-access', '')}, true ) } ); | ||
end | end | ||
Riga 2 731: | Riga 2 612: | ||
if not utilities.is_set (A['MapURL']) and utilities.is_set (MapUrlAccess) then | if not utilities.is_set (A['MapURL']) and utilities.is_set (MapUrlAccess) then | ||
MapUrlAccess = nil; | MapUrlAccess = nil; | ||
utilities.set_message ('err_param_access_requires_param', {'map-url'}); | table.insert( z.message_tail, { utilities.set_message ( 'err_param_access_requires_param', {'map-url'}, true ) } ); | ||
end | end | ||
Riga 2 739: | Riga 2 620: | ||
-- check this page to see if it is in one of the namespaces that cs1 is not supposed to add to the error categories | -- check this page to see if it is in one of the namespaces that cs1 is not supposed to add to the error categories | ||
if not utilities.is_set (no_tracking_cats) then -- ignore if we are already not going to categorize this page | if not utilities.is_set (no_tracking_cats) then -- ignore if we are already not going to categorize this page | ||
if cfg.uncategorized_namespaces | if utilities.in_array (this_page.nsText, cfg.uncategorized_namespaces) then | ||
no_tracking_cats = "true"; -- set no_tracking_cats | no_tracking_cats = "true"; -- set no_tracking_cats | ||
end | end | ||
Riga 2 759: | Riga 2 640: | ||
if utilities.is_set (PublicationPlace) and utilities.is_set (Place) then -- both |publication-place= and |place= (|location=) allowed if different | if utilities.is_set (PublicationPlace) and utilities.is_set (Place) then -- both |publication-place= and |place= (|location=) allowed if different | ||
utilities.add_prop_cat ('location | utilities.add_prop_cat ('location test'); -- add property cat to evaluate how often PublicationPlace and Place are used together | ||
if PublicationPlace == Place then | if PublicationPlace == Place then | ||
Place = ''; -- unset; don't need both if they are the same | Place = ''; -- unset; don't need both if they are the same | ||
Riga 2 797: | Riga 2 678: | ||
if utilities.is_set (Encyclopedia) then -- emit error message when Encyclopedia set but template is other than {{cite encyclopedia}} or {{citation}} | if utilities.is_set (Encyclopedia) then -- emit error message when Encyclopedia set but template is other than {{cite encyclopedia}} or {{citation}} | ||
if 'encyclopaedia' ~= config.CitationClass and 'citation' ~= config.CitationClass then | if 'encyclopaedia' ~= config.CitationClass and 'citation' ~= config.CitationClass then | ||
utilities.set_message ('err_parameter_ignored', {A:ORIGIN ('Encyclopedia')}); | table.insert (z.message_tail, {utilities.set_message ('err_parameter_ignored', {A:ORIGIN ('Encyclopedia')}, true)}); | ||
Encyclopedia = nil; -- unset because not supported by this template | Encyclopedia = nil; -- unset because not supported by this template | ||
end | end | ||
Riga 2 803: | Riga 2 684: | ||
if ('encyclopaedia' == config.CitationClass) or ('citation' == config.CitationClass and utilities.is_set (Encyclopedia)) then | if ('encyclopaedia' == config.CitationClass) or ('citation' == config.CitationClass and utilities.is_set (Encyclopedia)) then | ||
if utilities.is_set (Periodical) and utilities.is_set (Encyclopedia) then -- when both set emit an error | if utilities.is_set (Periodical) and utilities.is_set (Encyclopedia) then -- when both set emit an error | ||
utilities.set_message ('err_redundant_parameters', {utilities.wrap_style ('parameter', A:ORIGIN ('Encyclopedia')) .. | table.insert (z.message_tail, {utilities.set_message ('err_redundant_parameters', {utilities.wrap_style ('parameter', A:ORIGIN ('Encyclopedia')) .. ' and ' .. utilities.wrap_style ('parameter', Periodical_origin)}, true )}); | ||
end | end | ||
Riga 2 836: | Riga 2 717: | ||
ScriptTitle = ''; | ScriptTitle = ''; | ||
end | end | ||
elseif utilities.is_set (Chapter | elseif utilities.is_set (Chapter) then -- |title= not set | ||
Title = Periodical; -- |encyclopedia= set and |article= set so map |encyclopedia= to |title= | Title = Periodical; -- |encyclopedia= set and |article= set so map |encyclopedia= to |title= | ||
Periodical = ''; -- redundant so unset | Periodical = ''; -- redundant so unset | ||
Riga 2 850: | Riga 2 731: | ||
ID = A['Number']; -- yes, use it | ID = A['Number']; -- yes, use it | ||
else -- ID has a value so emit error message | else -- ID has a value so emit error message | ||
utilities.set_message ('err_redundant_parameters', {utilities.wrap_style ('parameter', 'id') .. | table.insert( z.message_tail, { utilities.set_message ('err_redundant_parameters', {utilities.wrap_style ('parameter', 'id') .. ' and ' .. utilities.wrap_style ('parameter', 'number')}, true )}); | ||
end | end | ||
end | end | ||
Riga 2 895: | Riga 2 776: | ||
local Sheets = A['Sheets'] or ''; | local Sheets = A['Sheets'] or ''; | ||
if config.CitationClass == "map" then | if config.CitationClass == "map" then | ||
if utilities.is_set (Chapter) then | if utilities.is_set (Chapter) then | ||
utilities.set_message ('err_redundant_parameters', {utilities.wrap_style ('parameter', 'map') .. | table.insert( z.message_tail, { utilities.set_message ( 'err_redundant_parameters', {utilities.wrap_style ('parameter', 'map') .. ' and ' .. utilities.wrap_style ('parameter', Chapter_origin)}, true ) } ); -- add error message | ||
end | end | ||
Chapter = A['Map']; | Chapter = A['Map']; | ||
Riga 2 938: | Riga 2 819: | ||
local SeriesNumber = A['SeriesNumber']; | local SeriesNumber = A['SeriesNumber']; | ||
if utilities.is_set (Season) and utilities.is_set (SeriesNumber) then -- these are mutually exclusive so if both are set | if utilities.is_set (Season) and utilities.is_set (SeriesNumber) then -- these are mutually exclusive so if both are set | ||
utilities.set_message ('err_redundant_parameters', {utilities.wrap_style ('parameter', 'season') .. | table.insert( z.message_tail, { utilities.set_message ( 'err_redundant_parameters', {utilities.wrap_style ('parameter', 'season') .. ' and ' .. utilities.wrap_style ('parameter', 'seriesno')}, true ) } ); -- add error message | ||
SeriesNumber = ''; -- unset; prefer |season= over |seriesno= | SeriesNumber = ''; -- unset; prefer |season= over |seriesno= | ||
end | end | ||
Riga 2 956: | Riga 2 837: | ||
ChapterUrlAccess = UrlAccess; | ChapterUrlAccess = UrlAccess; | ||
ChapterURL_origin = URL_origin; | ChapterURL_origin = URL_origin; | ||
Title = Series; -- promote series to title | Title = Series; -- promote series to title | ||
TitleLink = SeriesLink; | TitleLink = SeriesLink; | ||
Riga 2 970: | Riga 2 850: | ||
TransTitle = ''; | TransTitle = ''; | ||
ScriptTitle = ''; | ScriptTitle = ''; | ||
else -- now oddities that are cite serial | else -- now oddities that are cite serial | ||
Riga 2 986: | Riga 2 865: | ||
local TitleType = A['TitleType']; | local TitleType = A['TitleType']; | ||
local Degree = A['Degree']; | local Degree = A['Degree']; | ||
if utilities.in_array (config.CitationClass, { | if utilities.in_array (config.CitationClass, {"AV-media-notes", "interview", "mailinglist", "map", "podcast", "pressrelease", "report", "techreport", "thesis"}) then | ||
TitleType = set_titletype (config.CitationClass, TitleType); | TitleType = set_titletype (config.CitationClass, TitleType); | ||
if utilities.is_set (Degree) and "Thesis" == TitleType then -- special case for cite thesis | if utilities.is_set (Degree) and "Thesis" == TitleType then -- special case for cite thesis | ||
Riga 3 067: | Riga 2 946: | ||
-- start temporary Julian / Gregorian calendar uncertainty categorization | -- start temporary Julian / Gregorian calendar uncertainty categorization | ||
if COinS_date.inter_cal_cat then | if COinS_date.inter_cal_cat then | ||
utilities.add_prop_cat (' | utilities.add_prop_cat ('jul_greg_uncertainty'); | ||
end | end | ||
-- end temporary Julian / Gregorian calendar uncertainty categorization | -- end temporary Julian / Gregorian calendar uncertainty categorization | ||
Riga 3 078: | Riga 2 957: | ||
local modified = false; -- flag | local modified = false; -- flag | ||
if validation.edtf_transform (date_parameters_list) then -- edtf dates to MOS compliant format | |||
modified = true; | |||
end | |||
if utilities.is_set (DF) then -- if we need to reformat dates | if utilities.is_set (DF) then -- if we need to reformat dates | ||
modified = validation.reformat_dates (date_parameters_list, DF); -- reformat to DF format, use long month names if appropriate | modified = validation.reformat_dates (date_parameters_list, DF); -- reformat to DF format, use long month names if appropriate | ||
Riga 3 087: | Riga 2 970: | ||
end | end | ||
-- for those wikis that can and want to have English date names translated to the local language | -- for those wikis that can and want to have English date names translated to the local language, | ||
-- uncomment the next three lines. Not supported by en.wiki (for obvious reasons) | |||
-- set validation.date_name_xlate() second argument to true to translate English digits to local digits (will translate ymd dates) | |||
-- if validation.date_name_xlate (date_parameters_list, false) then | |||
-- modified = true; | |||
-- end | |||
if modified then -- if the date_parameters_list values were modified | if modified then -- if the date_parameters_list values were modified | ||
Riga 3 102: | Riga 2 986: | ||
end | end | ||
else | else | ||
utilities.set_message ('err_bad_date', {utilities.make_sep_list (#error_list, error_list)}); -- add this error message | table.insert (z.message_tail, {utilities.set_message ('err_bad_date', {utilities.make_sep_list (#error_list, error_list)}, true)}); -- add this error message | ||
end | end | ||
end -- end of do | end -- end of do | ||
Riga 3 119: | Riga 3 003: | ||
-- Account for the oddities that are {{cite arxiv}}, {{cite biorxiv}}, {{cite citeseerx}}, {{cite ssrn}}, before generation of COinS data. | -- Account for the oddities that are {{cite arxiv}}, {{cite biorxiv}}, {{cite citeseerx}}, {{cite ssrn}}, before generation of COinS data. | ||
if utilities.in_array (config.CitationClass, whitelist.preprint_template_list) then -- |arxiv= or |eprint= required for cite arxiv; |biorxiv= | if utilities.in_array (config.CitationClass, whitelist.preprint_template_list) then | ||
if not utilities.is_set (ID_list_coins[config.CitationClass:upper()]) then -- |arxiv= or |eprint= required for cite arxiv; |biorxiv= & |citeseerx= required for their templates | |||
table.insert (z.message_tail, {utilities.set_message ('err_' .. config.CitationClass .. '_missing', {}, true)}); -- add error message | |||
end | end | ||
Riga 3 144: | Riga 3 027: | ||
end | end | ||
if utilities.is_set (URL) | if utilities.is_set (URL) and utilities.is_set (AccessDate) then -- access date requires |url=; identifier-created URL is not |url= | ||
table.insert( z.message_tail, { utilities.set_message ( 'err_accessdate_missing_url', {}, true ) } ); -- add an error message | |||
AccessDate = ''; -- unset | |||
end | end | ||
end | end | ||
Riga 3 160: | Riga 3 036: | ||
-- Test if citation has no title | -- Test if citation has no title | ||
if not utilities.is_set (Title) and not utilities.is_set (TransTitle) and not utilities.is_set (ScriptTitle) then -- has special case for cite episode | if not utilities.is_set (Title) and not utilities.is_set (TransTitle) and not utilities.is_set (ScriptTitle) then -- has special case for cite episode | ||
utilities.set_message ('err_citation_missing_title', {'episode' == config.CitationClass and 'series' or 'title'}); | table.insert( z.message_tail, { utilities.set_message ( 'err_citation_missing_title', {'episode' == config.CitationClass and 'series' or 'title'}, true ) } ); | ||
end | end | ||
Riga 3 170: | Riga 3 046: | ||
utilities.set_message ('maint_untitled'); -- add maint cat | utilities.set_message ('maint_untitled'); -- add maint cat | ||
end | end | ||
check_for_url ({ -- add error message when any of these parameters hold a URL | |||
['title'] = Title, | |||
[A:ORIGIN('Chapter')] = Chapter, | |||
[Periodical_origin] = Periodical, | |||
[PublisherName_origin] = PublisherName | |||
}); | |||
-- COinS metadata (see <http://ocoins.info/>) for automated parsing of citation information. | -- COinS metadata (see <http://ocoins.info/>) for automated parsing of citation information. | ||
Riga 3 189: | Riga 3 072: | ||
end | end | ||
local QuotePage = A['QuotePage']; | |||
local QuotePages = hyphen_to_dash (A['QuotePages']); | |||
-- this is the function call to COinS() | -- this is the function call to COinS() | ||
local OCinSoutput = metadata.COinS({ | local OCinSoutput = metadata.COinS({ | ||
['Periodical'] = utilities.strip_apostrophe_markup (Periodical), -- no markup in the metadata | ['Periodical'] = utilities.strip_apostrophe_markup (Periodical), -- no markup in the metadata | ||
['Encyclopedia'] = Encyclopedia, -- just a flag; content ignored by ~/COinS | ['Encyclopedia'] = Encyclopedia, -- just a flag; content ignored by ~/COinS | ||
['Chapter'] = metadata.make_coins_title (coins_chapter, ScriptChapter), -- Chapter and ScriptChapter stripped of bold / italic | ['Chapter'] = metadata.make_coins_title (coins_chapter, ScriptChapter), -- Chapter and ScriptChapter stripped of bold / italic wiki-markup | ||
['Degree'] = Degree; -- cite thesis only | ['Degree'] = Degree; -- cite thesis only | ||
['Title'] = metadata.make_coins_title (coins_title, ScriptTitle), -- Title and ScriptTitle stripped of bold / italic | ['Title'] = metadata.make_coins_title (coins_title, ScriptTitle), -- Title and ScriptTitle stripped of bold / italic wiki-markup | ||
['PublicationPlace'] = PublicationPlace, | ['PublicationPlace'] = PublicationPlace, | ||
['Date'] = COinS_date.rftdate, -- COinS_date has correctly formatted date if Date is valid; | ['Date'] = COinS_date.rftdate, -- COinS_date has correctly formatted date if Date is valid; | ||
Riga 3 204: | Riga 3 090: | ||
['Volume'] = Volume, | ['Volume'] = Volume, | ||
['Issue'] = Issue, | ['Issue'] = Issue, | ||
['Pages'] = coins_pages or metadata.get_coins_pages (first_set ({Sheet, Sheets, Page, Pages, At, QuotePage, QuotePages}, 7)), -- pages stripped of external links | ['Pages'] = coins_pages or metadata.get_coins_pages (first_set ({Sheet, Sheets, Page, Pages, At, QuotePage, QuotePages}, 7)), -- pages stripped of external links | ||
['Edition'] = Edition, | ['Edition'] = Edition, | ||
Riga 3 303: | Riga 3 188: | ||
if utilities.in_array (config.CitationClass, {"web", "podcast", "mailinglist"}) or -- |url= required for cite web, cite podcast, and cite mailinglist | if utilities.in_array (config.CitationClass, {"web", "podcast", "mailinglist"}) or -- |url= required for cite web, cite podcast, and cite mailinglist | ||
('citation' == config.CitationClass and ('website' == Periodical_origin or 'script-website' == ScriptPeriodical_origin)) then -- and required for {{citation}} with |website= or |script-website= | ('citation' == config.CitationClass and ('website' == Periodical_origin or 'script-website' == ScriptPeriodical_origin)) then -- and required for {{citation}} with |website= or |script-website= | ||
utilities.set_message ('err_cite_web_url'); | table.insert( z.message_tail, { utilities.set_message ( 'err_cite_web_url', {}, true ) } ); | ||
end | end | ||
-- do we have |accessdate= without either |url= or |chapter-url=? | -- do we have |accessdate= without either |url= or |chapter-url=? | ||
if utilities.is_set (AccessDate) and not utilities.is_set (ChapterURL) then -- ChapterURL may be set when URL is not set; | if utilities.is_set (AccessDate) and not utilities.is_set (ChapterURL) then -- ChapterURL may be set when URL is not set; | ||
utilities.set_message ('err_accessdate_missing_url'); | table.insert( z.message_tail, { utilities.set_message ( 'err_accessdate_missing_url', {}, true ) } ); | ||
AccessDate = ''; | AccessDate = ''; | ||
end | end | ||
Riga 3 343: | Riga 3 228: | ||
UrlAccess = nil; -- restricted access levels do not make sense for archived URLs | UrlAccess = nil; -- restricted access levels do not make sense for archived URLs | ||
end | end | ||
end | |||
end | end | ||
Riga 3 364: | Riga 3 247: | ||
if utilities.is_set (chap_param) then -- if we found one | if utilities.is_set (chap_param) then -- if we found one | ||
utilities.set_message ('err_chapter_ignored', {chap_param}); -- add error message | table.insert( z.message_tail, { utilities.set_message ( 'err_chapter_ignored', {chap_param}, true ) } ); -- add error message | ||
Chapter = ''; -- and set them to empty string to be safe with concatenation | Chapter = ''; -- and set them to empty string to be safe with concatenation | ||
TransChapter = ''; | TransChapter = ''; | ||
Riga 3 404: | Riga 3 287: | ||
end | end | ||
if not accept_title then | if not accept_title then -- <Title> not wrapped in accept-as-written markup | ||
if '...' == Title:sub (-3) then -- if ellipsis is the last three characters of |title= | if '...' == Title:sub (-3) then -- if ellipsis is the last three characters of |title= | ||
Title = Title:gsub ('(%.%.%.)%.+$', '%1'); -- limit the number of dots to three | Title = Title:gsub ('(%.%.%.)%.+$', '%1'); -- limit the number of dots to three | ||
Riga 3 416: | Riga 3 299: | ||
end | end | ||
if | if is_generic_title (Title) then | ||
utilities.set_message ('err_generic_title'); | table.insert (z.message_tail, {utilities.set_message ( 'err_generic_title', {}, true ) } ); -- set an error message | ||
end | end | ||
end | end | ||
Riga 3 428: | Riga 3 311: | ||
Title = script_concatenate (Title, ScriptTitle, 'script-title'); -- <bdi> tags, lang attribute, categorization, etc.; must be done after title is wrapped | Title = script_concatenate (Title, ScriptTitle, 'script-title'); -- <bdi> tags, lang attribute, categorization, etc.; must be done after title is wrapped | ||
TransTitle = utilities.wrap_style ('trans-quoted-title', TransTitle ); | TransTitle = utilities.wrap_style ('trans-quoted-title', TransTitle ); | ||
elseif plain_title or ('report' == config.CitationClass) then | elseif plain_title or ('report' == config.CitationClass) then -- no styling for cite report and descriptive titles (otherwise same as above) | ||
Title = script_concatenate (Title, ScriptTitle, 'script-title'); -- <bdi> tags, lang attribute, categorization, etc.; must be done after title is wrapped | Title = script_concatenate (Title, ScriptTitle, 'script-title'); -- <bdi> tags, lang attribute, categorization, etc.; must be done after title is wrapped | ||
TransTitle = utilities.wrap_style ('trans-quoted-title', TransTitle ); -- for cite report, use this form for trans-title | TransTitle = utilities.wrap_style ('trans-quoted-title', TransTitle ); -- for cite report, use this form for trans-title | ||
else | else | ||
Title = utilities.wrap_style ('italic-title', Title); | Title = utilities.wrap_style ('italic-title', Title); | ||
Riga 3 437: | Riga 3 320: | ||
end | end | ||
local TransError = ""; | |||
if utilities.is_set (TransTitle) then | if utilities.is_set (TransTitle) then | ||
if utilities.is_set (Title) then | if utilities.is_set (Title) then | ||
TransTitle = " " .. TransTitle; | TransTitle = " " .. TransTitle; | ||
else | else | ||
utilities.set_message ('err_trans_missing_title', {'title'}); | TransError = " " .. utilities.set_message ( 'err_trans_missing_title', {'title'} ); | ||
end | end | ||
end | end | ||
Riga 3 447: | Riga 3 331: | ||
if utilities.is_set (Title) then -- TODO: is this the right place to be making Wikisource URLs? | if utilities.is_set (Title) then -- TODO: is this the right place to be making Wikisource URLs? | ||
if utilities.is_set (TitleLink) and utilities.is_set (URL) then | if utilities.is_set (TitleLink) and utilities.is_set (URL) then | ||
utilities.set_message ('err_wikilink_in_url'); | table.insert( z.message_tail, { utilities.set_message ( 'err_wikilink_in_url', {}, true ) } ); -- set an error message because we can't have both | ||
TitleLink = ''; -- unset | TitleLink = ''; -- unset | ||
end | end | ||
if not utilities.is_set (TitleLink) and utilities.is_set (URL) then | if not utilities.is_set (TitleLink) and utilities.is_set (URL) then | ||
Title = external_link (URL, Title, URL_origin, UrlAccess) .. TransTitle .. Format; | Title = external_link (URL, Title, URL_origin, UrlAccess) .. TransTitle .. TransError .. Format; | ||
URL = ''; -- unset these because no longer needed | URL = ''; -- unset these because no longer needed | ||
Format = ""; | Format = ""; | ||
Riga 3 461: | Riga 3 345: | ||
Title = external_link (ws_url, Title .. ' ', 'ws link in title-link'); -- space char after Title to move icon away from italic text; TODO: a better way to do this? | Title = external_link (ws_url, Title .. ' ', 'ws link in title-link'); -- space char after Title to move icon away from italic text; TODO: a better way to do this? | ||
Title = utilities.substitute (cfg.presentation['interwiki-icon'], {cfg.presentation['class-wikisource'], TitleLink, Title}); | Title = utilities.substitute (cfg.presentation['interwiki-icon'], {cfg.presentation['class-wikisource'], TitleLink, Title}); | ||
Title = Title .. TransTitle; | Title = Title .. TransTitle .. TransError; | ||
else | else | ||
Title = utilities.make_wikilink (TitleLink, Title) .. TransTitle; | Title = utilities.make_wikilink (TitleLink, Title) .. TransTitle .. TransError; | ||
end | end | ||
else | else | ||
Riga 3 472: | Riga 3 356: | ||
Title = external_link (ws_url, Title .. ' ', 'ws link in title'); -- space char after Title to move icon away from italic text; TODO: a better way to do this? | Title = external_link (ws_url, Title .. ' ', 'ws link in title'); -- space char after Title to move icon away from italic text; TODO: a better way to do this? | ||
Title = utilities.substitute (cfg.presentation['interwiki-icon'], {cfg.presentation['class-wikisource'], L, Title}); | Title = utilities.substitute (cfg.presentation['interwiki-icon'], {cfg.presentation['class-wikisource'], L, Title}); | ||
Title = Title .. TransTitle; | Title = Title .. TransTitle .. TransError; | ||
else | else | ||
Title = Title .. TransTitle; | Title = Title .. TransTitle .. TransError; | ||
end | end | ||
end | end | ||
else | else | ||
Title = TransTitle; | Title = TransTitle .. TransError; | ||
end | end | ||
Riga 3 501: | Riga 3 385: | ||
if utilities.is_set (Minutes) then | if utilities.is_set (Minutes) then | ||
if utilities.is_set (Time) then | if utilities.is_set (Time) then | ||
utilities.set_message ('err_redundant_parameters', {utilities.wrap_style ('parameter', 'minutes') .. | table.insert( z.message_tail, { utilities.set_message ( 'err_redundant_parameters', {utilities.wrap_style ('parameter', 'minutes') .. ' and ' .. utilities.wrap_style ('parameter', 'time')}, true ) } ); | ||
end | end | ||
Position = " " .. Minutes .. " " .. cfg.messages['minutes']; | Position = " " .. Minutes .. " " .. cfg.messages['minutes']; | ||
Riga 3 564: | Riga 3 448: | ||
if utilities.is_set (Edition) then | if utilities.is_set (Edition) then | ||
if Edition:match ('%f[%a][Ee]d%n?%.?$') or Edition:match ('%f[%a][Ee]dition$') then -- Ed, ed, Ed., ed., Edn, edn, Edn., edn. | if Edition:match ('%f[%a][Ee]d%n?%.?$') or Edition:match ('%f[%a][Ee]dition$') then -- Ed, ed, Ed., ed., Edn, edn, Edn., edn. | ||
utilities.set_message ('err_extra_text_edition'); | table.insert( z.message_tail, { utilities.set_message ( 'err_extra_text_edition')}); -- add error | ||
end | end | ||
Edition = " " .. wrap_msg ('edition', Edition); | Edition = " " .. wrap_msg ('edition', Edition); | ||
Riga 3 574: | Riga 3 458: | ||
local Agency = A['Agency']; | local Agency = A['Agency']; | ||
Agency = utilities.is_set (Agency) and wrap_msg ('agency', {sepc, Agency}) or ""; | Agency = utilities.is_set (Agency) and wrap_msg ('agency', {sepc, Agency}) or ""; | ||
Volume = format_volume_issue (Volume, Issue | Volume = format_volume_issue (Volume, Issue, config.CitationClass, Periodical_origin, sepc, use_lowercase); | ||
if utilities.is_set (AccessDate) then | if utilities.is_set (AccessDate) then | ||
Riga 3 610: | Riga 3 494: | ||
end | end | ||
end | end | ||
Quote = utilities.wrap_style ('quoted-text', Quote ); -- wrap in <q>...</q> tags | Quote = utilities.wrap_style ('quoted-text', Quote ); -- wrap in <q>...</q> tags | ||
Riga 3 659: | Riga 3 542: | ||
-- TODO: Should we check a specific pattern? | -- TODO: Should we check a specific pattern? | ||
if utilities.is_set(PostScript) and mw.ustring.len(PostScript) > 1 then | if utilities.is_set(PostScript) and mw.ustring.len(PostScript) > 1 then | ||
utilities.set_message ('maint_postscript') | utilities.set_message('maint_postscript') | ||
end | end | ||
local Archived | local Archived | ||
if utilities.is_set (ArchiveURL) then | if utilities.is_set (ArchiveURL) then | ||
local arch_text; | local arch_text; | ||
if not utilities.is_set (ArchiveDate) then | if not utilities.is_set (ArchiveDate) then | ||
utilities.set_message ('err_archive_missing_date'); | ArchiveDate = utilities.set_message ('err_archive_missing_date'); | ||
end | end | ||
if "live" == UrlStatus then | if "live" == UrlStatus then | ||
arch_text = cfg.messages['archived']; | arch_text = cfg.messages['archived']; | ||
if sepc ~= "." then arch_text = arch_text:lower() end | if sepc ~= "." then arch_text = arch_text:lower() end | ||
Archived = sepc .. " " .. utilities.substitute ( cfg.messages['archived-live'], | |||
{ external_link( ArchiveURL, arch_text, A:ORIGIN('ArchiveURL'), nil ) .. ArchiveFormat, ArchiveDate } ); | |||
if not utilities.is_set (OriginalURL) then | if not utilities.is_set (OriginalURL) then | ||
utilities.set_message ('err_archive_missing_url'); | Archived = Archived .. " " .. utilities.set_message ('err_archive_missing_url'); | ||
end | end | ||
elseif utilities.is_set (OriginalURL) then -- UrlStatus is empty, 'dead', 'unfit', 'usurped', 'bot: unknown' | elseif utilities.is_set (OriginalURL) then -- UrlStatus is empty, 'dead', 'unfit', 'usurped', 'bot: unknown' | ||
Riga 3 686: | Riga 3 563: | ||
arch_text = cfg.messages['archived-unfit']; | arch_text = cfg.messages['archived-unfit']; | ||
if sepc ~= "." then arch_text = arch_text:lower() end | if sepc ~= "." then arch_text = arch_text:lower() end | ||
Archived = sepc .. | Archived = sepc .. " " .. arch_text .. ArchiveDate; -- format already styled | ||
if 'bot: unknown' == UrlStatus then | if 'bot: unknown' == UrlStatus then | ||
utilities.set_message ('maint_bot_unknown'); -- and add a category if not already added | utilities.set_message ('maint_bot_unknown'); -- and add a category if not already added | ||
Riga 3 695: | Riga 3 572: | ||
arch_text = cfg.messages['archived-dead']; | arch_text = cfg.messages['archived-dead']; | ||
if sepc ~= "." then arch_text = arch_text:lower() end | if sepc ~= "." then arch_text = arch_text:lower() end | ||
Archived = sepc .. " " .. utilities.substitute ( arch_text, | |||
{ external_link( OriginalURL, cfg.messages['original'], OriginalURL_origin, OriginalAccess ) .. OriginalFormat, ArchiveDate } ); -- format already styled | |||
end | end | ||
else -- OriginalUrl not set | else -- OriginalUrl not set | ||
arch_text = cfg.messages['archived-missing']; | arch_text = cfg.messages['archived-missing']; | ||
if sepc ~= "." then arch_text = arch_text:lower() end | if sepc ~= "." then arch_text = arch_text:lower() end | ||
utilities.set_message ('err_archive_missing_url'); | Archived = sepc .. " " .. utilities.substitute ( arch_text, | ||
{ utilities.set_message ('err_archive_missing_url'), ArchiveDate } ); | |||
end | end | ||
elseif utilities.is_set (ArchiveFormat) then | elseif utilities.is_set (ArchiveFormat) then | ||
Archived = ArchiveFormat; -- if set and ArchiveURL not set ArchiveFormat has error message | Archived = ArchiveFormat; -- if set and ArchiveURL not set ArchiveFormat has error message | ||
else | else | ||
Archived = | Archived = "" | ||
end | end | ||
Riga 3 791: | Riga 3 664: | ||
]] | ]] | ||
if "speech" == config.CitationClass then -- cite speech only | if "speech" == config.CitationClass then -- cite speech only | ||
TitleNote = | TitleNote = " (Speech)"; -- annotate the citation | ||
if utilities.is_set (Periodical) then -- if Periodical, perhaps because of an included |website= or |journal= parameter | if utilities.is_set (Periodical) then -- if Periodical, perhaps because of an included |website= or |journal= parameter | ||
if utilities.is_set (Conference) then -- and if |event= is set | if utilities.is_set (Conference) then -- and if |event= is set | ||
Riga 3 809: | Riga 3 680: | ||
if utilities.in_array (config.CitationClass, {"journal", "citation"}) and utilities.is_set (Periodical) then | if utilities.in_array (config.CitationClass, {"journal", "citation"}) and utilities.is_set (Periodical) then | ||
if utilities.is_set (Others) then Others = safe_join ({Others, sepc .. " "}, sepc) end -- add terminal punctuation & space; check for dup sepc; TODO why do we need to do this here? | if utilities.is_set (Others) then Others = safe_join ({Others, sepc .. " "}, sepc) end -- add terminal punctuation & space; check for dup sepc; TODO why do we need to do this here? | ||
tcommon = safe_join( {Others, Title, TitleNote, Conference, Periodical, Format, TitleType, Series, Language, Edition, Publisher, Agency, Volume}, sepc ); | tcommon = safe_join( {Others, Title, TitleNote, Conference, Periodical, Format, TitleType, Series, Language, Edition, Publisher, Agency, Volume}, sepc ); | ||
Riga 3 907: | Riga 3 775: | ||
if utilities.is_set (Date) then | if utilities.is_set (Date) then | ||
if EditorCount <= 1 then | if EditorCount <= 1 then | ||
Editors = Editors .. | Editors = Editors .. ", " .. cfg.messages['editor']; | ||
else | else | ||
Editors = Editors .. | Editors = Editors .. ", " .. cfg.messages['editors']; | ||
end | end | ||
else | else | ||
Riga 3 935: | Riga 3 803: | ||
-- Now enclose the whole thing in a <cite> element | -- Now enclose the whole thing in a <cite> element | ||
local | local options = {}; | ||
if utilities.is_set (config.CitationClass) and config.CitationClass ~= "citation" then | |||
options.class = string.format ('%s %s %s', 'citation', config.CitationClass, utilities.is_set (Mode) and Mode or 'cs1'); -- class=citation required for blue highlight when used with |ref= | |||
else | |||
options.class = string.format ('%s %s', 'citation', utilities.is_set (Mode) and Mode or 'cs2'); | |||
end | |||
local Ref = | local Ref = A['Ref']; | ||
if 'harv' == Ref then -- need to check this before setting to default | |||
if 'none' ~= cfg.keywords_xlate[ | utilities.set_message ('maint_ref_harv'); -- add maint cat to identify templates that have this now-extraneous param value | ||
local | elseif not utilities.is_set (Ref) then | ||
Ref = 'harv'; -- set as default when not set externally | |||
end | |||
if 'none' ~= cfg.keywords_xlate[Ref:lower()] then | |||
local id = Ref | |||
local namelist = {}; -- holds selected contributor, author, editor name list | |||
local year = first_set ({Year, anchor_year}, 2); -- Year first for legacy citations and for YMD dates that require disambiguation | local year = first_set ({Year, anchor_year}, 2); -- Year first for legacy citations and for YMD dates that require disambiguation | ||
if #c > 0 then -- if there is a contributor list | if #c > 0 then -- if there is a contributor list | ||
namelist = c; -- select it | |||
elseif #a > 0 then -- or an author list | elseif #a > 0 then -- or an author list | ||
namelist = a; | |||
elseif #e > 0 then -- or an editor list | elseif #e > 0 then -- or an editor list | ||
namelist = e; | |||
end | end | ||
local citeref_id | local citeref_id | ||
if # | if #namelist > 0 then -- if there are names in namelist | ||
citeref_id = make_citeref_id ( | citeref_id = make_citeref_id (namelist, year); -- go make the CITEREF anchor | ||
else | else | ||
citeref_id = ''; -- unset | citeref_id = ''; -- unset | ||
end | end | ||
if citeref_id == Ref then | |||
utilities.set_message ('maint_ref_duplicates_default'); | |||
end | |||
if 'harv' == Ref then | |||
id = citeref_id | |||
end | |||
options.id = id; | |||
end | end | ||
if string.len (text:gsub( | if string.len(text:gsub("<span[^>/]*>(.-)</span>", "%1"):gsub("%b<>", "")) <= 2 then -- remove <span> tags and other HTML-like markup; then get length of what remains | ||
z.error_categories = {}; | |||
z. | text = utilities.set_message ('err_empty_citation'); | ||
z.message_tail = {}; | |||
text = | |||
end | end | ||
local | local render = {}; -- here we collect the final bits for concatenation into the rendered citation | ||
if utilities.is_set ( | if utilities.is_set (options.id) then -- here we wrap the rendered citation in <cite ...>...</cite> tags | ||
table.insert ( | table.insert (render, utilities.substitute (cfg.presentation['cite-id'], {mw.uri.anchorEncode(options.id), mw.text.nowiki(options.class), text})); -- when |ref= is set | ||
else | else | ||
table.insert ( | table.insert (render, utilities.substitute (cfg.presentation['cite'], {mw.text.nowiki(options.class), text})); -- all other cases | ||
end | end | ||
table.insert (render, utilities.substitute (cfg.presentation['ocins'], {OCinSoutput})); -- append metadata to the citation | |||
if 0 ~= #z.message_tail then | |||
table.insert (render, ' '); | |||
for i,v in ipairs( z.message_tail ) do | |||
if utilities.is_set (v[1]) then | |||
if i == #z.message_tail then | |||
table.insert (render, utilities.error_comment ( v[1], v[2] )); | |||
else | |||
table.insert (render, utilities.error_comment ( v[1] .. "; ", v[2] )); | |||
end | |||
end | end | ||
end | end | ||
end | end | ||
if 0 ~= #z. | if 0 ~= #z.maintenance_cats then | ||
local maint_msgs = {}; -- here we collect all of the maint messages | |||
for _, v in ipairs( z.maintenance_cats ) do -- append maintenance categories | |||
local maint = {}; -- here we assemble a maintenence message | |||
table.insert (maint, v); -- maint msg is the category name | |||
local | table.insert (maint, ' ('); -- open the link text | ||
table.insert (maint, utilities.substitute (cfg.messages[':cat wikilink'], {v})); -- add the link | |||
table.insert (maint, ')'); -- and close it | |||
table.insert (maint_msgs, table.concat (maint)); -- assemble new maint message and add it to the maint_msgs table | |||
for _, v in ipairs( z. | |||
table.insert ( | |||
end | end | ||
table.insert ( | table.insert (render, utilities.substitute (cfg.presentation['hidden-maint'], table.concat (maint_msgs, ' '))); -- wrap the group of maint message with proper presentation and save | ||
end | end | ||
if not no_tracking_cats then | if not no_tracking_cats then | ||
for _, v in ipairs (z. | for _, v in ipairs( z.error_categories ) do -- append error categories | ||
table.insert ( | table.insert (render, utilities.substitute (cfg.messages['cat wikilink'], {v})); | ||
end | end | ||
for _, v in ipairs (z. | for _, v in ipairs( z.maintenance_cats ) do -- append maintenance categories | ||
table.insert ( | table.insert (render, utilities.substitute (cfg.messages['cat wikilink'], {v})); | ||
end | end | ||
for _, v in ipairs (z. | for _, v in ipairs( z.properties_cats ) do -- append properties categories | ||
table.insert ( | table.insert (render, utilities.substitute (cfg.messages['cat wikilink'], {v})); | ||
end | end | ||
end | end | ||
return table.concat ( | return table.concat (render); | ||
end | end | ||
Riga 4 062: | Riga 3 924: | ||
return true; | return true; | ||
end | end | ||
if ' | if 'discouraged' == state then | ||
discouraged_parameter (name); -- parameter is discouraged but still supported | |||
return true; | return true; | ||
end | end | ||
Riga 4 122: | Riga 3 983: | ||
if prefix and cfg.inter_wiki_map[prefix:lower()] then -- if prefix is in the map, needs preceding colon so | if prefix and cfg.inter_wiki_map[prefix:lower()] then -- if prefix is in the map, needs preceding colon so | ||
utilities.set_message ('err_bad_paramlink', parameter); | table.insert( z.message_tail, {utilities.set_message ('err_bad_paramlink', parameter)}); -- emit an error message | ||
_, value, _ = utilities.is_wikilink (value); -- extract label portion from wikilink | _, value, _ = utilities.is_wikilink (value); -- extract label portion from wikilink | ||
end | end | ||
Riga 4 149: | Riga 4 010: | ||
capture = value:match ('%s+(%a[%w%-]+)%s*=') or value:match ('^(%a[%w%-]+)%s*='); -- find and categorize parameters with possible missing pipes | capture = value:match ('%s+(%a[%w%-]+)%s*=') or value:match ('^(%a[%w%-]+)%s*='); -- find and categorize parameters with possible missing pipes | ||
if capture and validate (capture) then -- if the capture is a valid parameter name | if capture and validate (capture) then -- if the capture is a valid parameter name | ||
utilities.set_message ('err_missing_pipe', parameter); | table.insert( z.message_tail, {utilities.set_message ('err_missing_pipe', parameter)}); | ||
end | end | ||
end | end | ||
Riga 4 171: | Riga 4 032: | ||
if value:match ('[,;:]$') then | if value:match ('[,;:]$') then | ||
utilities.set_message ('maint_extra_punct'); -- has extraneous punctuation; add maint cat | utilities.set_message ('maint_extra_punct'); -- has extraneous punctuation; add maint cat | ||
end | end | ||
Riga 4 179: | Riga 4 037: | ||
--[[--------------------------< | --[[--------------------------< C I T A T I O N >-------------------------------------------------------------- | ||
This is used by templates such as {{cite book}} to create the actual citation text. | |||
]] | ]] | ||
local function | local function citation(frame) | ||
local | Frame = frame; -- save a copy in case we need to display an error message in preview mode | ||
local pframe = frame:getParent() | |||
local styles; | |||
if nil ~= string.find (frame:getTitle(), 'sandbox', 1, true) then -- did the {{#invoke:}} use sandbox version? | |||
cfg = mw.loadData ('Module:Citation/CS1/Configuration/sandbox'); -- load sandbox versions of support modules | |||
whitelist = mw.loadData ('Module:Citation/CS1/Whitelist/sandbox'); | |||
utilities | utilities = require ('Module:Citation/CS1/Utilities/sandbox'); | ||
validation = require ('Module:Citation/CS1/Date_validation/sandbox'); | |||
identifiers = require ('Module:Citation/CS1/Identifiers/sandbox'); | |||
metadata = require ('Module:Citation/CS1/COinS/sandbox'); | |||
styles = 'Module:Citation/CS1/sandbox/styles.css'; | |||
else -- otherwise | |||
cfg = mw.loadData ('Module:Citation/CS1/Configuration'); -- load live versions of support modules | |||
whitelist = mw.loadData ('Module:Citation/CS1/Whitelist'); | |||
utilities = require ('Module:Citation/CS1/Utilities'); | |||
validation = require ('Module:Citation/CS1/Date_validation'); | |||
identifiers = require ('Module:Citation/CS1/Identifiers'); | |||
metadata = require ('Module:Citation/CS1/COinS'); | |||
styles = 'Module:Citation/CS1/styles.css'; | |||
end | end | ||
utilities.set_selected_modules (cfg); -- so that functions in Utilities can see the selected cfg tables | |||
identifiers.set_selected_modules (cfg, utilities); -- so that functions in Identifiers can see the selected cfg tables and selected Utilities module | |||
validation.set_selected_modules (cfg, utilities); -- so that functions in Date validataion can see selected cfg tables and the selected Utilities module | |||
metadata.set_selected_modules (cfg, utilities); -- so that functions in COinS can see the selected cfg tables and selected Utilities module | |||
-- | z = utilities.z; -- table of error and category tables in Module:Citation/CS1/Utilities | ||
local args = {}; -- table where we store all of the template's arguments | |||
local suggestions = {}; -- table where we store suggestions if we need to loadData them | |||
local error_text, error_state; | |||
]] | local config = {}; -- table to store parameters from the module {{#invoke:}} | ||
for k, v in pairs( frame.args ) do -- get parameters from the {{#invoke}} frame | |||
config[k] = v; | |||
-- args[k] = v; -- crude debug support that allows us to render a citation from module {{#invoke:}}; skips parameter validation; TODO: keep? | |||
end | |||
local capture; -- the single supported capture when matching unknown parameters using patterns | |||
local empty_unknowns = {}; -- sequence table to hold empty unknown params for error message listing | |||
for k, v in pairs( pframe.args ) do -- get parameters from the parent (template) frame | |||
v = mw.ustring.gsub (v, '^%s*(.-)%s*$', '%1'); -- trim leading/trailing whitespace; when v is only whitespace, becomes empty string | |||
if v ~= '' then | |||
if ('string' == type (k)) then | |||
k = mw.ustring.gsub (k, '%d', cfg.date_names.local_digits); -- for enumerated parameters, translate 'local' digits to Western 0-9 | |||
end | |||
if not validate( k, config.CitationClass ) then | |||
error_text = ""; | |||
if type( k ) ~= 'string' then | |||
-- exclude empty numbered parameters | |||
if v:match("%S+") ~= nil then | |||
error_text, error_state = utilities.set_message ( 'err_text_ignored', {v}, true ); | |||
end | |||
elseif validate( k:lower(), config.CitationClass ) then | |||
error_text, error_state = utilities.set_message ( 'err_parameter_ignored_suggest', {k, k:lower()}, true ); -- suggest the lowercase version of the parameter | |||
else | |||
if nil == suggestions.suggestions then -- if this table is nil then we need to load it | |||
if nil ~= string.find (frame:getTitle(), 'sandbox', 1, true) then -- did the {{#invoke:}} use sandbox version? | |||
suggestions = mw.loadData( 'Module:Citation/CS1/Suggestions/sandbox' ); -- use the sandbox version | |||
else | |||
suggestions = mw.loadData( 'Module:Citation/CS1/Suggestions' ); -- use the live version | |||
end | |||
local capture; -- the single supported capture when matching unknown parameters using patterns | |||
local empty_unknowns = {}; -- sequence table to hold empty unknown params for error message listing | |||
for k, v in pairs( pframe.args ) do -- get parameters from the parent (template) frame | |||
v = mw.ustring.gsub (v, '^%s*(.-)%s*$', '%1'); -- trim leading/trailing whitespace; when v is only whitespace, becomes empty string | |||
if v ~= '' then | |||
if ('string' == type (k)) then | |||
k = mw.ustring.gsub (k, '%d', cfg.date_names.local_digits); -- for enumerated parameters, translate 'local' digits to Western 0-9 | |||
end | |||
if not validate( k, config.CitationClass ) then | |||
if type (k) ~= 'string' then | |||
if v:match("%S+") ~= nil then | |||
error_text = utilities.set_message ('err_text_ignored', {v}); | |||
end | |||
elseif validate (k:lower(), config.CitationClass) then | |||
error_text = utilities.set_message ('err_parameter_ignored_suggest', {k, k:lower()}); -- suggest the lowercase version of the parameter | |||
else | |||
if nil == suggestions.suggestions then -- if this table is nil then we need to load it | |||
suggestions = mw.loadData ('Module:Citation/CS1/Suggestions' | |||
end | end | ||
for pattern, param in pairs (suggestions.patterns) do -- loop through the patterns to see if we can suggest a proper parameter | for pattern, param in pairs (suggestions.patterns) do -- loop through the patterns to see if we can suggest a proper parameter | ||
Riga 4 263: | Riga 4 114: | ||
param = utilities.substitute (param, capture); -- add the capture to the suggested parameter (typically the enumerator) | param = utilities.substitute (param, capture); -- add the capture to the suggested parameter (typically the enumerator) | ||
if validate (param, config.CitationClass) then -- validate the suggestion to make sure that the suggestion is supported by this template (necessary for limited parameter lists) | if validate (param, config.CitationClass) then -- validate the suggestion to make sure that the suggestion is supported by this template (necessary for limited parameter lists) | ||
error_text = utilities.set_message ('err_parameter_ignored_suggest', {k, param}); -- set the suggestion error message | error_text, error_state = utilities.set_message ('err_parameter_ignored_suggest', {k, param}, true); -- set the suggestion error message | ||
else | else | ||
error_text = utilities.set_message ('err_parameter_ignored', {k}); -- suggested param not supported by this template | error_text, error_state = utilities.set_message ( 'err_parameter_ignored', {k}, true ); -- suggested param not supported by this template | ||
v = ''; -- unset | v = ''; -- unset | ||
end | end | ||
Riga 4 272: | Riga 4 123: | ||
if not utilities.is_set (error_text) then -- couldn't match with a pattern, is there an explicit suggestion? | if not utilities.is_set (error_text) then -- couldn't match with a pattern, is there an explicit suggestion? | ||
if (suggestions.suggestions[ k:lower() ] ~= nil) and validate (suggestions.suggestions[ k:lower() ], config.CitationClass) then | if (suggestions.suggestions[ k:lower() ] ~= nil) and validate (suggestions.suggestions[ k:lower() ], config.CitationClass) then | ||
utilities.set_message ('err_parameter_ignored_suggest', {k, suggestions.suggestions[ k:lower() ]}); | error_text, error_state = utilities.set_message ( 'err_parameter_ignored_suggest', {k, suggestions.suggestions[ k:lower() ]}, true ); | ||
else | else | ||
utilities.set_message ('err_parameter_ignored', {k}); | error_text, error_state = utilities.set_message ( 'err_parameter_ignored', {k}, true ); | ||
v = ''; -- unset value assigned to unrecognized parameters (this for the limited parameter lists) | v = ''; -- unset value assigned to unrecognized parameters (this for the limited parameter lists) | ||
end | end | ||
end | end | ||
end | end | ||
if error_text ~= '' then | |||
table.insert( z.message_tail, {error_text, error_state} ); | |||
end | |||
end | end | ||
Riga 4 295: | Riga 4 149: | ||
if 0 ~= #empty_unknowns then -- create empty unknown error message | if 0 ~= #empty_unknowns then -- create empty unknown error message | ||
utilities.set_message ('err_param_unknown_empty', { | table.insert (z.message_tail, {utilities.set_message ('err_param_unknown_empty', { | ||
1 == #empty_unknowns and '' or 's', | 1 == #empty_unknowns and '' or 's', | ||
utilities.make_sep_list (#empty_unknowns, empty_unknowns) | utilities.make_sep_list (#empty_unknowns, empty_unknowns) | ||
}); | }, true )}); | ||
end | end | ||
for k, v in pairs( args ) do | for k, v in pairs( args ) do | ||
Riga 4 310: | Riga 4 162: | ||
missing_pipe_check (k, v); -- do we think that there is a parameter that is missing a pipe? | missing_pipe_check (k, v); -- do we think that there is a parameter that is missing a pipe? | ||
args[k] = inter_wiki_check (k, v); -- when language interwiki-linked parameter missing leading colon replace with wiki-link label | args[k] = inter_wiki_check (k, v); -- when language interwiki-linked parameter missing leading colon replace with wiki-link label | ||
end | end | ||
return table.concat ({ | return table.concat ({ | ||
Riga 4 323: | Riga 4 169: | ||
}); | }); | ||
end | end | ||
--[[--------------------------< E X P O R T E D F U N C T I O N S >------------------------------------------ | --[[--------------------------< E X P O R T E D F U N C T I O N S >------------------------------------------ |