Module:Citation/CS1: Difference between revisions
synch from sandbox;
m>Trappist the monk (interim fix to kern_quotes(); see discussion;) |
m>Trappist the monk (synch from sandbox;) |
||
Line 5: | Line 5: | ||
]] | ]] | ||
local dates, year_date_check, reformat_dates, date_hyphen_to_dash -- functions in Module:Citation/CS1/Date_validation | local dates, year_date_check, reformat_dates, date_hyphen_to_dash, -- functions in Module:Citation/CS1/Date_validation | ||
date_name_xlate | |||
local is_set, in_array, substitute, error_comment, set_error, select_one, -- functions in Module:Citation/CS1/Utilities | local is_set, in_array, substitute, error_comment, set_error, select_one, -- functions in Module:Citation/CS1/Utilities | ||
add_maint_cat, wrap_style, safe_for_italics, | add_maint_cat, wrap_style, safe_for_italics, is_wikilink, make_wikilink; | ||
local z ={}; -- tables in Module:Citation/CS1/Utilities | local z ={}; -- tables in Module:Citation/CS1/Utilities | ||
Line 54: | Line 55: | ||
end | end | ||
end | end | ||
--[[--------------------------< A D D _ P R O P _ C A T >-------------------------------------------------------- | --[[--------------------------< A D D _ P R O P _ C A T >-------------------------------------------------------- | ||
Adds a category to z.properties_cats using names from the configuration file with additional text if any. | Adds a category to z.properties_cats using names from the configuration file with additional text if any. | ||
foreign_lang_source and foreign_lang_source_2 keys have a language code appended to them so that multiple languages | |||
may be categorized but multiples of the same language are not categorized. | |||
added_prop_cats is a table declared in page scope variables above | added_prop_cats is a table declared in page scope variables above | ||
Line 66: | Line 71: | ||
if not added_prop_cats [key] then | if not added_prop_cats [key] then | ||
added_prop_cats [key] = true; -- note that we've added this category | added_prop_cats [key] = true; -- note that we've added this category | ||
key = key:gsub ('(foreign_lang_source_?2?)%a%a%a?', '%1'); -- strip lang code from keyname | |||
table.insert( z.properties_cats, substitute (cfg.prop_cats [key], arguments)); -- make name then add to table | table.insert( z.properties_cats, substitute (cfg.prop_cats [key], arguments)); -- make name then add to table | ||
end | end | ||
end | end | ||
--[[--------------------------< A D D _ V A N C _ E R R O R >---------------------------------------------------- | --[[--------------------------< A D D _ V A N C _ E R R O R >---------------------------------------------------- | ||
Line 126: | Line 133: | ||
the first character of the whole domain name including subdomains must be a letter or a digit | the first character of the whole domain name including subdomains must be a letter or a digit | ||
internationalized domain name (ascii characters with .xn-- ASCII Compatible Encoding (ACE) prefix xn-- in the tld) see https://tools.ietf.org/html/rfc3490 | internationalized domain name (ascii characters with .xn-- ASCII Compatible Encoding (ACE) prefix xn-- in the tld) see https://tools.ietf.org/html/rfc3490 | ||
single-letter/digit second-level domains in the .org | single-letter/digit second-level domains in the .org and .cash TLDs | ||
q, x, and z SL domains in the .com TLD | q, x, and z SL domains in the .com TLD | ||
i and q SL domains in the .net TLD | i and q SL domains in the .net TLD | ||
Line 153: | Line 160: | ||
elseif domain:match ('%f[%a%d][%a%d][%a%d%-]+[%a%d]%.xn%-%-[%a%d]+$') then -- internationalized domain name with ACE prefix | elseif domain:match ('%f[%a%d][%a%d][%a%d%-]+[%a%d]%.xn%-%-[%a%d]+$') then -- internationalized domain name with ACE prefix | ||
return true; | return true; | ||
elseif domain:match ('%f[%a%d][%a%d]%.org$') then -- one character .org hostname | elseif domain:match ('%f[%a%d][%a%d]%.cash$') then -- one character/digit .cash hostname | ||
return true; | |||
elseif domain:match ('%f[%a%d][%a%d]%.org$') then -- one character/digit .org hostname | |||
return true; | return true; | ||
elseif domain:match ('%f[%a][qxz]%.com$') then -- assigned one character .com hostname (x.com times out 2015-12-10) | elseif domain:match ('%f[%a][qxz]%.com$') then -- assigned one character .com hostname (x.com times out 2015-12-10) | ||
Line 249: | Line 258: | ||
return not is_url (scheme, domain); -- return true if value DOES NOT appear to be a valid url | return not is_url (scheme, domain); -- return true if value DOES NOT appear to be a valid url | ||
end | end | ||
--[[--------------------------< L I N K _ T I T L E _ O K >--------------------------------------------------- | --[[--------------------------< L I N K _ T I T L E _ O K >--------------------------------------------------- | ||
Line 376: | Line 386: | ||
['\n'] = ' ' } ); | ['\n'] = ' ' } ); | ||
end | end | ||
--[[--------------------------< E X T E R N A L _ L I N K >---------------------------------------------------- | --[[--------------------------< E X T E R N A L _ L I N K >---------------------------------------------------- | ||
Line 408: | Line 419: | ||
if is_set (access) then -- access level (subscription, registration, limited) | if is_set (access) then -- access level (subscription, registration, limited) | ||
label = safe_for_url (label); -- replace square brackets and newlines | |||
base_url = table.concat ( -- assemble external link with access signal | |||
{ | { | ||
'<span class="plainlinks">[', -- opening css | '<span class="plainlinks">[', -- opening css and url markup | ||
URL, -- the url | URL, -- the url | ||
' ', -- the required space | ' ', -- the required space | ||
label, | |||
'<span style="padding-left:0.15em">', -- signal spacing css | '<span style="padding-left:0.15em">', -- signal spacing css | ||
cfg.presentation[access], -- the appropriate icon | cfg.presentation[access], -- the appropriate icon | ||
' | '</span>', -- close signal spacing span | ||
']</span>' -- close url markup and plain links span | |||
']</span>' -- close | |||
}); | }); | ||
else | else | ||
Line 462: | Line 457: | ||
end | end | ||
Apply kerning to open the space between the quote mark provided by the Module and a leading or trailing quote mark contained in a |title= or |chapter= parameter's value. | --[=[-------------------------< K E R N _ Q U O T E S >-------------------------------------------------------- | ||
Apply kerning to open the space between the quote mark provided by the Module and a leading or trailing quote | |||
mark contained in a |title= or |chapter= parameter's value. | |||
This function will positive kern either single or double quotes: | This function will positive kern either single or double quotes: | ||
"'Unkerned title with leading and trailing single quote marks'" | "'Unkerned title with leading and trailing single quote marks'" | ||
Line 470: | Line 468: | ||
Double single quotes (italic or bold wikimarkup) are not kerned. | Double single quotes (italic or bold wikimarkup) are not kerned. | ||
Replaces unicode quotemarks with typewriter quote marks regardless of the need for kerning. | Replaces unicode quotemarks in plain text or in the label portion of a [[L|D]] style wikilink with typewriter | ||
quote marks regardless of the need for kerning. Unicode quote marks are not replaced in simple [[D]] wikilinks. | |||
Call this function for chapter titles, for website titles, etc; not for book titles. | Call this function for chapter titles, for website titles, etc; not for book titles. | ||
]] | ]=] | ||
local function kern_quotes (str) | local function kern_quotes (str) | ||
local cap=''; | local cap=''; | ||
local cap2=''; | local cap2=''; | ||
local wl_type, label, link; | |||
wl_type, label, link = is_wikilink (str); -- wl_type is: 0, no wl (text in label variable); 1, [[D]]; 2, [[L|D]] | |||
if 1 == wl_type then -- [[D]] simple wikilink with or without quote marks | |||
if mw.ustring.match (str, '%[%[[\"“”\'‘’].+[\"“”\'‘’]%]%]') then -- leading and trailing quote marks | |||
str = substitute (cfg.presentation['kern-wl-both'], str); | |||
elseif mw.ustring.match (str, '%[%[[\"“”\'‘’].+%]%]') then -- leading quote marks | |||
str = substitute (cfg.presentation['kern-wl-left'], str); | |||
elseif mw.ustring.match (str, '%[%[.+[\"“”\'‘’]%]%]') then -- trailing quote marks | |||
str = substitute (cfg.presentation['kern-wl-right'], str); | |||
end | |||
else -- plain text or [[L|D]]; text in label variable | |||
label= mw.ustring.gsub (label, '[“”]', '\"'); -- replace “” (U+201C & U+201D) with " (typewriter double quote mark) | |||
label= mw.ustring.gsub (label, '[‘’]', '\''); -- replace ‘’ (U+2018 & U+2019) with ' (typewriter single quote mark) | |||
cap, cap2 = | cap, cap2 = mw.ustring.match (label, "^([\"\'])([^\'].+)"); -- match leading double or single quote but not doubled single quotes (italic markup) | ||
if is_set (cap) then | |||
label = substitute (cfg.presentation['kern-left'], {cap, cap2}); | |||
end | |||
cap, cap2 = mw.ustring.match (label, "^(.+[^\'])([\"\'])$") -- match trailing double or single quote but not doubled single quotes (italic markup) | |||
if is_set (cap) then | |||
label = substitute (cfg.presentation['kern-right'], {cap, cap2}); | |||
end | |||
if 2 == wl_type then | |||
str = make_wikilink (link, label); -- reassemble the wikilink | |||
else | |||
str = label; | |||
end | |||
end | end | ||
return str; | return str; | ||
end | end | ||
--[[--------------------------< F O R M A T _ S C R I P T _ V A L U E >---------------------------------------- | --[[--------------------------< F O R M A T _ S C R I P T _ V A L U E >---------------------------------------- | ||
Line 547: | Line 567: | ||
return script_value; | return script_value; | ||
end | end | ||
--[[--------------------------< 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 >------------------------------------------ | ||
Line 594: | Line 615: | ||
]] | ]] | ||
local function format_chapter_title (scriptchapter, chapter, transchapter, chapterurl, chapter_url_source, no_quotes) | local function format_chapter_title (scriptchapter, chapter, transchapter, chapterurl, chapter_url_source, no_quotes, access) | ||
local chapter_error = ''; | local chapter_error = ''; | ||
Line 601: | Line 622: | ||
else | else | ||
if false == no_quotes then | if false == no_quotes then | ||
chapter = kern_quotes (chapter); | chapter = kern_quotes (chapter); -- if necessary, separate chapter title's leading and trailing quote marks from Module provided quote marks | ||
chapter = wrap_style ('quoted-title', chapter); | chapter = wrap_style ('quoted-title', chapter); | ||
end | end | ||
Line 619: | Line 640: | ||
if is_set (chapterurl) then | if is_set (chapterurl) then | ||
chapter = external_link (chapterurl, chapter, chapter_url_source, | chapter = external_link (chapterurl, chapter, chapter_url_source, access); -- adds bare_url_missing_title error if appropriate | ||
end | end | ||
return chapter .. chapter_error; | return chapter .. chapter_error; | ||
end | end | ||
--[[--------------------------< H A S _ I N V I S I B L E _ C H A R S >---------------------------------------- | --[[--------------------------< H A S _ I N V I S I B L E _ C H A R S >---------------------------------------- | ||
Line 659: | Line 681: | ||
local pattern=cfg.invisible_chars[i][2] -- the pattern used to find it | local pattern=cfg.invisible_chars[i][2] -- the pattern used to find it | ||
position, dummy, capture = mw.ustring.find (v, pattern) -- see if the parameter value contains characters that match the pattern | position, dummy, capture = mw.ustring.find (v, pattern) -- see if the parameter value contains characters that match the pattern | ||
if position and (char == 'zero width joiner') then -- if we found a zero width joiner character | |||
if mw.ustring.find (v, cfg.indic_script) then -- its ok if one of the indic scripts | |||
position = nil; -- unset position | |||
end | |||
end | |||
if position then | if position then | ||
Line 730: | Line 758: | ||
}); | }); | ||
end | end | ||
--[[--------------------------< V A L I D A T E >-------------------------------------------------------------- | --[[--------------------------< V A L I D A T E >-------------------------------------------------------------- | ||
Line 742: | Line 771: | ||
]] | ]] | ||
local function validate( name, cite_class ) | local function validate( name, cite_class ) | ||
local name = tostring( name ); | local name = tostring( name ); | ||
local state; | local state; | ||
if in_array (cite_class, {'arxiv', 'biorxiv', 'citeseerx'}) then | if in_array (cite_class, {'arxiv', 'biorxiv', 'citeseerx'}) then -- limited parameter sets allowed for these templates | ||
state = whitelist.limited_basic_arguments[ name ]; | state = whitelist.limited_basic_arguments[ name ]; | ||
if true == state then return true; end -- valid actively supported parameter | if true == state then return true; end -- valid actively supported parameter | ||
Line 826: | Line 854: | ||
return date; | return date; | ||
end | end | ||
--[[--------------------------< S E T _ T I T L E T Y P E >---------------------------------------------------- | --[[--------------------------< S E T _ T I T L E T Y P E >---------------------------------------------------- | ||
Line 909: | Line 938: | ||
elseif end_chr == "]" then -- if it might be wikimarkup | elseif end_chr == "]" then -- if it might be wikimarkup | ||
if str:sub(-3,-1) == duplicate_char .. "]]" then -- if last three chars of str are sepc]] wikilink | if str:sub(-3,-1) == duplicate_char .. "]]" then -- if last three chars of str are sepc]] wikilink | ||
trim = true; | |||
elseif str:sub(-3,-1) == duplicate_char .. '"]' then -- if last three chars of str are sepc"] quoted external link | |||
trim = true; | trim = true; | ||
elseif str:sub(-2,-1) == duplicate_char .. "]" then -- if last two chars of str are sepc] external link | elseif str:sub(-2,-1) == duplicate_char .. "]" then -- if last two chars of str are sepc] external link | ||
Line 951: | Line 982: | ||
return false; | return false; | ||
end | end | ||
--[[--------------------------< I S _ G O O D _ V A N C _ N A M E >-------------------------------------------- | --[[--------------------------< I S _ G O O D _ V A N C _ N A M E >-------------------------------------------- | ||
Line 997: | Line 1,029: | ||
return true; | return true; | ||
end | end | ||
--[[--------------------------< R E D U C E _ T O _ I N I T I A L S >------------------------------------------ | --[[--------------------------< R E D U C E _ T O _ I N I T I A L S >------------------------------------------ | ||
Line 1,055: | Line 1,088: | ||
return table.concat(initials) -- Vancouver format does not include spaces. | return table.concat(initials) -- Vancouver format does not include spaces. | ||
end | end | ||
--[[--------------------------< L I S T _ P E O P L E >------------------------------------------------------- | --[[--------------------------< L I S T _ P E O P L E >------------------------------------------------------- | ||
Line 1,073: | Line 1,107: | ||
sep = ','; -- name-list separator between authors is a comma | sep = ','; -- name-list separator between authors is a comma | ||
namesep = ' '; -- last/first separator is a space | namesep = ' '; -- last/first separator is a space | ||
else | else | ||
sep = ';' -- name-list separator between authors is a semicolon | sep = ';' -- name-list separator between authors is a semicolon | ||
Line 1,104: | Line 1,135: | ||
local first = person.first | local first = person.first | ||
if is_set(first) then | if is_set(first) then | ||
if | if ( "vanc" == format ) then -- if vancouver format | ||
one = one:gsub ('%.', ''); -- remove periods from surnames (http://www.ncbi.nlm.nih.gov/books/NBK7271/box/A35029/) | |||
if not person.corporate and is_good_vanc_name (one, first) then -- and name is all Latin characters; corporate authors not tested | |||
first = reduce_to_initials(first) -- attempt to convert first name(s) to initials | |||
end | end | ||
end | |||
one = one .. namesep .. first; | |||
end | end | ||
if is_set(person.link) and person.link ~= control.page_name then | if is_set(person.link) and person.link ~= control.page_name then | ||
one = | one = make_wikilink (person.link, one); -- link author/editor if this page is not the author's/editor's page | ||
end | end | ||
end | end | ||
Line 1,132: | Line 1,155: | ||
if count > 0 then | if count > 0 then | ||
if count > 1 and is_set(lastauthoramp) and not etal then | if count > 1 and is_set(lastauthoramp) and not etal then | ||
text[#text-2] = " & "; -- replace last separator with ampersand text | |||
end | end | ||
text[#text] = nil; -- erase the last separator | text[#text] = nil; -- erase the last separator | ||
Line 1,148: | Line 1,167: | ||
return result, count | return result, count | ||
end | end | ||
--[[--------------------------< A N C H O R _ I D >------------------------------------------------------------ | --[[--------------------------< A N C H O R _ I D >------------------------------------------------------------ | ||
Line 1,227: | Line 1,247: | ||
'^[%(%[]?%s*[Ee][Dd][Ii][Tt][Oo][Rr][Ss]?%A', -- (editor or (editors: also sq brackets, case insensitive, optional brackets, 's' | '^[%(%[]?%s*[Ee][Dd][Ii][Tt][Oo][Rr][Ss]?%A', -- (editor or (editors: also sq brackets, case insensitive, optional brackets, 's' | ||
'^[%(%[]?%s*[Ee][Dd][Ii][Tt][Ee][Dd]%A', -- (edited: also sq brackets, case insensitive, optional brackets | '^[%(%[]?%s*[Ee][Dd][Ii][Tt][Ee][Dd]%A', -- (edited: also sq brackets, case insensitive, optional brackets | ||
} | } | ||
Line 1,349: | Line 1,368: | ||
return names, etal; -- all done, return our list of names | return names, etal; -- all done, return our list of names | ||
end | end | ||
--[[--------------------------< G E T _ I S O 6 3 9 _ C O D E >------------------------------------------------ | --[[--------------------------< G E T _ I S O 6 3 9 _ C O D E >------------------------------------------------ | ||
Line 1,440: | Line 1,460: | ||
if this_wiki_code ~= code then -- when the language is not the same as this wiki's language | if this_wiki_code ~= code then -- when the language is not the same as this wiki's language | ||
if 2 == code:len() then -- and is a two-character code | if 2 == code:len() then -- and is a two-character code | ||
add_prop_cat ('foreign_lang_source', {name, code}) -- categorize it | add_prop_cat ('foreign_lang_source' .. code, {name, code}) -- categorize it | ||
else -- or is a recognized language (but has a three-character code) | else -- or is a recognized language (but has a three-character code) | ||
add_prop_cat ('foreign_lang_source_2', {code}) -- categorize it differently TODO: support mutliple three-character code categories per cs1|2 template | add_prop_cat ('foreign_lang_source_2' .. code, {code}) -- categorize it differently TODO: support mutliple three-character code categories per cs1|2 template | ||
end | end | ||
end | end | ||
Line 1,468: | Line 1,488: | ||
]] | ]] | ||
end | end | ||
--[[--------------------------< S E T _ C S 1 _ S T Y L E >---------------------------------------------------- | --[[--------------------------< S E T _ C S 1 _ S T Y L E >---------------------------------------------------- | ||
Line 1,481: | Line 1,502: | ||
return '.', ps; -- separator is a full stop | return '.', ps; -- separator is a full stop | ||
end | end | ||
--[[--------------------------< S E T _ C S 2 _ S T Y L E >---------------------------------------------------- | --[[--------------------------< S E T _ C S 2 _ S T Y L E >---------------------------------------------------- | ||
Line 1,497: | Line 1,519: | ||
return ',', ps, ref; -- separator is a comma | return ',', ps, ref; -- separator is a comma | ||
end | end | ||
--[[--------------------------< G E T _ S E T T I N G S _ F R O M _ C I T E _ C L A S S >---------------------- | --[[--------------------------< G E T _ S E T T I N G S _ F R O M _ C I T E _ C L A S S >---------------------- | ||
Line 1,515: | Line 1,538: | ||
return sep, ps, ref -- return them all | return sep, ps, ref -- return them all | ||
end | end | ||
--[[--------------------------< S E T _ S T Y L E >------------------------------------------------------------ | --[[--------------------------< S E T _ S T Y L E >------------------------------------------------------------ | ||
Line 1,528: | Line 1,552: | ||
sep, ps, ref = set_cs2_style (ps, ref); | sep, ps, ref = set_cs2_style (ps, ref); | ||
elseif 'cs1' == mode then -- if this template is to be rendered in CS1 (cite xxx) style | elseif 'cs1' == mode then -- if this template is to be rendered in CS1 (cite xxx) style | ||
sep, ps = set_cs1_style (ps); | sep, ps = set_cs1_style (ps); | ||
else -- anything but cs1 or cs2 | else -- anything but cs1 or cs2 | ||
Line 1,540: | Line 1,562: | ||
return sep, ps, ref | return sep, ps, ref | ||
end | end | ||
--[=[-------------------------< I S _ P D F >------------------------------------------------------------------ | --[=[-------------------------< I S _ P D F >------------------------------------------------------------------ | ||
Line 1,546: | Line 1,569: | ||
applying the pdf icon to external links. | applying the pdf icon to external links. | ||
returns true if file extension is one of the recognized | returns true if file extension is one of the recognized extensions, else false | ||
]=] | ]=] | ||
local function is_pdf (url) | local function is_pdf (url) | ||
return url:match ('%.pdf[%?#] | return url:match ('%.pdf$') or url:match ('%.PDF$') or url:match ('%.pdf[%?#]') or url:match ('%.PDF[%?#]'); | ||
end | end | ||
--[[--------------------------< S T Y L E _ F O R M A T >------------------------------------------------------ | --[[--------------------------< S T Y L E _ F O R M A T >------------------------------------------------------ | ||
Line 1,565: | Line 1,589: | ||
local function style_format (format, url, fmt_param, url_param) | local function style_format (format, url, fmt_param, url_param) | ||
if is_set (format) then | if is_set (format) then | ||
format = wrap_style ('format', format); -- add leading space, | format = wrap_style ('format', format); -- add leading space, parentheses, resize | ||
if not is_set (url) then | if not is_set (url) then | ||
format = format .. set_error( 'format_missing_url', {fmt_param, url_param} ); -- add an error message | format = format .. set_error( 'format_missing_url', {fmt_param, url_param} ); -- add an error message | ||
Line 1,576: | Line 1,600: | ||
return format; | return format; | ||
end | end | ||
--[[--------------------------< G E T _ D I S P L A Y _ A U T H O R S _ E D I T O R S >------------------------ | --[[--------------------------< G E T _ D I S P L A Y _ A U T H O R S _ E D I T O R S >------------------------ | ||
Line 1,618: | Line 1,643: | ||
return max, etal; | return max, etal; | ||
end | end | ||
--[[--------------------------< E X T R A _ T E X T _ I N _ P A G E _ C H E C K >------------------------------ | --[[--------------------------< E X T R A _ T E X T _ I N _ P A G E _ C H E C K >------------------------------ | ||
Line 1,631: | Line 1,657: | ||
local function extra_text_in_page_check (page) | local function extra_text_in_page_check (page) | ||
local good_pattern = '^P[^%.Pp]'; -- ok to begin with uppercase P: P7 (pg 7 of section P) but not p123 (page 123) TODO: add Gg for PG or Pg? | local good_pattern = '^P[^%.Pp]'; -- ok to begin with uppercase P: P7 (pg 7 of section P) but not p123 (page 123) TODO: add Gg for PG or Pg? | ||
local bad_pattern = '^[Pp]?[Pp]%.?[ %d]'; | local bad_pattern = '^[Pp]?[Pp]%.?[ %d]'; | ||
Line 1,639: | Line 1,663: | ||
add_maint_cat ('extra_text'); | add_maint_cat ('extra_text'); | ||
end | end | ||
end | end | ||
split apart a | | --[=[-------------------------< G E T _ V _ N A M E _ T A B L E >---------------------------------------------- | ||
split apart a |vauthors= or |veditors= parameter. This function allows for corporate names, wrapped in doubled | |||
parentheses to also have commas; in the old version of the code, the doubled parnetheses were included in the | parentheses to also have commas; in the old version of the code, the doubled parnetheses were included in the | ||
rendered citation and in the metadata. | rendered citation and in the metadata. Individual author names may be wikilinked | ||
|vauthors=Jones AB, White EB, ((Black, Brown, and Co.)) | |vauthors=Jones AB, [[E. B. White|White EB]], ((Black, Brown, and Co.)) | ||
]=] | |||
local function get_v_name_table (vparam, output_table, output_link_table) | |||
local function get_v_name_table (vparam, output_table) | |||
local name_table = mw.text.split(vparam, "%s*,%s*"); -- names are separated by commas | local name_table = mw.text.split(vparam, "%s*,%s*"); -- names are separated by commas | ||
local wl_type, label, link; -- wl_type not used here; just a place holder | |||
local i = 1; | local i = 1; | ||
Line 1,673: | Line 1,694: | ||
end | end | ||
table.insert (output_table, name); -- and add corporate name to the output table | table.insert (output_table, name); -- and add corporate name to the output table | ||
table.insert (output_link_table, ''); -- no wikilink | |||
else | else | ||
table.insert (output_table, | wl_type, label, link = is_wikilink (name_table[i]); -- wl_type is: 0, no wl (text in label variable); 1, [[D]]; 2, [[L|D]] | ||
table.insert (output_table, label); -- add this name | |||
if 1 == wl_type then | |||
table.insert (output_link_table, label); -- simple wikilink [[D]] | |||
else | |||
table.insert (output_link_table, link); -- no wikilink or [[L|D]]; add this link if there is one, else empty string | |||
end | |||
end | end | ||
i = i+1; | i = i+1; | ||
Line 1,680: | Line 1,708: | ||
return output_table; | return output_table; | ||
end | end | ||
--[[--------------------------< P A R S E _ V A U T H O R S _ V E D I T O R S >-------------------------------- | --[[--------------------------< P A R S E _ V A U T H O R S _ V E D I T O R S >-------------------------------- | ||
Line 1,699: | Line 1,728: | ||
local names = {}; -- table of names assembled from |vauthors=, |author-maskn=, |author-linkn= | local names = {}; -- table of names assembled from |vauthors=, |author-maskn=, |author-linkn= | ||
local v_name_table = {}; | local v_name_table = {}; | ||
local v_link_table = {}; -- when name is wikilinked, targets go in this table | |||
local etal = false; -- return value set to true when we find some form of et al. vauthors parameter | local etal = false; -- return value set to true when we find some form of et al. vauthors parameter | ||
local last, first, link, mask, suffix; | local last, first, link, mask, suffix; | ||
Line 1,704: | Line 1,734: | ||
vparam, etal = name_has_etal (vparam, etal, true); -- find and remove variations on et al. do not categorize (do it here because et al. might have a period) | vparam, etal = name_has_etal (vparam, etal, true); -- find and remove variations on et al. do not categorize (do it here because et al. might have a period) | ||
v_name_table = get_v_name_table (vparam, v_name_table, v_link_table); -- names are separated by commas | |||
v_name_table = get_v_name_table (vparam, v_name_table); -- names are separated by commas | |||
for i, v_name in ipairs(v_name_table) do | for i, v_name in ipairs(v_name_table) do | ||
Line 1,751: | Line 1,778: | ||
end | end | ||
end | end | ||
link = select_one( args, cfg.aliases[list_name .. '-Link'], 'redundant_parameters', i ); | link = select_one( args, cfg.aliases[list_name .. '-Link'], 'redundant_parameters', i ) or v_link_table[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 ); | ||
names[i] = {last = last, first = first, link = link, mask = mask, corporate=corporate}; -- add this assembled name to our names list | names[i] = {last = last, first = first, link = link, mask = mask, corporate=corporate}; -- add this assembled name to our names list | ||
Line 1,811: | Line 1,838: | ||
This function is used to validate a parameter's assigned value for those parameters that have only a limited number | This function is used to validate a parameter's assigned value for those parameters that have only a limited number | ||
of allowable values (yes, y, true, no, etc). When the parameter value has not been assigned a value (missing or empty | of allowable values (yes, y, true, no, etc). When the parameter value has not been assigned a value (missing or empty | ||
in the source template) the function | in the source template) the function returns true. If the parameter value is one of the list of allowed values returns | ||
true; else, emits an error message and returns false. | true; else, emits an error message and returns false. | ||
]] | ]] | ||
local function is_valid_parameter_value (value, name, possible | local function is_valid_parameter_value (value, name, possible) | ||
if not is_set (value) then | if not is_set (value) then | ||
return true; -- an empty parameter is ok | return true; -- an empty parameter is ok | ||
Line 1,862: | Line 1,882: | ||
]] | ]] | ||
local function format_volume_issue (volume, issue, cite_class, origin, sepc, lower | local function format_volume_issue (volume, issue, cite_class, origin, sepc, lower) | ||
if not is_set (volume) and not is_set (issue) then | if not is_set (volume) and not is_set (issue) then | ||
return ''; | return ''; | ||
end | end | ||
if 'magazine' == cite_class or (in_array (cite_class, {'citation', 'map'}) and 'magazine' == origin) then | if 'magazine' == cite_class or (in_array (cite_class, {'citation', 'map'}) and 'magazine' == origin) then | ||
if is_set (volume) and is_set (issue) then | if is_set (volume) and is_set (issue) then | ||
Line 1,902: | Line 1,911: | ||
return vol; | return vol; | ||
end | end | ||
Line 1,933: | Line 1,923: | ||
]] | ]] | ||
local function format_pages_sheets (page, pages, sheet, sheets, cite_class, origin, sepc, nopp, lower | local function format_pages_sheets (page, pages, sheet, sheets, cite_class, origin, sepc, nopp, lower) | ||
if 'map' == cite_class then -- only cite map supports sheet(s) as in-source locators | if 'map' == cite_class then -- only cite map supports sheet(s) as in-source locators | ||
if is_set (sheet) then | if is_set (sheet) then | ||
Line 1,952: | Line 1,942: | ||
local is_journal = 'journal' == cite_class or (in_array (cite_class, {'citation', 'map'}) and 'journal' == origin); | local is_journal = 'journal' == cite_class or (in_array (cite_class, {'citation', 'map'}) and 'journal' == origin); | ||
if is_set (page) then | if is_set (page) then | ||
if is_journal then | if is_journal then | ||
Line 2,096: | Line 2,082: | ||
-- define different field names for the same underlying things. | -- define different field names for the same underlying things. | ||
-- set default parameter values defined by |mode= parameter. | -- set default parameter values defined by |mode= parameter. | ||
local Mode = A['Mode']; | local Mode = A['Mode']; | ||
if not is_valid_parameter_value (Mode, 'mode', cfg.keywords['mode'] | if not is_valid_parameter_value (Mode, 'mode', cfg.keywords['mode']) then | ||
Mode = ''; | Mode = ''; | ||
end | end | ||
Line 2,148: | Line 2,134: | ||
local Translators; -- assembled translators name list | local Translators; -- assembled translators name list | ||
t = extract_names (args, 'TranslatorList'); -- fetch translator list from |translatorn= / |translator-lastn=, -firstn=, -linkn=, -maskn= | t = extract_names (args, 'TranslatorList'); -- fetch translator list from |translatorn= / |translator-lastn=, -firstn=, -linkn=, -maskn= | ||
local interviewers_list = {}; | local interviewers_list = {}; | ||
Line 2,236: | Line 2,221: | ||
local Pages; | local Pages; | ||
local At; | local At; | ||
if in_array (config.CitationClass, cfg.templates_using_volume) then | if in_array (config.CitationClass, cfg.templates_using_volume) then | ||
Volume = A['Volume']; | Volume = A['Volume']; | ||
Line 2,261: | Line 2,245: | ||
RegistrationRequired=nil; | RegistrationRequired=nil; | ||
end | end | ||
local SubscriptionRequired = A['SubscriptionRequired']; | local SubscriptionRequired = A['SubscriptionRequired']; | ||
if not is_valid_parameter_value (SubscriptionRequired, 'subscription', cfg.keywords ['yes_true_y']) then | if not is_valid_parameter_value (SubscriptionRequired, 'subscription', cfg.keywords ['yes_true_y']) then | ||
SubscriptionRequired=nil; | SubscriptionRequired=nil; | ||
end | end | ||
local UrlAccess = A['UrlAccess']; | local UrlAccess = A['UrlAccess']; | ||
if not is_valid_parameter_value (UrlAccess, 'url-access', cfg.keywords ['url-access']) then | if not is_valid_parameter_value (UrlAccess, 'url-access', cfg.keywords ['url-access']) then | ||
Line 2,283: | Line 2,269: | ||
end | end | ||
local ChapterUrlAccess = A['ChapterUrlAccess']; | |||
if not is_valid_parameter_value (ChapterUrlAccess, 'chapter-url-access', cfg.keywords ['url-access']) then -- same as url-access | |||
ChapterUrlAccess = nil; | |||
end | |||
if not is_set(ChapterURL) and is_set(ChapterUrlAccess) then | |||
ChapterUrlAccess = nil; | |||
table.insert( z.message_tail, { set_error( 'param_access_requires_param', {'chapter-url'}, true ) } ); | |||
end | |||
local Via = A['Via']; | local Via = A['Via']; | ||
Line 2,318: | Line 2,312: | ||
LastAuthorAmp = nil; -- set to empty string | LastAuthorAmp = nil; -- set to empty string | ||
end | end | ||
local no_tracking_cats = A['NoTracking']; | local no_tracking_cats = A['NoTracking']; | ||
if not is_valid_parameter_value (no_tracking_cats, 'no-tracking', cfg.keywords ['yes_true_y']) then | if not is_valid_parameter_value (no_tracking_cats, 'no-tracking', cfg.keywords ['yes_true_y']) then | ||
Line 2,326: | Line 2,318: | ||
end | end | ||
--local variables that are not cs1 parameters | --local variables that are not cs1 parameters | ||
local use_lowercase; -- controls capitalization of certain static text | local use_lowercase; -- controls capitalization of certain static text | ||
local this_page = mw.title.getCurrentTitle(); -- also used for COinS and for language | local this_page = mw.title.getCurrentTitle(); -- also used for COinS and for language | ||
Line 2,343: | Line 2,335: | ||
use_lowercase = ( sepc == ',' ); -- used to control capitalization for certain static text | use_lowercase = ( sepc == ',' ); -- used to control capitalization for certain static text | ||
--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 is_set (no_tracking_cats) then -- ignore if we are already not going to categorize this page | if not is_set (no_tracking_cats) then -- ignore if we are already not going to categorize this page | ||
if in_array (this_page.nsText, cfg.uncategorized_namespaces) then | if in_array (this_page.nsText, cfg.uncategorized_namespaces) then | ||
Line 2,356: | Line 2,348: | ||
end | end | ||
-- check for extra |page=, |pages= or |at= parameters. (also sheet and sheets while we're at it) | -- 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 | ||
Line 2,379: | Line 2,371: | ||
end | end | ||
-- both |publication-place= and |place= (|location=) allowed if different | -- both |publication-place= and |place= (|location=) allowed if different | ||
if not is_set(PublicationPlace) and is_set(Place) then | if not is_set(PublicationPlace) and is_set(Place) then | ||
PublicationPlace = Place; -- promote |place= (|location=) to |publication-place | PublicationPlace = Place; -- promote |place= (|location=) to |publication-place | ||
Line 2,386: | Line 2,378: | ||
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 | ||
--[[ | --[[ | ||
Parameter remapping for cite encyclopedia: | Parameter remapping for cite encyclopedia: | ||
When the citation has these parameters: | When the citation has these parameters: | ||
|encyclopedia and |title then map |title to |article and |encyclopedia to |title | |||
|encyclopedia and |article then map |encyclopedia to |title | |||
|encyclopedia then map |encyclopedia to |title | |||
|trans_title maps to |trans_chapter when |title is re-mapped | |||
|url maps to |chapterurl when |title is remapped | |||
All other combinations of |encyclopedia, |title, and |article are not modified | All other combinations of |encyclopedia, |title, and |article are not modified | ||
]] | ]] | ||
local Encyclopedia = A['Encyclopedia']; | local Encyclopedia = A['Encyclopedia']; | ||
Line 2,410: | Line 2,402: | ||
TransChapter = TransTitle; | TransChapter = TransTitle; | ||
ChapterURL = URL; | ChapterURL = URL; | ||
ChapterUrlAccess = UrlAccess; | |||
if not is_set (ChapterURL) and is_set (TitleLink) then | if not is_set (ChapterURL) and is_set (TitleLink) then | ||
Chapter= | Chapter = make_wikilink (TitleLink, Chapter); | ||
end | end | ||
Title = Periodical; | Title = Periodical; | ||
Line 2,429: | Line 2,423: | ||
end | end | ||
-- Special case for cite techreport. | -- Special case for cite techreport. | ||
if (config.CitationClass == "techreport") then -- special case for cite techreport | if (config.CitationClass == "techreport") then -- special case for cite techreport | ||
if is_set(A['Number']) then -- cite techreport uses 'number', which other citations alias to 'issue' | if is_set(A['Number']) then -- cite techreport uses 'number', which other citations alias to 'issue' | ||
Line 2,440: | Line 2,434: | ||
end | end | ||
-- special case for cite mailing list | -- special case for cite mailing list | ||
if (config.CitationClass == "mailinglist") then | if (config.CitationClass == "mailinglist") then | ||
Periodical = A ['MailingList']; | Periodical = A ['MailingList']; | ||
Line 2,447: | Line 2,441: | ||
end | end | ||
-- Account for the oddity that is {{cite conference}}, before generation of COinS data. | -- Account for the oddity that is {{cite conference}}, before generation of COinS data. | ||
if 'conference' == config.CitationClass then | if 'conference' == config.CitationClass then | ||
if is_set(BookTitle) then | if is_set(BookTitle) then | ||
Line 2,453: | Line 2,447: | ||
-- ChapterLink = TitleLink; -- |chapterlink= is deprecated | -- ChapterLink = TitleLink; -- |chapterlink= is deprecated | ||
ChapterURL = URL; | ChapterURL = URL; | ||
ChapterUrlAccess = UrlAccess; | |||
ChapterURLorigin = URLorigin; | ChapterURLorigin = URLorigin; | ||
URLorigin = ''; | URLorigin = ''; | ||
Line 2,467: | Line 2,462: | ||
end | end | ||
-- cite map oddities | -- cite map oddities | ||
local Cartography = ""; | local Cartography = ""; | ||
local Scale = ""; | local Scale = ""; | ||
Line 2,475: | Line 2,470: | ||
Chapter = A['Map']; | Chapter = A['Map']; | ||
ChapterURL = A['MapURL']; | ChapterURL = A['MapURL']; | ||
ChapterUrlAccess = UrlAccess; | |||
TransChapter = A['TransMap']; | TransChapter = A['TransMap']; | ||
ChapterURLorigin = A:ORIGIN('MapURL'); | ChapterURLorigin = A:ORIGIN('MapURL'); | ||
Line 2,489: | Line 2,485: | ||
end | end | ||
-- 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 AirDate = A['AirDate']; | local AirDate = A['AirDate']; | ||
Line 2,527: | Line 2,523: | ||
TransChapter = TransTitle; | TransChapter = TransTitle; | ||
ChapterURL = URL; | ChapterURL = URL; | ||
ChapterUrlAccess = UrlAccess; | |||
ChapterURLorigin = A:ORIGIN('URL'); | ChapterURLorigin = A:ORIGIN('URL'); | ||
Line 2,534: | Line 2,531: | ||
if is_set (ChapterLink) and not is_set (ChapterURL) then -- link but not URL | if is_set (ChapterLink) and not is_set (ChapterURL) then -- link but not URL | ||
Chapter = | Chapter = make_wikilink (ChapterLink, Chapter); | ||
elseif is_set (ChapterLink) and is_set (ChapterURL) then -- if both are set, URL links episode; | elseif is_set (ChapterLink) and is_set (ChapterURL) then -- if both are set, URL links episode; | ||
Series = | Series = make_wikilink (ChapterLink, Series); | ||
end | end | ||
URL = ''; -- unset | URL = ''; -- unset | ||
Line 2,546: | Line 2,543: | ||
Chapter = A['Episode']; -- TODO: make |episode= available to cite episode someday? | Chapter = A['Episode']; -- TODO: make |episode= available to cite episode someday? | ||
if is_set (Series) and is_set (SeriesLink) then | if is_set (Series) and is_set (SeriesLink) then | ||
Series = | Series = make_wikilink (SeriesLink, Series); | ||
end | end | ||
Series = wrap_style ('italic-title', Series); -- series is italicized | Series = wrap_style ('italic-title', Series); -- series is italicized | ||
end | end | ||
end | end | ||
-- end of {{cite episode}} stuff | -- end of {{cite episode}} stuff | ||
-- Account for the oddities that are {{cite arxiv}}, {{cite biorxiv}}, {{cite citeseerx}}, before generation of COinS data. | -- Account for the oddities that are {{cite arxiv}}, {{cite biorxiv}}, {{cite citeseerx}}, before generation of COinS data. | ||
do | do | ||
if in_array (config.CitationClass, {'arxiv', 'biorxiv', 'citeseerx'}) then | if in_array (config.CitationClass, {'arxiv', 'biorxiv', 'citeseerx'}) then | ||
Line 2,563: | Line 2,560: | ||
Periodical = 'arXiv'; -- set to arXiv for COinS; after that, must be set to empty string | Periodical = 'arXiv'; -- set to arXiv for COinS; after that, must be set to empty string | ||
end | end | ||
if 'biorxiv' == config.CitationClass then | if 'biorxiv' == config.CitationClass then | ||
Periodical = 'bioRxiv'; -- set to bioRxiv for COinS; after that, must be set to empty string | Periodical = 'bioRxiv'; -- set to bioRxiv for COinS; after that, must be set to empty string | ||
end | end | ||
if 'citeseerx' == config.CitationClass then | if 'citeseerx' == config.CitationClass then | ||
Periodical = 'CiteSeerX'; -- set to CiteSeerX for COinS; after that, must be set to empty string | Periodical = 'CiteSeerX'; -- set to CiteSeerX for COinS; after that, must be set to empty string | ||
Line 2,572: | Line 2,571: | ||
end | end | ||
-- handle type parameter for those CS1 citations that have default values | -- handle type parameter for those CS1 citations that have default values | ||
if in_array(config.CitationClass, {"AV-media-notes", "interview", "mailinglist", "map", "podcast", "pressrelease", "report", "techreport", "thesis"}) then | if 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); | ||
Line 2,585: | Line 2,584: | ||
end | end | ||
-- legacy: promote PublicationDate to Date if neither Date nor Year are set. | -- legacy: promote PublicationDate to Date if neither Date nor Year are set. | ||
if not is_set (Date) then | if not is_set (Date) then | ||
Date = Year; -- promote Year to Date | Date = Year; -- promote Year to Date | ||
Line 2,597: | Line 2,596: | ||
if PublicationDate == Date then PublicationDate = ''; end -- if PublicationDate is same as Date, don't display in rendered citation | if PublicationDate == Date then PublicationDate = ''; end -- if PublicationDate is same as Date, don't display in rendered citation | ||
--[[ | --[[ | ||
Go test all of the date-holding parameters for valid MOS:DATE format and make sure that dates are real dates. This must be done before we do COinS because here is where | Go test all of the date-holding parameters for valid MOS:DATE format and make sure that dates are real dates. This must be done before we do COinS because here is where | ||
we get the date used in the metadata. | we get the date used in the metadata. | ||
Date validation supporting code is in Module:Citation/CS1/Date_validation | Date validation supporting code is in Module:Citation/CS1/Date_validation | ||
]] | ]] | ||
do -- create defined block to contain local variables error_message, date_parameters_list, mismatch | do -- create defined block to contain local variables error_message, date_parameters_list, mismatch | ||
local error_message = ''; | local error_message = ''; | ||
Line 2,625: | Line 2,624: | ||
if not is_set(error_message) then -- error free dates only | if not is_set(error_message) then -- error free dates only | ||
local modified = false; -- flag | local modified = false; -- flag | ||
if is_set (DF) then -- if we need to reformat dates | if is_set (DF) then -- if we need to reformat dates | ||
modified = reformat_dates (date_parameters_list, DF, false); -- reformat to DF format, use long month names if appropriate | modified = reformat_dates (date_parameters_list, DF, false); -- reformat to DF format, use long month names if appropriate | ||
end | end | ||
if true == date_hyphen_to_dash (date_parameters_list) then | if true == date_hyphen_to_dash (date_parameters_list) then -- convert hyphens to dashes where appropriate | ||
modified = true; | modified = true; | ||
add_maint_cat ('date_format'); -- hyphens were converted so add maint category | add_maint_cat ('date_format'); -- hyphens were converted so add maint category | ||
end | end | ||
-- for those wikis that can and want to have English date names translated to the local language, | |||
-- uncomment these three lines. Not supported by en.wiki (for obvious reasons) | |||
-- if date_name_xlate (date_parameters_list) 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 | ||
AccessDate = date_parameters_list['access-date']; -- overwrite date holding parameters with modified values | AccessDate = date_parameters_list['access-date']; -- overwrite date holding parameters with modified values | ||
Line 2,647: | Line 2,653: | ||
end -- end of do | end -- end of do | ||
-- Account for the oddity that is {{cite journal}} with |pmc= set and |url= not set. Do this after date check but before COInS. | -- Account for the oddity that is {{cite journal}} with |pmc= set and |url= not set. Do this after date check but before COInS. | ||
-- Here we unset Embargo if PMC not embargoed (|embargo= not set in the citation) or if the embargo time has expired. Otherwise, holds embargo date | -- Here we unset Embargo if PMC not embargoed (|embargo= not set in the citation) or if the embargo time has expired. Otherwise, holds embargo date | ||
Embargo = is_embargoed (Embargo); | Embargo = is_embargoed (Embargo); | ||
if config.CitationClass == "journal" and not is_set(URL) and is_set(ID_list['PMC']) then | if config.CitationClass == "journal" and not is_set(URL) and is_set(ID_list['PMC']) then | ||
Line 2,663: | Line 2,669: | ||
end | end | ||
-- At this point fields may be nil if they weren't specified in the template use. We can use that fact. | -- At this point fields may be nil if they weren't specified in the template use. We can use that fact. | ||
-- Test if citation has no title | -- Test if citation has no title | ||
if not is_set(Title) and | if not is_set(Title) and | ||
Line 2,728: | Line 2,734: | ||
}, config.CitationClass); | }, config.CitationClass); | ||
-- Account for the oddities that are {{cite arxiv}}, AFTER generation of COinS data. | -- Account for the oddities that are {{cite arxiv}}, {{cite biorxiv}}, and {{cite citeseerx}} AFTER generation of COinS data. | ||
if in_array (config.CitationClass, {'arxiv', 'biorxiv', 'citeseerx'}) then -- we have set rft.jtitle in COinS to arXiv, bioRxiv, or CiteSeerX now unset so it isn't displayed | if in_array (config.CitationClass, {'arxiv', 'biorxiv', 'citeseerx'}) then -- we have set rft.jtitle in COinS to arXiv, bioRxiv, or CiteSeerX 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 then | if 'newsgroup' == config.CitationClass then | ||
if is_set (PublisherName) then | if is_set (PublisherName) then | ||
Line 2,809: | Line 2,814: | ||
end | end | ||
-- apply |[xx-]format= styling; at the end, these parameters hold correctly styled format annotation, | -- apply |[xx-]format= styling; at the end, these parameters hold correctly styled format annotation, | ||
-- an error message if the associated url is not set, or an empty string for concatenation | -- an error message if the associated url is not set, or an empty string for concatenation | ||
ArchiveFormat = style_format (ArchiveFormat, ArchiveURL, 'archive-format', 'archive-url'); | ArchiveFormat = style_format (ArchiveFormat, ArchiveURL, 'archive-format', 'archive-url'); | ||
ConferenceFormat = style_format (ConferenceFormat, ConferenceURL, 'conference-format', 'conference-url'); | ConferenceFormat = style_format (ConferenceFormat, ConferenceURL, 'conference-format', 'conference-url'); | ||
Line 2,817: | Line 2,822: | ||
TranscriptFormat = style_format (TranscriptFormat, TranscriptURL, 'transcript-format', 'transcripturl'); | TranscriptFormat = style_format (TranscriptFormat, TranscriptURL, 'transcript-format', 'transcripturl'); | ||
-- special case for chapter format so no error message or cat when chapter not supported | -- special case for chapter format so no error message or cat when chapter not supported | ||
if not (in_array(config.CitationClass, {'web', 'news', 'journal', 'magazine', 'pressrelease', 'podcast', 'newsgroup', 'arxiv', 'biorxiv', 'citeseerx'}) or | if not (in_array(config.CitationClass, {'web', 'news', 'journal', 'magazine', 'pressrelease', 'podcast', 'newsgroup', 'arxiv', 'biorxiv', 'citeseerx'}) or | ||
('citation' == config.CitationClass and is_set (Periodical) and not is_set (Encyclopedia))) then | ('citation' == config.CitationClass and is_set (Periodical) and not is_set (Encyclopedia))) then | ||
Line 2,892: | Line 2,897: | ||
end | end | ||
Chapter = format_chapter_title (ScriptChapter, Chapter, TransChapter, ChapterURL, ChapterURLorigin, no_quotes); -- Contribution is also in Chapter | Chapter = format_chapter_title (ScriptChapter, Chapter, TransChapter, ChapterURL, ChapterURLorigin, no_quotes, ChapterUrlAccess); -- Contribution is also in Chapter | ||
if is_set (Chapter) then | if is_set (Chapter) then | ||
Chapter = Chapter .. ChapterFormat ; | Chapter = Chapter .. ChapterFormat ; | ||
Line 2,905: | Line 2,910: | ||
-- Format main title. | -- Format main title. | ||
Title = mw.ustring.gsub(Title, '%'..sepc..'$', ''); -- remove any trailing separator character | |||
if is_set(TitleLink) and is_set(Title) then | if is_set(TitleLink) and is_set(Title) then | ||
Title = | Title = make_wikilink (TitleLink, Title); | ||
end | end | ||
Line 2,938: | Line 2,944: | ||
Title = external_link( URL, Title, URLorigin, UrlAccess ) .. TransTitle .. TransError .. Format; | Title = external_link( URL, Title, URLorigin, UrlAccess ) .. TransTitle .. TransError .. Format; | ||
URL = ''; -- unset these because no longer needed | URL = ''; -- unset these because no longer needed | ||
Format = ""; | Format = ""; | ||
Line 2,955: | Line 2,949: | ||
Title = Title .. TransTitle .. TransError; | Title = Title .. TransTitle .. TransError; | ||
end | end | ||
else | |||
Title = TransTitle .. TransError; | |||
end | end | ||
Line 2,996: | Line 2,992: | ||
end | end | ||
Page, Pages, Sheet, Sheets = format_pages_sheets (Page, Pages, Sheet, Sheets, config.CitationClass, Periodical_origin, sepc, NoPP, use_lowercase | Page, Pages, Sheet, Sheets = format_pages_sheets (Page, Pages, Sheet, Sheets, config.CitationClass, Periodical_origin, sepc, NoPP, use_lowercase); | ||
At = is_set(At) and (sepc .. " " .. At) or ""; | At = is_set(At) and (sepc .. " " .. At) or ""; | ||
Line 3,029: | Line 3,025: | ||
if is_set (Translators) then | if is_set (Translators) then | ||
Others = sepc .. ' ' .. wrap_msg ('translated', Translators, use_lowercase) .. Others; | |||
end | end | ||
if is_set (Interviewers) then | if is_set (Interviewers) then | ||
Line 3,044: | Line 3,036: | ||
add_maint_cat ('extra_text', 'edition'); | add_maint_cat ('extra_text', 'edition'); | ||
end | end | ||
Edition = " " .. wrap_msg ('edition', Edition); | |||
else | else | ||
Edition = ''; | Edition = ''; | ||
Line 3,054: | Line 3,042: | ||
Series = is_set(Series) and (sepc .. " " .. Series) or ""; | Series = is_set(Series) and (sepc .. " " .. Series) or ""; | ||
OrigYear = is_set(OrigYear) and (" [" .. OrigYear .. "]") or ""; -- TODO: presentation | |||
OrigYear = is_set(OrigYear) and (" [" .. OrigYear .. "]") or ""; | |||
Agency = is_set(Agency) and (sepc .. " " .. Agency) or ""; | Agency = is_set(Agency) and (sepc .. " " .. Agency) or ""; | ||
Volume = format_volume_issue (Volume, Issue, config.CitationClass, Periodical_origin, sepc, use_lowercase | Volume = format_volume_issue (Volume, Issue, config.CitationClass, Periodical_origin, sepc, use_lowercase); | ||
------------------------------------ totally unrelated data | ------------------------------------ totally unrelated data | ||
Line 3,068: | Line 3,053: | ||
end | end | ||
--[[ | --[[ | ||
Subscription implies paywall; Registration does not. If both are used in a citation, the subscription required link | Subscription implies paywall; Registration does not. If both are used in a citation, the subscription required link | ||
note is displayed. There are no error messages for this condition. | note is displayed. There are no error messages for this condition. | ||
]] | ]] | ||
if is_set (SubscriptionRequired) then | if is_set (SubscriptionRequired) then | ||
SubscriptionRequired = sepc .. " " .. cfg.messages['subscription']; -- subscription required message | SubscriptionRequired = sepc .. " " .. cfg.messages['subscription']; -- subscription required message | ||
Line 3,085: | Line 3,070: | ||
AccessDate = nowrap_date (AccessDate); -- wrap in nowrap span if date in appropriate format | AccessDate = nowrap_date (AccessDate); -- wrap in nowrap span if date in appropriate format | ||
if (sepc ~= ".") then retrv_text = retrv_text:lower() end -- if mode is cs2, lower case | |||
AccessDate = substitute (retrv_text, AccessDate); -- add retrieved text | |||
AccessDate = substitute (cfg.presentation['accessdate'], {sepc, AccessDate}); -- allow editors to hide accessdates | AccessDate = substitute (cfg.presentation['accessdate'], {sepc, AccessDate}); -- allow editors to hide accessdates | ||
end | end | ||
Line 3,206: | Line 3,188: | ||
end | end | ||
--[[ | --[[ | ||
Handle the oddity that is cite speech. This code overrides whatever may be the value assigned to TitleNote (through |department=) and forces it to be " (Speech)" so that | Handle the oddity that is cite speech. This code overrides whatever may be the value assigned to TitleNote (through |department=) and forces it to be " (Speech)" so that | ||
the annotation directly follows the |title= parameter value in the citation rather than the |event= parameter value (if provided). | the annotation directly follows the |title= parameter value in the citation rather than the |event= parameter value (if provided). | ||
]] | ]] | ||
if "speech" == config.CitationClass then -- cite speech only | if "speech" == config.CitationClass then -- cite speech only | ||
TitleNote = " (Speech)"; -- annotate the citation | TitleNote = " (Speech)"; -- annotate the citation | ||
Line 3,228: | Line 3,210: | ||
if in_array(config.CitationClass, {"journal","citation"}) and is_set(Periodical) then | if in_array(config.CitationClass, {"journal","citation"}) and is_set(Periodical) then | ||
if is_set(Others) then Others = Others .. sepc .. " " end | if is_set(Others) then Others = Others .. sepc .. " " end | ||
tcommon = safe_join( {Others, Title, TitleNote, Conference, Periodical, Format, TitleType, Series, Language, Edition, Publisher, Agency, Volume}, sepc ); | |||
elseif in_array(config.CitationClass, {"book","citation"}) and not is_set(Periodical) then -- special cases for book cites | elseif in_array(config.CitationClass, {"book","citation"}) and not is_set(Periodical) then -- special cases for book cites | ||
if is_set (Contributors) then -- when we are citing foreword, preface, introduction, etc | if is_set (Contributors) then -- when we are citing foreword, preface, introduction, etc | ||
tcommon = safe_join( {Title, TitleNote}, sepc ); -- author and other stuff will come after this and before tcommon2 | tcommon = safe_join( {Title, TitleNote}, sepc ); -- author and other stuff will come after this and before tcommon2 | ||
tcommon2 = safe_join( {Conference, Periodical, Format, TitleType, Series, Language, Volume, Others, Edition, Publisher, Agency}, sepc ); | |||
else | else | ||
tcommon = safe_join( {Title, TitleNote, Conference, Periodical, Format, TitleType, Series, Language, Volume, Others, Edition, Publisher, Agency}, sepc ); | tcommon = safe_join( {Title, TitleNote, Conference, Periodical, Format, TitleType, Series, Language, Volume, Others, Edition, Publisher, Agency}, sepc ); | ||
Line 3,259: | Line 3,230: | ||
elseif 'episode' == config.CitationClass then -- special case for cite episode | elseif 'episode' == config.CitationClass then -- special case for cite episode | ||
tcommon = safe_join( {Title, TitleNote, TitleType, Series, Transcript, Language, Edition, Publisher}, sepc ); | tcommon = safe_join( {Title, TitleNote, TitleType, Series, Transcript, Language, Edition, Publisher}, sepc ); | ||
else -- all other CS1 templates | else -- all other CS1 templates | ||
Line 3,283: | Line 3,247: | ||
if is_set(Date) then | if is_set(Date) then | ||
if | if is_set (Authors) or is_set (Editors) then -- date follows authors or editors when authors not set | ||
Date = " (" .. Date ..")" .. OrigYear .. sepc .. " "; -- in paranetheses | Date = " (" .. Date ..")" .. OrigYear .. sepc .. " "; -- in paranetheses | ||
else -- neither of authors and editors set | else -- neither of authors and editors set | ||
Line 3,300: | Line 3,258: | ||
end | end | ||
if is_set(Authors) then | if is_set(Authors) then | ||
if (not is_set (Date) | if (not is_set (Date)) then -- when date is set it's in parentheses; no Authors termination | ||
Authors = terminate_name_list (Authors, sepc); -- when no date, terminate with 0 or 1 sepc and a space | Authors = terminate_name_list (Authors, sepc); -- when no date, terminate with 0 or 1 sepc and a space | ||
end | end | ||
Line 3,306: | Line 3,264: | ||
local in_text = " "; | local in_text = " "; | ||
local post_text = ""; | local post_text = ""; | ||
if is_set(Chapter) and 0 == #c | if is_set(Chapter) and 0 == #c then | ||
in_text = in_text .. cfg.messages['in'] .. " " | in_text = in_text .. cfg.messages['in'] .. " " | ||
if (sepc ~= '.') then in_text = in_text:lower() | if (sepc ~= '.') then | ||
in_text = in_text:lower() -- lowercase for cs2 | |||
end | |||
else | else | ||
if EditorCount <= 1 then | if EditorCount <= 1 then | ||
Line 3,328: | Line 3,282: | ||
if (sepc ~= '.') then by_text = by_text:lower() end -- lowercase for cs2 | if (sepc ~= '.') then by_text = by_text:lower() end -- lowercase for cs2 | ||
Authors = by_text .. Authors; -- author follows title so tweak it here | Authors = by_text .. Authors; -- author follows title so tweak it here | ||
if is_set (Editors) and is_set (Date | if is_set (Editors) and is_set (Date) then -- when Editors make sure that Authors gets terminated | ||
Authors = terminate_name_list (Authors, sepc); -- terminate with 0 or 1 sepc and a space | Authors = terminate_name_list (Authors, sepc); -- terminate with 0 or 1 sepc and a space | ||
end | end | ||
if (not is_set (Date) | if (not is_set (Date)) then -- when date is set it's in parentheses; no Contributors termination | ||
Contributors = terminate_name_list (Contributors, sepc); -- terminate with 0 or 1 sepc and a space | Contributors = terminate_name_list (Contributors, sepc); -- terminate with 0 or 1 sepc and a space | ||
end | end | ||
text = safe_join( {Contributors, Date, Chapter, tcommon, Authors, Place, Editors, tcommon2, pgtext, idcommon }, sepc ); | |||
else | else | ||
text = safe_join( {Authors, Date, Chapter, Place, Editors, tcommon, pgtext, idcommon }, sepc ); | text = safe_join( {Authors, Date, Chapter, Place, Editors, tcommon, pgtext, idcommon }, sepc ); | ||
Line 3,359: | Line 3,306: | ||
end | end | ||
end | end | ||
text = safe_join( {Editors, Date, Chapter, Place, tcommon, pgtext, idcommon}, sepc ); | |||
else | else | ||
if in_array(config.CitationClass, {"journal","citation"}) and is_set(Periodical) then | if in_array(config.CitationClass, {"journal","citation"}) and is_set(Periodical) then | ||
Line 3,427: | Line 3,360: | ||
end | end | ||
local render = {}; -- here we collect the final bits for concatenation into the rendered citation | |||
if is_set(options.id) then -- here we wrap the rendered citation in <cite ...>...</cite> tags | if is_set(options.id) then -- here we wrap the rendered citation in <cite ...>...</cite> tags | ||
table.insert (render, substitute (cfg.presentation['cite-id'], {mw.uri.anchorEncode(options.id), mw.text.nowiki(options.class), text})); -- when |ref= is set | |||
else | else | ||
table.insert (render, substitute (cfg.presentation['cite'], {mw.text.nowiki(options.class), text})); -- all other cases | |||
end | end | ||
table.insert (render, substitute (cfg.presentation['ocins'], {OCinSoutput})); -- append metadata to the citation | |||
if #z.message_tail ~= 0 then | if #z.message_tail ~= 0 then | ||
table.insert (render, ' '); | |||
for i,v in ipairs( z.message_tail ) do | for i,v in ipairs( z.message_tail ) do | ||
if is_set(v[1]) then | if is_set(v[1]) then | ||
if i == #z.message_tail then | if i == #z.message_tail then | ||
table.insert (render, error_comment( v[1], v[2] )); | |||
else | else | ||
table.insert (render, error_comment( v[1] .. "; ", v[2] )); | |||
end | end | ||
end | end | ||
Line 3,449: | Line 3,384: | ||
if #z.maintenance_cats ~= 0 then | if #z.maintenance_cats ~= 0 then | ||
table.insert (render, '<span class="citation-comment" style="display:none; color:#33aa33; margin-left:0.3em">'); | |||
for _, v in ipairs( z.maintenance_cats ) do -- append maintenance categories | for _, v in ipairs( z.maintenance_cats ) do -- append maintenance categories | ||
table.insert (render, v); | |||
table.insert (render, ' ('); | |||
table.insert (render, make_wikilink (':Category:' .. v, 'link')); | |||
table.insert (render, ') '); | |||
end | end | ||
table.insert (render, '</span>'); | |||
end | end | ||
Line 3,459: | Line 3,397: | ||
if in_array(no_tracking_cats, {"", "no", "false", "n"}) then | if in_array(no_tracking_cats, {"", "no", "false", "n"}) then | ||
for _, v in ipairs( z.error_categories ) do | for _, v in ipairs( z.error_categories ) do | ||
table.insert (render, make_wikilink ('Category:' .. v)); | |||
end | end | ||
for _, v in ipairs( z.maintenance_cats ) do -- append maintenance categories | for _, v in ipairs( z.maintenance_cats ) do -- append maintenance categories | ||
table.insert (render, make_wikilink ('Category:' .. v)); | |||
end | end | ||
for _, v in ipairs( z.properties_cats ) do -- append | for _, v in ipairs( z.properties_cats ) do -- append properties categories | ||
table.insert (render, make_wikilink ('Category:' .. v)); | |||
end | end | ||
end | end | ||
return | return table.concat (render); | ||
end | end | ||
Line 3,503: | Line 3,441: | ||
utilities.set_selected_modules (cfg); -- so that functions in Utilities can see the cfg tables | utilities.set_selected_modules (cfg); -- so that functions in Utilities can see the cfg tables | ||
identifiers.set_selected_modules (cfg, utilities); -- so that functions in Identifiers can see the selected cfg tables and selected Utilities module | 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 (utilities); | 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 | metadata.set_selected_modules (cfg, utilities); -- so that functions in COinS can see the selected cfg tables and selected Utilities module | ||
Line 3,510: | Line 3,448: | ||
reformat_dates = validation.reformat_dates; | reformat_dates = validation.reformat_dates; | ||
date_hyphen_to_dash = validation.date_hyphen_to_dash; | date_hyphen_to_dash = validation.date_hyphen_to_dash; | ||
date_name_xlate = validation.date_name_xlate; | |||
is_set = utilities.is_set; -- imported functions from Module:Citation/CS1/Utilities | is_set = utilities.is_set; -- imported functions from Module:Citation/CS1/Utilities | ||
in_array = utilities.in_array; | in_array = utilities.in_array; | ||
Line 3,520: | Line 3,459: | ||
wrap_style = utilities.wrap_style; | wrap_style = utilities.wrap_style; | ||
safe_for_italics = utilities.safe_for_italics; | safe_for_italics = utilities.safe_for_italics; | ||
is_wikilink = utilities.is_wikilink; | |||
make_wikilink = utilities.make_wikilink; | |||
z = utilities.z; -- table of error and category tables in Module:Citation/CS1/Utilities | z = utilities.z; -- table of error and category tables in Module:Citation/CS1/Utilities |