Module:Citation/CS1: Difference between revisions
sync from sandbox;
(sync from sandbox;) |
(sync from sandbox;) |
||
Line 534: | Line 534: | ||
local lang=''; -- initialize to empty string | local lang=''; -- initialize to empty string | ||
local name; | local name; | ||
if script_value:match('^%l%l%l?%s*:') then -- if first 3 or 4 non-space characters are script language prefix | if script_value:match('^%l%l%l?%s*:') then -- if first 3 or 4 non-space characters are script language prefix | ||
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 is_set (lang) then | if not is_set (lang) then | ||
Line 545: | Line 543: | ||
name = cfg.lang_code_remap[lang] or mw.language.fetchLanguageName( lang, cfg.this_wiki_code ); -- get language name so that we can use it to categorize | name = cfg.lang_code_remap[lang] or mw.language.fetchLanguageName( lang, cfg.this_wiki_code ); -- get language name so that we can use it to categorize | ||
if is_set (name) then -- is prefix a proper ISO 639-1 language code? | if is_set (name) then -- is prefix a proper ISO 639-1 language code? | ||
script_value = script_value:gsub ('^%l+%s*:%s*', ''); -- strip prefix from script | script_value = script_value:gsub ('^%l+%s*:%s*', ''); -- strip prefix from script | ||
-- is prefix one of these language codes? | -- is prefix one of these language codes? | ||
Line 617: | Line 614: | ||
local wl_type, D, L; | local wl_type, D, L; | ||
local ws_url, ws_label; | local ws_url, ws_label; | ||
local wikisource_prefix = table.concat ({'https://', cfg.this_wiki_code, '.wikisource.org/wiki/'}); | |||
wl_type, D, L = is_wikilink (str); -- wl_type is 0 (not a wikilink), 1 (simple wikilink), 2 (complex wikilink) | wl_type, D, L = is_wikilink (str); -- wl_type is 0 (not a wikilink), 1 (simple wikilink), 2 (complex wikilink) | ||
Line 624: | Line 622: | ||
if is_set (str) then | if is_set (str) then | ||
ws_url = table.concat ({ -- build a wikisource url | ws_url = table.concat ({ -- build a wikisource url | ||
wikisource_prefix, -- prefix | |||
str, -- article title | str, -- article title | ||
}); | }); | ||
ws_label = str; -- label for the url | ws_label = str; -- label for the url | ||
end | end | ||
elseif 1 == wl_type then | elseif 1 == wl_type then -- simple wikilink: [[Wikisource:ws article]] | ||
str = D:match ('^[Ww]ikisource:(.+)') or D:match ('^[Ss]:(.+)'); -- article title from interwiki link with long-form or short-form namespace | str = D:match ('^[Ww]ikisource:(.+)') or D:match ('^[Ss]:(.+)'); -- article title from interwiki link with long-form or short-form namespace | ||
if is_set (str) then | if is_set (str) then | ||
ws_url = table.concat ({ -- build a wikisource url | ws_url = table.concat ({ -- build a wikisource url | ||
wikisource_prefix, -- prefix | |||
str, -- article title | str, -- article title | ||
}); | }); | ||
Line 643: | Line 641: | ||
ws_label = D; -- get ws article name from display portion of interwiki link | ws_label = D; -- get ws article name from display portion of interwiki link | ||
ws_url = table.concat ({ -- build a wikisource url | ws_url = table.concat ({ -- build a wikisource url | ||
wikisource_prefix, -- prefix | |||
str, -- article title without namespace from link portion of wikilink | str, -- article title without namespace from link portion of wikilink | ||
}); | }); | ||
Line 651: | Line 649: | ||
if ws_url then | if ws_url then | ||
ws_url = mw.uri.encode (ws_url, 'WIKI'); -- make a usable url | ws_url = mw.uri.encode (ws_url, 'WIKI'); -- make a usable url | ||
ws_url = ws_url:gsub ('%%23', '#'); -- undo percent encoding of | ws_url = ws_url:gsub ('%%23', '#'); -- undo percent encoding of fragment marker | ||
end | end | ||
Line 660: | Line 658: | ||
--[[--------------------------< F O R M A T _ P E R I O D I C A L >-------------------------------------------- | --[[--------------------------< F O R M A T _ P E R I O D I C A L >-------------------------------------------- | ||
Format the | Format the three periodical parameters: |script-<periodical>=, |<periodical>=, and |trans-<periodical>= into a single Periodical meta- | ||
parameter. | parameter. | ||
Line 680: | Line 678: | ||
if is_set (periodical) then | if is_set (periodical) then | ||
periodical = periodical .. ' ' .. trans_periodical; | periodical = periodical .. ' ' .. trans_periodical; | ||
else -- here when | else -- here when trans-periodical without periodical or script-periodical | ||
periodical = trans_periodical; | periodical = trans_periodical; | ||
periodical_error = ' ' .. set_error ('trans_missing_title', {'periodical'}); | periodical_error = ' ' .. set_error ('trans_missing_title', {'periodical'}); | ||
Line 733: | Line 731: | ||
end | end | ||
end | end | ||
return chapter .. chapter_error; | return chapter .. chapter_error; | ||
Line 843: | Line 837: | ||
-- Empty strings, not nil; | -- Empty strings, not nil; | ||
if v == nil then | if v == nil then | ||
-- v = cfg.defaults[k] or ''; | |||
v = ''; | |||
origin[k] = ''; | origin[k] = ''; | ||
end | end | ||
Line 888: | Line 883: | ||
local function set_titletype (cite_class, title_type) | local function set_titletype (cite_class, title_type) | ||
if is_set(title_type) then | if is_set(title_type) then | ||
if cfg.keywords_xlate[title_type] == 'none' then | |||
title_type = ""; -- if |type=none then type parameter not displayed | title_type = ""; -- if |type=none then type parameter not displayed | ||
end | end | ||
Line 926: | Line 922: | ||
str = str:gsub ('&[nm]dash;', {['–'] = '–', ['—'] = '—'}); -- replace — and – entities with their characters; semicolon mucks up the text.split | str = str:gsub ('&[nm]dash;', {['–'] = '–', ['—'] = '—'}); -- replace — and – entities with their characters; semicolon mucks up the text.split | ||
str = str:gsub ('-', '-'); -- replace html numeric entity with hyphen character | str = str:gsub ('-', '-'); -- replace html numeric entity with hyphen character | ||
str = str:gsub (' ', ' '); -- replace entity with generic keyboard space character | |||
local out = {}; | local out = {}; | ||
Line 1,082: | Line 1,079: | ||
if is_set (suffix) then | if is_set (suffix) then | ||
if not is_suffix (suffix) then | if not is_suffix (suffix) then | ||
add_vanc_error ( | add_vanc_error (cfg.err_msg_supl.suffix); | ||
return false; -- not a name with an appropriate suffix | return false; -- not a name with an appropriate suffix | ||
end | end | ||
Line 1,088: | Line 1,085: | ||
if nil == mw.ustring.find (last, "^[A-Za-z\195\128-\195\150\195\152-\195\182\195\184-\198\191\199\132-\201\143%-%s%']*$") or | if nil == mw.ustring.find (last, "^[A-Za-z\195\128-\195\150\195\152-\195\182\195\184-\198\191\199\132-\201\143%-%s%']*$") or | ||
nil == mw.ustring.find (first, "^[A-Za-z\195\128-\195\150\195\152-\195\182\195\184-\198\191\199\132-\201\143%-%s%'%.]*$") then | nil == mw.ustring.find (first, "^[A-Za-z\195\128-\195\150\195\152-\195\182\195\184-\198\191\199\132-\201\143%-%s%'%.]*$") then | ||
add_vanc_error ('non-Latin character'); | add_vanc_error (cfg.err_msg_supl['non-Latin character']); | ||
return false; -- not a string of latin characters; Vancouver requires Romanization | return false; -- not a string of latin characters; Vancouver requires Romanization | ||
end; | end; | ||
Line 1,121: | Line 1,118: | ||
return first; -- one or two initials and a valid suffix so nothing to do | return first; -- one or two initials and a valid suffix so nothing to do | ||
else | else | ||
add_vanc_error ( | add_vanc_error (cfg.err_msg_supl.suffix); -- one or two initials with invalid suffix so error message | ||
return first; -- and return first unmolested | return first; -- and return first unmolested | ||
end | end | ||
Line 1,129: | Line 1,126: | ||
end | end | ||
end -- if here then name has 3 or more uppercase letters so treat them as a word | end -- if here then name has 3 or more uppercase letters so treat them as a word | ||
local initials, names = {}, {}; -- tables to hold name parts and initials | local initials, names = {}, {}; -- tables to hold name parts and initials | ||
Line 1,208: | Line 1,204: | ||
one = one .. namesep .. first; | one = one .. namesep .. first; | ||
end | end | ||
end | end | ||
table.insert( text, one ) | if is_set (person.link) then | ||
table.insert( text, sep_one ) | one = make_wikilink (person.link, one); -- link author/editor | ||
end | |||
table.insert (text, one) | |||
table.insert (text, sep_one) | |||
end | end | ||
end | end | ||
Line 1,241: | Line 1,237: | ||
]] | ]] | ||
local function anchor_id (namelist, year) | local function anchor_id (namelist, year) | ||
local names={}; -- a table for the one to four names and year | local names={}; -- a table for the one to four names and year | ||
Line 1,284: | Line 1,281: | ||
return name, etal; -- | return name, etal; -- | ||
end | |||
--[[--------------------------< N A M E _ I S _ N U M E R I C >------------------------------------------------ | |||
Add maint cat when name parameter value does not contain letters. Does not catch mixed alphanumeric names so | |||
|last=A. Green (1922-1987) does not get caught in the current version of this test but |first=(1888) is caught. | |||
returns nothing | |||
]] | |||
local function name_is_numeric (name, list_name) | |||
if is_set (name) then | |||
if mw.ustring.match (name, '^[%A]+$') then -- when name does not contain any letters | |||
add_maint_cat ('numeric_names', cfg.special_case_translation [list_name]); -- add a maint cat for this template | |||
end | |||
end | |||
end | end | ||
Line 1,292: | Line 1,307: | ||
These annotation do not belong in author parameters and are redundant in editor parameters. If found, the function | These annotation do not belong in author parameters and are redundant in editor parameters. If found, the function | ||
adds the editor markup maintenance category. | adds the editor markup maintenance category. | ||
returns nothing | |||
]] | ]] | ||
local function name_has_ed_markup (name, list_name) | local function name_has_ed_markup (name, list_name) | ||
local patterns = cfg.editor_markup_patterns; -- get patterns from configuration | local patterns = cfg.editor_markup_patterns; -- get patterns from configuration | ||
Line 1,307: | Line 1,323: | ||
end | end | ||
end | end | ||
end | end | ||
Line 1,316: | Line 1,331: | ||
indicated if there is more than one comma and or semicolon. If found, the function adds the multiple name | indicated if there is more than one comma and or semicolon. If found, the function adds the multiple name | ||
(author or editor) maintenance category. | (author or editor) maintenance category. | ||
returns nothing | |||
]] | ]] | ||
local function name_has_mult_names (name, list_name) | local function name_has_mult_names (name, list_name) | ||
local count | local _, count; | ||
if is_set (name) then | if is_set (name) then | ||
_, count = name:gsub ('[;,]', ''); -- count the number of separator-like characters | _, count = name:gsub ('[;,]', ''); -- count the number of separator-like characters | ||
Line 1,328: | Line 1,345: | ||
end | end | ||
end | end | ||
end | end | ||
--[[--------------------------< N A M E _ C H E C K S >-------------------------------------------------------- | --[[--------------------------< 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 | This function calls various name checking functions used to validate the content of the various name-holding | ||
parameters. | parameters. | ||
Line 1,343: | Line 1,360: | ||
last = last:match ('^%(%((.*)%)%)$'); -- strip parens | last = last:match ('^%(%((.*)%)%)$'); -- strip parens | ||
else | else | ||
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 compsed of digits and punctuation | |||
end | end | ||
end | end | ||
Line 1,351: | Line 1,369: | ||
first = first:match ('^%(%((.*)%)%)$'); -- strip parens | first = first:match ('^%(%((.*)%)%)$'); -- strip parens | ||
else | else | ||
name_has_ed_markup (first, list_name); -- check for extraneous 'editor' annotation | |||
name_is_numeric (first, list_name); -- check for names that are compsed of digits and punctuation | |||
end | end | ||
end | end | ||
Line 1,385: | Line 1,404: | ||
local etal=false; -- return value set to true when we find some form of et al. in an author parameter | local etal=false; -- return value set to true when we find some form of et al. in an author parameter | ||
local last_alias, first_alias; | local last_alias, first_alias, link_alias; -- selected parameter aliases used in error messaging | ||
while true do | while true do | ||
last, last_alias = select_one( args, cfg.aliases[list_name .. '-Last'], 'redundant_parameters', i ); -- search through args for name components beginning at 1 | last, last_alias = select_one( args, cfg.aliases[list_name .. '-Last'], 'redundant_parameters', i ); -- search through args for name components beginning at 1 | ||
first, first_alias = select_one( args, cfg.aliases[list_name .. '-First'], 'redundant_parameters', i ); | first, first_alias = select_one( args, cfg.aliases[list_name .. '-First'], 'redundant_parameters', i ); | ||
link = select_one( args, cfg.aliases[list_name .. '-Link'], 'redundant_parameters', i ); | link, link_alias = select_one( args, cfg.aliases[list_name .. '-Link'], 'redundant_parameters', i ); | ||
mask = select_one( args, cfg.aliases[list_name .. '-Mask'], 'redundant_parameters', i ); | mask = select_one( args, cfg.aliases[list_name .. '-Mask'], 'redundant_parameters', i ); | ||
Line 1,404: | Line 1,423: | ||
end | end | ||
else -- we have last with or without a first | else -- we have last with or without a first | ||
link_title_ok (link, | link_title_ok (link, link_alias, last, last_alias); -- check for improper wikimarkup | ||
if first then | |||
link_title_ok (link, link_alias, first, first_alias); -- check for improper wikimarkup | |||
end | |||
names[n] = {last = last, first = first, link = link, mask = mask, corporate=false}; -- add this name to our names list (corporate for |vauthors= only) | names[n] = {last = last, first = first, link = link, mask = mask, corporate=false}; -- add this name to our names list (corporate for |vauthors= only) | ||
Line 1,483: | Line 1,505: | ||
Languages that are the same as the local wiki are not categorized. MediaWiki does not recognize three-character | Languages that are the same as the local wiki are not categorized. MediaWiki does not recognize three-character | ||
equivalents of two-character codes: code 'ar' is recognized | equivalents of two-character codes: code 'ar' is recognized but code 'ara' is not. | ||
This function supports multiple languages in the form |language=nb, French, th where the language names or codes are | This function supports multiple languages in the form |language=nb, French, th where the language names or codes are | ||
separated from each other by commas. | separated from each other by commas with optional space characters. | ||
]] | ]] | ||
Line 1,508: | Line 1,530: | ||
end | end | ||
else | 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 | 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 | name = mw.language.fetchLanguageName (lang:lower(), cfg.this_wiki_code); -- get language name if |language= is a proper code | ||
Line 1,546: | Line 1,566: | ||
name = table.concat (language_list, cfg.messages['parameter-pair-separator']) -- insert '<space>and<space>' between two language names | name = table.concat (language_list, cfg.messages['parameter-pair-separator']) -- insert '<space>and<space>' between two language names | ||
elseif 2 < code then | elseif 2 < code then | ||
name = table.concat (language_list, ', | name = table.concat (language_list, cfg.messages['parameter-separator'], 1, code-1); -- concatenate all but last | ||
name = name | name = table.concat ({name, language_list[code]}, cfg.messages['parameter-final-separator']); -- concatenate last with final separator | ||
end | end | ||
if this_wiki_name == name then | if this_wiki_name == name then | ||
Line 1,569: | Line 1,589: | ||
local function set_cs1_style (ps) | local function set_cs1_style (ps) | ||
if not is_set (ps) then -- unless | if not is_set (ps) then -- unless explicitly set to something | ||
ps = cfg.presentation['ps_cs1']; -- terminate the rendered citation | ps = cfg.presentation['ps_cs1']; -- terminate the rendered citation | ||
end | end | ||
Line 1,631: | Line 1,651: | ||
sep, ps, ref = get_settings_from_cite_class (ps, ref, cite_class); -- get settings based on the template's CitationClass | sep, ps, ref = get_settings_from_cite_class (ps, ref, cite_class); -- get settings based on the template's CitationClass | ||
end | end | ||
if | |||
if cfg.keywords_xlate[ps:lower()] == 'none' then -- if assigned value is 'none' then | |||
ps = ''; -- set to empty string | ps = ''; -- set to empty string | ||
end | end | ||
Line 1,820: | Line 1,841: | ||
elseif string.find(v_name, "%s") then | elseif string.find(v_name, "%s") then | ||
if v_name:find('[;%.]') then -- look for commonly occurring punctuation characters; | if v_name:find('[;%.]') then -- look for commonly occurring punctuation characters; | ||
add_vanc_error ( | add_vanc_error (cfg.err_msg_supl.punctuation); | ||
end | end | ||
local lastfirstTable = {} | local lastfirstTable = {} | ||
Line 1,831: | Line 1,852: | ||
last = table.concat(lastfirstTable, " ") -- returns a string that is the concatenation of all other names that are not initials | last = table.concat(lastfirstTable, " ") -- returns a string that is the concatenation of all other names that are not initials | ||
if mw.ustring.match (last, '%a+%s+%u+%s+%a+') then | if mw.ustring.match (last, '%a+%s+%u+%s+%a+') then | ||
add_vanc_error ('missing comma'); -- matches last II last; the case when a comma is missing | add_vanc_error (cfg.err_msg_supl['missing comma']); -- matches last II last; the case when a comma is missing | ||
end | end | ||
if mw.ustring.match (v_name, ' %u %u$') then -- this test is in the wrong place TODO: move or replace with a more appropriate test | if mw.ustring.match (v_name, ' %u %u$') then -- this test is in the wrong place TODO: move or replace with a more appropriate test | ||
add_vanc_error ( | add_vanc_error (cfg.err_msg_supl.name); -- matches a space between two intiials | ||
end | end | ||
else | else | ||
Line 1,843: | Line 1,864: | ||
if is_set (first) then | if is_set (first) then | ||
if not mw.ustring.match (first, "^%u?%u$") then -- first shall contain one or two upper-case letters, nothing else | if not mw.ustring.match (first, "^%u?%u$") then -- first shall contain one or two upper-case letters, nothing else | ||
add_vanc_error ( | add_vanc_error (cfg.err_msg_supl.initials); -- too many initials; mixed case initials (which may be ok Romanization); hyphenated initials | ||
end | end | ||
is_good_vanc_name (last, first); -- check first and last before restoring the suffix which may have a non-Latin digit | is_good_vanc_name (last, first); -- check first and last before restoring the suffix which may have a non-Latin digit | ||
Line 1,883: | Line 1,904: | ||
local function select_author_editor_source (vxxxxors, xxxxors, args, list_name) | local function select_author_editor_source (vxxxxors, xxxxors, args, list_name) | ||
local lastfirst = false; | local lastfirst = false; | ||
if select_one( args, cfg.aliases[list_name .. '-Last'], 'none', 1 ) or -- do this twice incase we have a |first1= without a |last1=; this ... | if select_one( args, cfg.aliases[list_name .. '-Last'], 'none', 1 ) or -- do this twice incase we have a |first1= without a |last1=; this ... | ||
select_one( args, cfg.aliases[list_name .. '-First'], 'none', 1 ) or -- ... also catches the case where |first= is used with |vauthors= | select_one( args, cfg.aliases[list_name .. '-First'], 'none', 1 ) or -- ... also catches the case where |first= is used with |vauthors= | ||
Line 2,105: | Line 2,126: | ||
return page, pages, at, coins_pages; | return page, pages, at, coins_pages; | ||
end | end | ||
Line 2,150: | Line 2,170: | ||
if url:match('//web%.archive%.org/save/') then -- if a save command url, we don't want to allow saving of the target page | if url:match('//web%.archive%.org/save/') then -- if a save command url, we don't want to allow saving of the target page | ||
err_msg = | err_msg = cfg.err_msg_supl.save; | ||
url = url:gsub ('(//web%.archive%.org)/save/', '%1/*/', 1); -- for preview mode: modify ArchiveURL | url = url:gsub ('(//web%.archive%.org)/save/', '%1/*/', 1); -- for preview mode: modify ArchiveURL | ||
elseif url:match('//liveweb%.archive%.org/') then | elseif url:match('//liveweb%.archive%.org/') then | ||
err_msg = | err_msg = cfg.err_msg_supl.liveweb; | ||
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 is_set(timestamp) or 14 ~= timestamp:len() then -- path and flag optional, must have 14-digit timestamp here | if not is_set(timestamp) or 14 ~= timestamp:len() then -- path and flag optional, must have 14-digit timestamp here | ||
err_msg = | 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) | 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 is_set(path) and 'web/' ~= path then -- older archive urls do not have the extra 'web/' path element | elseif is_set(path) and 'web/' ~= path then -- older archive urls do not have the extra 'web/' path element | ||
err_msg = | err_msg = cfg.err_msg_supl.path; | ||
elseif is_set (flag) and not is_set (path) then -- flag not allowed with the old form url (without the 'web/' path element) | elseif is_set (flag) and not is_set (path) then -- flag not allowed with the old form url (without the 'web/' path element) | ||
err_msg = | err_msg = cfg.err_msg_supl.flag; | ||
elseif is_set (flag) and not flag:match ('%a%a_') then -- flag if present must be two alpha characters and underscore (requires 'web/' path element) | elseif is_set (flag) and not flag:match ('%a%a_') then -- flag if present must be two alpha characters and underscore (requires 'web/' path element) | ||
err_msg = | err_msg = cfg.err_msg_supl.flag; | ||
else | else | ||
return url, date; -- return | return url, date; -- return ArchiveURL and ArchiveDate | ||
end | end | ||
end | end | ||
Line 2,175: | Line 2,195: | ||
table.insert( z.message_tail, { set_error( 'archive_url', {err_msg}, true ) } ); -- add error message and | table.insert( z.message_tail, { set_error( 'archive_url', {err_msg}, true ) } ); -- add error message and | ||
if is_set (Frame:preprocess('{{REVISIONID}}')) then | if is_set (Frame:preprocess('{{REVISIONID}}')) then | ||
return '', ''; -- return empty strings for | return '', ''; -- return empty strings for ArchiveURL and ArchiveDate | ||
else | else | ||
return url, date; -- preview mode so return | return url, date; -- preview mode so return ArchiveURL and ArchiveDate | ||
end | end | ||
end | end | ||
Line 2,192: | Line 2,212: | ||
local function place_check (param_val) | local function place_check (param_val) | ||
if not is_set (param_val) then | if not is_set (param_val) then -- parameter empty or omitted | ||
return param_val; -- return that empty state | return param_val; -- return that empty state | ||
end | end | ||
Line 2,280: | Line 2,300: | ||
local c = {}; -- contributors list from |contributor-lastn= / contributor-firstn= pairs | local c = {}; -- contributors list from |contributor-lastn= / contributor-firstn= pairs | ||
local Contributors; -- assembled contributors name list | local Contributors; -- assembled contributors name list | ||
local Contribution = A['Contribution']; | local Contribution = A['Contribution']; -- TODO: move to after chapter use if A:ORIGIN ('Chapter') ... to set Contribution; this to remove duplicate in aliases list | ||
if in_array(config.CitationClass, {"book","citation"}) and not is_set(A['Periodical']) then -- |contributor= and |contribution= only supported in book cites | if in_array(config.CitationClass, {"book","citation"}) and not is_set(A['Periodical']) then -- |contributor= and |contribution= only supported in book cites | ||
c = extract_names (args, 'ContributorList'); -- fetch contributor list from |contributorn= / |contributor-lastn=, -firstn=, -linkn=, -maskn= | c = extract_names (args, 'ContributorList'); -- fetch contributor list from |contributorn= / |contributor-lastn=, -firstn=, -linkn=, -maskn= | ||
Line 2,322: | Line 2,342: | ||
link_title_ok (TitleLink, A:ORIGIN ('TitleLink'), Title, 'title'); -- check for wikimarkup in |title-link= or wikimarkup in |title= when |title-link= is set | link_title_ok (TitleLink, A:ORIGIN ('TitleLink'), Title, 'title'); -- check for wikimarkup in |title-link= or wikimarkup in |title= when |title-link= is set | ||
local Chapter = A['Chapter']; | local Chapter = A['Chapter']; -- TODO: insert test, assignment, and then unset Chapter when |section= in cite map; test is at c. line 3220 | ||
local ScriptChapter = A['ScriptChapter']; | local ScriptChapter = A['ScriptChapter']; | ||
local ScriptChapterOrigin = A:ORIGIN ('ScriptChapter'); | local ScriptChapterOrigin = A:ORIGIN ('ScriptChapter'); | ||
Line 2,347: | Line 2,367: | ||
local ConferenceURL = A['ConferenceURL']; | local ConferenceURL = A['ConferenceURL']; | ||
local ConferenceURLorigin = A:ORIGIN('ConferenceURL'); -- get name of parameter that holds ConferenceURL | local ConferenceURLorigin = A:ORIGIN('ConferenceURL'); -- get name of parameter that holds ConferenceURL | ||
local Periodical = A['Periodical']; | |||
-- TODO: mailinglist should be removed from Periodical alias list; Periodical should be assigned value from |mailinglist= here wh | |||
local Periodical = A['Periodical']; -- cite mailinglist or citation and |mailinglist=; error check for duplicate work params (Periodical already set) | |||
local Periodical_origin = ''; | local Periodical_origin = ''; | ||
if is_set (Periodical) then | if is_set (Periodical) then | ||
Line 2,357: | Line 2,379: | ||
end | end | ||
end | end | ||
-- TODO: mailinglist assignment here? iff Periodical not set; err msg else; see TODO c. line 2607 | |||
local ScriptPeriodical = A['ScriptPeriodical']; | local ScriptPeriodical = A['ScriptPeriodical']; | ||
local ScriptPeriodical_origin = A:ORIGIN('ScriptPeriodical'); | local ScriptPeriodical_origin = A:ORIGIN('ScriptPeriodical'); | ||
Line 2,363: | Line 2,385: | ||
-- Wikipedia:Administrators%27_noticeboard#Is_there_a_semi-automated_tool_that_could_fix_these_annoying_"Cite_Web"_errors? | -- Wikipedia:Administrators%27_noticeboard#Is_there_a_semi-automated_tool_that_could_fix_these_annoying_"Cite_Web"_errors? | ||
if not (is_set (Periodical) or is_set (ScriptPeriodical)) then -- 'periodical' templates require periodical parameter | if not (is_set (Periodical) or is_set (ScriptPeriodical)) then -- 'periodical' templates require periodical parameter | ||
-- | -- local p = {['journal'] = 'journal', ['magazine'] = 'magazine', ['news'] = 'newspaper', ['web'] = 'website'}; -- for error message | ||
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 | ||
Line 2,428: | Line 2,450: | ||
end | end | ||
end | end | ||
local Newsgroup = A['Newsgroup']; -- TODO: strip apostrophe markup? | |||
local Newsgroup_origin = A:ORIGIN('Newsgroup'); | |||
if 'newsgroup' == config.CitationClass then | |||
if is_set (PublisherName) then -- general use parmeter |publisher= not allowed in cite newsgroup | |||
local error_text = set_error ('parameter_ignored', {PublisherName_origin}, true); | |||
if is_set (error_text) then | |||
table.insert( z.message_tail, {error_text, error_state} ); | |||
end | |||
end | |||
PublisherName = nil; -- ensure that this parameter is unset for the time being; will be used again after COinS | |||
end | |||
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); | ||
Line 2,494: | Line 2,530: | ||
local sepc; -- separator between citation elements for CS1 a period, for CS2, a comma | local sepc; -- separator between citation elements for CS1 a period, for CS2, a comma | ||
local PostScript; | local PostScript; | ||
local Ref; | local Ref = A['Ref']; | ||
sepc, PostScript, Ref = set_style (Mode:lower(), A['PostScript'], | if 'harv' == Ref then | ||
add_maint_cat ('ref_harv'); -- add maint cat to identify templates that have this now-extraneous param value | |||
elseif not is_set (Ref) then | |||
Ref = 'harv'; -- set as default when not set externally | |||
end | |||
sepc, PostScript, Ref = set_style (Mode:lower(), A['PostScript'], Ref, config.CitationClass); | |||
use_lowercase = ( sepc == ',' ); -- used to control capitalization for certain static text | use_lowercase = ( sepc == ',' ); -- used to control capitalization for certain static text | ||
Line 2,510: | Line 2,552: | ||
end | end | ||
end | end | ||
-- check for extra |page=, |pages= or |at= parameters. (also sheet and sheets while we're at it) | |||
select_one (args, {'page', 'p', 'pp', 'pages', 'at', 'sheet', 'sheets'}, 'redundant_parameters'); -- this is a dummy call simply to get the error message and category | |||
select_one( args, {'page', 'p', 'pp', 'pages', 'at', 'sheet', 'sheets'}, 'redundant_parameters' ); -- this is a dummy call simply to get the error message and category | |||
local coins_pages; | local coins_pages; | ||
Line 2,529: | Line 2,570: | ||
end | end | ||
if PublicationPlace == Place then Place = ''; end -- don't need both if they are the same | if PublicationPlace == Place then Place = ''; end -- don't need both if they are the same | ||
Line 2,548: | Line 2,585: | ||
]] | ]] | ||
local Encyclopedia = A['Encyclopedia']; | local Encyclopedia = A['Encyclopedia']; | ||
if ( config.CitationClass == "encyclopaedia" ) or ( config.CitationClass == "citation" and is_set (Encyclopedia)) then -- test code for citation | if ( config.CitationClass == "encyclopaedia" ) or ( config.CitationClass == "citation" and is_set (Encyclopedia)) then -- test code for citation | ||
Line 2,559: | Line 2,596: | ||
TransChapter = TransTitle; | TransChapter = TransTitle; | ||
ChapterURL = URL; | ChapterURL = URL; | ||
ChapterURLorigin = A:ORIGIN('URL') | |||
ChapterUrlAccess = UrlAccess; | ChapterUrlAccess = UrlAccess; | ||
Line 2,592: | Line 2,631: | ||
-- special case for cite mailing list | -- special case for cite mailing list | ||
if (config.CitationClass == "mailinglist") then | if (config.CitationClass == "mailinglist") then -- TODO: move this to Periodical assignment; see TODOs at c. line 2360 | ||
Periodical = A ['MailingList']; | Periodical = A ['MailingList']; | ||
elseif 'mailinglist' == Periodical_origin then | elseif 'mailinglist' == Periodical_origin then | ||
Line 2,602: | Line 2,641: | ||
if is_set(BookTitle) then | if is_set(BookTitle) then | ||
Chapter = Title; | Chapter = Title; | ||
-- | -- ChapterLink = TitleLink; -- |chapterlink= is deprecated | ||
ChapterURL = URL; | ChapterURL = URL; | ||
ChapterUrlAccess = UrlAccess; | ChapterUrlAccess = UrlAccess; | ||
Line 2,611: | Line 2,650: | ||
Title = BookTitle; | Title = BookTitle; | ||
Format = ''; | Format = ''; | ||
-- | -- TitleLink = ''; | ||
TransTitle = ''; | TransTitle = ''; | ||
URL = ''; | URL = ''; | ||
Line 2,647: | Line 2,686: | ||
-- Account for the oddities that are {{cite episode}} and {{cite serial}}, before generation of COinS data. | -- Account for the oddities that are {{cite episode}} and {{cite serial}}, before generation of COinS data. | ||
if 'episode' == config.CitationClass or 'serial' == config.CitationClass then | if 'episode' == config.CitationClass or 'serial' == config.CitationClass then | ||
local SeriesLink = A['SeriesLink']; | local SeriesLink = A['SeriesLink']; | ||
Line 2,660: | Line 2,698: | ||
ID = table.concat(n, sepc .. ' '); | ID = table.concat(n, sepc .. ' '); | ||
if 'episode' == config.CitationClass then -- handle the oddities that are strictly {{cite episode}} | if 'episode' == config.CitationClass then -- handle the oddities that are strictly {{cite episode}} | ||
local Season = A['Season']; | local Season = A['Season']; | ||
Line 2,680: | Line 2,714: | ||
Chapter = Title; -- promote title parameters to chapter | Chapter = Title; -- promote title parameters to chapter | ||
ScriptChapter = ScriptTitle; | ScriptChapter = ScriptTitle; | ||
ScriptChapterOrigin = A:ORIGIN('ScriptTitle'); | ScriptChapterOrigin = A:ORIGIN('ScriptTitle'); | ||
ChapterLink = TitleLink; -- alias episodelink | ChapterLink = TitleLink; -- alias episodelink | ||
Line 2,714: | Line 2,747: | ||
-- 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. | ||
do | do | ||
if in_array (config.CitationClass, | if in_array (config.CitationClass, whitelist.preprint_template_list) then | ||
if not is_set (ID_list[config.CitationClass:upper()]) then -- |arxiv= or |eprint= required for cite arxiv; |biorxiv= & |citeseerx= required for their templates | if not is_set (ID_list[config.CitationClass:upper()]) then -- |arxiv= or |eprint= required for cite arxiv; |biorxiv= & |citeseerx= required for their templates | ||
table.insert( z.message_tail, { set_error( config.CitationClass .. '_missing', {}, true ) } ); -- add error message | table.insert( z.message_tail, { set_error( config.CitationClass .. '_missing', {}, true ) } ); -- add error message | ||
Line 2,809: | Line 2,842: | ||
-- uncomment these three lines. Not supported by en.wiki (for obvious reasons) | -- uncomment these three lines. Not supported by en.wiki (for obvious reasons) | ||
-- set date_name_xlate() second argument to true to translate English digits to local digits (will translate ymd dates) | -- set date_name_xlate() second argument to true to translate English digits to local digits (will translate ymd dates) | ||
-- | -- if 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 | ||
Line 2,854: | Line 2,887: | ||
end | end | ||
if 'none' | if cfg.keywords_xlate[Title] == 'none' and | ||
in_array (config.CitationClass, {'journal', 'citation'}) and | in_array (config.CitationClass, {'journal', 'citation'}) and | ||
(is_set (Periodical) or is_set (ScriptPeriodical)) and | (is_set (Periodical) or is_set (ScriptPeriodical)) and | ||
Line 2,886: | Line 2,919: | ||
coins_author = c; -- use that instead | coins_author = c; -- use that instead | ||
end | end | ||
-- this is the function call to COinS() | -- this is the function call to COinS() | ||
local OCinSoutput = COinS({ | local OCinSoutput = COinS({ | ||
Line 2,903: | Line 2,936: | ||
['Pages'] = coins_pages or get_coins_pages (first_set ({Sheet, Sheets, Page, Pages, At}, 5)), -- pages stripped of external links | ['Pages'] = coins_pages or get_coins_pages (first_set ({Sheet, Sheets, Page, Pages, At}, 5)), -- pages stripped of external links | ||
['Edition'] = Edition, | ['Edition'] = Edition, | ||
['PublisherName'] = PublisherName, | ['PublisherName'] = PublisherName or Newsgroup, -- any apostrophe markup already removed from PublisherName | ||
['URL'] = first_set ({ChapterURL, URL}, 2), | ['URL'] = first_set ({ChapterURL, URL}, 2), | ||
['Authors'] = coins_author, | ['Authors'] = coins_author, | ||
Line 2,911: | Line 2,944: | ||
-- Account for the oddities that are {{cite arxiv}}, {{cite biorxiv}}, {{cite citeseerx}}, and {{cite ssrn}} AFTER generation of COinS data. | -- Account for the oddities that are {{cite arxiv}}, {{cite biorxiv}}, {{cite citeseerx}}, and {{cite ssrn}} AFTER generation of COinS data. | ||
if in_array (config.CitationClass, | if in_array (config.CitationClass, whitelist.preprint_template_list) then -- we have set rft.jtitle in COinS to arXiv, bioRxiv, CiteSeerX, or ssrn now unset so it isn't displayed | ||
Periodical = ''; -- periodical not allowed in these templates; if article has been published, use cite journal | Periodical = ''; -- periodical not allowed in these templates; if article has been published, use cite journal | ||
end | end | ||
-- special case for cite newsgroup. Do this after COinS because we are modifying Publishername to include some static text | -- special case for cite newsgroup. Do this after COinS because we are modifying Publishername to include some static text | ||
if 'newsgroup' == config.CitationClass | if 'newsgroup' == config.CitationClass and is_set (Newsgroup) then | ||
PublisherName = substitute (cfg.messages['newsgroup'], external_link( 'news:' .. Newsgroup, Newsgroup, Newsgroup_origin, nil )); | |||
end | end | ||
Line 2,932: | Line 2,963: | ||
maximum = nil, -- as if display-authors or display-editors not set | maximum = nil, -- as if display-authors or display-editors not set | ||
lastauthoramp = LastAuthorAmp, | lastauthoramp = LastAuthorAmp, | ||
mode = Mode | mode = Mode | ||
}; | }; | ||
Line 2,944: | Line 2,974: | ||
if editor_etal then | if editor_etal then | ||
Editors = Editors .. ' ' .. cfg.messages['et al']; -- add et al. to editors parameter beause |display-editors=etal | Editors = Editors .. ' ' .. cfg.messages['et al']; -- add et al. to editors parameter beause |display-editors=etal | ||
end | end | ||
EditorCount = 2; -- we don't know but assume |editors= is multiple names; spoof to display (eds.) annotation | |||
else | else | ||
Editors = last_first_list; -- either an author name list or an empty string | Editors = last_first_list; -- either an author name list or an empty string | ||
Line 3,088: | Line 3,116: | ||
end | end | ||
-- Format main title. | -- Format main title. TODO: add support for non-English versions of 'Archived copy' when used on other-language wikis | ||
if is_set (ArchiveURL) and mw.ustring.match (mw.ustring.lower(Title), cfg.special_case_translation | if is_set (ArchiveURL) and | ||
add_maint_cat ('archived_copy'); | (mw.ustring.match (mw.ustring.lower(Title), cfg.special_case_translation.archived_copy.en) or -- if title is 'Archived copy' (place holder added by bots that can't find proper title) | ||
mw.ustring.match (mw.ustring.lower(Title), cfg.special_case_translation.archived_copy['local'])) then -- local-wiki's form | |||
add_maint_cat ('archived_copy'); -- add maintenance category before we modify the content of Title | |||
end | end | ||
Line 3,103: | Line 3,133: | ||
end | end | ||
end | end | ||
if in_array(config.CitationClass, {'web', 'news', 'journal', 'magazine', 'pressrelease', 'podcast', 'newsgroup', 'mailinglist', 'interview', 'arxiv', 'biorxiv', 'citeseerx', 'ssrn'}) or | if in_array(config.CitationClass, {'web', 'news', 'journal', 'magazine', 'pressrelease', 'podcast', 'newsgroup', 'mailinglist', 'interview', 'arxiv', 'biorxiv', 'citeseerx', 'ssrn'}) or | ||
('citation' == config.CitationClass and (is_set (Periodical) or is_set (ScriptPeriodical)) and not is_set (Encyclopedia)) or | ('citation' == config.CitationClass and (is_set (Periodical) or is_set (ScriptPeriodical)) and not is_set (Encyclopedia)) or | ||
Line 3,129: | Line 3,159: | ||
end | end | ||
if is_set(Title) then | if is_set (Title) then -- TODO: is this the right place to be making wikisource urls? | ||
if not is_set (TitleLink) and is_set (URL) then | if not is_set (TitleLink) and is_set (URL) then | ||
Title = external_link (URL, Title, URLorigin, UrlAccess) .. TransTitle .. TransError .. Format; | Title = external_link (URL, Title, URLorigin, UrlAccess) .. TransTitle .. TransError .. Format; | ||
Line 3,145: | Line 3,175: | ||
end | end | ||
else | else | ||
local ws_url, ws_label; | local ws_url, ws_label; -- Title has italic or quote markup by the time we get here which causes is_wikilink() to return 0 (not a wikilink) | ||
ws_url, ws_label, L = wikisource_url_make (Title); | ws_url, ws_label, L = wikisource_url_make (Title:gsub('[\'"](.-)[\'"]', '%1')); -- make ws url from |title= interwiki link (strip italic or quote markup); link portion L becomes tool tip label | ||
if ws_url then | if ws_url then | ||
Title = Title:gsub ('%b[]', ws_label); -- replace interwiki link with ws_label to retain markup | Title = Title:gsub ('%b[]', ws_label); -- replace interwiki link with ws_label to retain markup | ||
Line 3,203: | Line 3,233: | ||
At = is_set(At) and (sepc .. " " .. At) or ""; | At = is_set(At) and (sepc .. " " .. At) or ""; | ||
Position = is_set(Position) and (sepc .. " " .. Position) or ""; | Position = is_set(Position) and (sepc .. " " .. Position) or ""; | ||
if config.CitationClass == 'map' then | if config.CitationClass == 'map' then -- TODO copy this line and | ||
local Section = A['Section']; | local Section = A['Section']; -- TODO move this line to c. line 2337 so that separate Sections in aliases{} not required? then unset Chapter? | ||
local Sections = A['Sections']; | local Sections = A['Sections']; | ||
local Inset = A['Inset']; | local Inset = A['Inset']; | ||
Line 3,530: | Line 3,560: | ||
end | end | ||
if is_set(Ref) and Ref:lower() | if is_set(Ref) and 'none' ~= cfg.keywords_xlate[Ref:lower()] then | ||
local id = Ref | local id = Ref | ||
if ('harv' == Ref ) then | if ('harv' == Ref ) then | ||
Line 3,594: | Line 3,624: | ||
end | end | ||
if not no_tracking_cats then | if not no_tracking_cats then | ||
for _, v in ipairs( z.error_categories ) do | for _, v in ipairs( z.error_categories ) do | ||
Line 3,626: | Line 3,654: | ||
local name = tostring (name); | local name = tostring (name); | ||
local state; | local state; | ||
local function state_test (state, name) -- local function to do testing of state values | |||
if true == state then return true; end -- valid actively supported parameter | if true == state then return true; end -- valid actively supported parameter | ||
if false == state then | if false == state then | ||
Line 3,634: | Line 3,660: | ||
return true; | return true; | ||
end | end | ||
return nil; | |||
end | |||
state = whitelist[cite_class | if name:find ('#') then -- # is a cs1|2 reserved character so parameters with # not permitted | ||
return nil; | |||
end | |||
if in_array (cite_class, whitelist.preprint_template_list ) then -- limited parameter sets allowed for these templates | |||
state = whitelist.limited_basic_arguments[name]; | |||
if true == state_test (state, name) then return true; end | |||
state = whitelist.preprint_arguments[cite_class][name]; -- look in the parameter-list for the template identified by cite_class | |||
if true == state_test (state, name) then return true; end | |||
-- limited enumerated parameters list | -- limited enumerated parameters list | ||
name = name:gsub("%d+", "#" ); -- replace digit(s) with # (last25 becomes last#) (mw.ustring because non-Western 'local' digits) | name = name:gsub("%d+", "#" ); -- replace digit(s) with # (last25 becomes last#) (mw.ustring because non-Western 'local' digits) | ||
state = whitelist.limited_numbered_arguments[name]; | state = whitelist.limited_numbered_arguments[name]; | ||
if true == state | if true == state_test (state, name) then return true; end | ||
return false; -- not supported because not found or name is set to nil | return false; -- not supported because not found or name is set to nil | ||
end -- end limited parameter-set templates | end -- end limited parameter-set templates | ||
if in_array (cite_class, whitelist.unique_param_template_list) then -- experiment for template-specific parameters for templates that accept parameters from the basic argument list | |||
state = whitelist.unique_arguments[cite_class][name]; -- look in the template-specific parameter-lists for the template identified by cite_class | |||
if true == state_test (state, name) then return true; end | |||
end -- if here, fall into general validation | |||
state = whitelist.basic_arguments[name]; -- all other templates; all normal parameters allowed | state = whitelist.basic_arguments[name]; -- all other templates; all normal parameters allowed | ||
if true == state_test (state, name) then return true; end | |||
if true == state then return true; end | |||
-- all enumerated parameters allowed | -- all enumerated parameters allowed | ||
name = name:gsub("%d+", "#" ); -- replace digit(s) with # (last25 becomes last#) (mw.ustring because non-Western 'local' digits) | name = name:gsub("%d+", "#" ); -- replace digit(s) with # (last25 becomes last#) (mw.ustring because non-Western 'local' digits) | ||
state = whitelist.numbered_arguments[name]; | state = whitelist.numbered_arguments[name]; | ||
if true == state_test (state, name) then return true; end | |||
return false; -- not supported because not found or name is set to nil | return false; -- not supported because not found or name is set to nil | ||
end | end |