Module:Citation/CS1: Difference between revisions
Jump to navigation
Jump to search
Content deleted Content added
m 1 revision imported |
hyphen_to_dash() fix; |
||
Line 3: | Line 3: | ||
--[[--------------------------< F O R W A R D D E C L A R A T I O N S >-------------------------------------- |
--[[--------------------------< F O R W A R D D E C L A R A T I O N S >-------------------------------------- |
||
each of these counts against the Lua upvalue limit |
each of these counts against the Lua upvalue limit |
||
]] |
]] |
||
Line 18: | Line 16: | ||
local whitelist = {}; -- table of tables listing valid template parameter names; defined in Module:Citation/CS1/Whitelist |
local whitelist = {}; -- table of tables listing valid template parameter names; defined in Module:Citation/CS1/Whitelist |
||
--[[------------------< P A G E S C O P E V A R I A B L E S >--------------- |
|||
declare variables here that have page-wide scope that are not brought in from |
|||
--[[--------------------------< P A G E S C O P E V A R I A B L E S >-------------------------------------- |
|||
other modules; that are created here and used here |
|||
declare variables here that have page-wide scope that are not brought in from other modules; that are created here and used here |
|||
]] |
]] |
||
local added_deprecated_cat; -- Boolean flag so that the category is added only once |
local added_deprecated_cat; -- Boolean flag so that the category is added only once |
||
local added_discouraged_cat; -- Boolean flag so that the category is added only once |
|||
local added_vanc_errs; -- Boolean flag so we only emit one Vancouver error / category |
local added_vanc_errs; -- Boolean flag so we only emit one Vancouver error / category |
||
local Frame; -- holds the module's frame table |
local Frame; -- holds the module's frame table |
||
--[[--------------------------< F I R S T _ S E T >------------------------------------------------------------ |
--[[--------------------------< F I R S T _ S E T >------------------------------------------------------------ |
||
Line 62: | Line 56: | ||
]] |
]] |
||
local function add_vanc_error (source) |
local function add_vanc_error (source, position) |
||
if |
if added_vanc_errs then return end |
||
added_vanc_errs = true; -- note that we've added this category |
|||
added_vanc_errs = true; -- note that we've added this category |
|||
table.insert( z.message_tail, { utilities.set_message ( 'err_vancouver', {source}, true ) } ); |
|||
table.insert( z.message_tail, { utilities.set_message ( 'err_vancouver', {source, position}, true ) } ); |
|||
end |
|||
end |
end |
||
Line 415: | Line 409: | ||
domain, path = URL:match ('^([/%.%-%+:%a%d]+)([/%?#].*)$'); -- split the URL into scheme plus domain and path |
domain, path = URL:match ('^([/%.%-%+:%a%d]+)([/%?#].*)$'); -- split the URL into scheme plus domain and path |
||
if path then -- if there is a path portion |
if path then -- if there is a path portion |
||
path = path:gsub ('[%[%]]', {['['] = '%5b', [']'] = '%5d'}); |
path = path:gsub ('[%[%]]', {['['] = '%5b', [']'] = '%5d'}); -- replace '[' and ']' with their percent-encoded values |
||
URL = table.concat ({domain, path}); -- and reassemble |
URL = table.concat ({domain, path}); -- and reassemble |
||
end |
end |
||
Line 443: | Line 437: | ||
added_deprecated_cat = true; -- note that we've added this category |
added_deprecated_cat = true; -- note that we've added this category |
||
table.insert( z.message_tail, { utilities.set_message ( 'err_deprecated_params', {name}, true ) } ); -- add error message |
table.insert( z.message_tail, { utilities.set_message ( 'err_deprecated_params', {name}, true ) } ); -- add error message |
||
end |
|||
end |
|||
--[[--------------------------< D I S C O U R A G E D _ P A R A M E T E R >------------------------------------ |
|||
Categorize and emit an maintenance message when the citation contains one or more discouraged parameters. Only |
|||
one error message is emitted regardless of the number of discouraged parameters in the citation. |
|||
added_discouraged_cat is a Boolean declared in page scope variables above |
|||
]] |
|||
local function discouraged_parameter(name) |
|||
if not added_discouraged_cat then |
|||
added_discouraged_cat = true; -- note that we've added this category |
|||
table.insert( z.message_tail, { utilities.set_message ( 'maint_discouraged', {name}, true ) } ); -- add maint message |
|||
end |
end |
||
end |
end |
||
Line 539: | Line 550: | ||
-- if we get this far we have prefix and script |
-- if we get this far we have prefix and script |
||
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 utilities.is_set (name) then |
if utilities.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 755: | Line 766: | ||
local function has_invisible_chars (param, v) |
local function has_invisible_chars (param, v) |
||
local position = ''; -- position of invisible char or starting position of stripmarker |
local position = ''; -- position of invisible char or starting position of stripmarker |
||
local dummy; -- end of matching string; not used but required to hold end position when a capture is returned |
|||
local capture; -- used by stripmarker detection to hold name of the stripmarker |
local capture; -- used by stripmarker detection to hold name of the stripmarker |
||
local stripmarker; -- boolean set true when a stripmarker is found |
|||
local i = 1; |
|||
local stripmarker, apostrophe; |
|||
capture = string.match (v, '[%w%p ]*'); -- test for values that are simple ASCII text and bypass other tests if true |
capture = string.match (v, '[%w%p ]*'); -- test for values that are simple ASCII text and bypass other tests if true |
||
if capture == v then -- if same there are no Unicode characters |
if capture == v then -- if same there are no Unicode characters |
||
Line 765: | Line 774: | ||
end |
end |
||
for _, invisible_char in ipairs (cfg.invisible_chars) do |
|||
local |
local char_name = invisible_char[1]; -- the character or group name |
||
local pattern = |
local pattern = invisible_char[2]; -- the pattern used to find it |
||
position, |
position, _, capture = mw.ustring.find (v, pattern); -- see if the parameter value contains characters that match the pattern |
||
if position and ( |
if position and (cfg.invisible_defs.zwj == capture) then -- if we found a zero-width joiner character |
||
if mw.ustring.find (v, cfg.indic_script) then -- it's ok if one of the Indic scripts |
if mw.ustring.find (v, cfg.indic_script) then -- it's ok if one of the Indic scripts |
||
position = nil; -- unset position |
|||
elseif cfg.emoji[mw.ustring.codepoint (v, position+1)] then -- is zwj followed by a character listed in emoji{}? |
|||
position = nil; -- unset position |
position = nil; -- unset position |
||
end |
end |
||
Line 780: | Line 791: | ||
('templatestyles' == capture and utilities.in_array (param, {'id', 'quote'})) then -- templatestyles stripmarker allowed in these parameters |
('templatestyles' == capture and utilities.in_array (param, {'id', 'quote'})) then -- templatestyles stripmarker allowed in these parameters |
||
stripmarker = true; -- set a flag |
stripmarker = true; -- set a flag |
||
elseif true == stripmarker and |
elseif true == stripmarker and cfg.invisible_defs.del == capture then -- because stripmakers begin and end with the delete char, assume that we've found one end of a stripmarker |
||
position = nil; -- unset |
position = nil; -- unset |
||
else |
else |
||
local err_msg; |
local err_msg; |
||
if capture and not (cfg.invisible_defs.del == capture or cfg.invisible_defs.zwj == capture) then |
|||
if capture then |
|||
err_msg = capture .. ' ' .. |
err_msg = capture .. ' ' .. char_name; |
||
else |
else |
||
err_msg = |
err_msg = char_name .. ' ' .. 'character'; |
||
end |
end |
||
table.insert |
table.insert (z.message_tail, {utilities.set_message ('err_invisible_char', {err_msg, utilities.wrap_style ('parameter', param), position}, true)}); -- add error message |
||
return; -- and done with this parameter |
return; -- and done with this parameter |
||
end |
end |
||
end |
end |
||
i = i + 1; -- bump our index |
|||
end |
end |
||
end |
end |
||
Line 812: | Line 822: | ||
return setmetatable({ |
return setmetatable({ |
||
ORIGIN = function ( self, k ) |
ORIGIN = function ( self, k ) |
||
local dummy = self[k]; |
local dummy = self[k]; -- force the variable to be loaded. |
||
return origin[k]; |
return origin[k]; |
||
end |
end |
||
Line 827: | Line 837: | ||
v, origin[k] = utilities.select_one ( args, list, 'err_redundant_parameters' ); |
v, origin[k] = utilities.select_one ( args, list, 'err_redundant_parameters' ); |
||
if origin[k] == nil then |
if origin[k] == nil then |
||
origin[k] = ''; |
origin[k] = ''; -- Empty string, not nil |
||
end |
end |
||
elseif list ~= nil then |
elseif list ~= nil then |
||
Line 924: | Line 934: | ||
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 triple-hyphen with emdash |
|||
str = str:gsub ('[^%-]%-%-[^%-]', '–'); -- replace double-hyphen (as found in BibTeX entries) with endash |
|||
str = str:gsub (' ', ' '); -- replace entity with generic keyboard space character |
str = str:gsub (' ', ' '); -- replace entity with generic keyboard space character |
||
Line 933: | Line 941: | ||
for _, item in ipairs (list) do -- for each item in the list |
for _, item in ipairs (list) do -- for each item in the list |
||
item, accept = utilities.has_accept_as_written (item); |
item, accept = utilities.has_accept_as_written (item); -- remove accept-this-as-written markup when it wraps all of item |
||
if not accept and mw.ustring.match (item, '^%w*[%.%-]?%w+%s*[%-–—]%s*%w*[%.%-]?%w+$') then -- if a hyphenated range or has endash or emdash separators |
if not accept and mw.ustring.match (item, '^%w*[%.%-]?%w+%s*[%-–—]%s*%w*[%.%-]?%w+$') then -- if a hyphenated range or has endash or emdash separators |
||
if item:match ('^%a+[%.%-]?%d+%s*%-%s*%a+[%.%-]?%d+$') or -- letterdigit hyphen letterdigit (optional separator between letter and digit) |
if item:match ('^%a+[%.%-]?%d+%s*%-%s*%a+[%.%-]?%d+$') or -- letterdigit hyphen letterdigit (optional separator between letter and digit) |
||
Line 948: | Line 956: | ||
end |
end |
||
local temp_str = ''; -- concatenate the output table into a comma separated string |
|||
temp_str, accept = utilities.has_accept_as_written (table.concat (out, ', ')); -- remove accept-this-as-written markup when it wraps all of concatenated out |
temp_str, accept = utilities.has_accept_as_written (table.concat (out, ', ')); -- remove accept-this-as-written markup when it wraps all of concatenated out |
||
if accept then |
if accept then |
||
temp_str = utilities.has_accept_as_written (str); -- when global markup removed, return original str; do it this way to suppress boolean second return value |
|||
return temp_str; |
|||
else |
else |
||
return temp_str; |
return temp_str; -- else, return assembled temp_str |
||
end |
end |
||
end |
end |
||
--[[--------------------------< S A F E _ J O I N >----------------------------- |
--[[--------------------------< S A F E _ J O I N >----------------------------- |
||
Line 996: | Line 1,006: | ||
trim = false; |
trim = false; |
||
end_chr = f.sub(str, -1, -1); -- get the last character of the output string |
end_chr = f.sub(str, -1, -1); -- get the last character of the output string |
||
-- str = str .. "<HERE(enchr=" .. end_chr .. ")" |
-- str = str .. "<HERE(enchr=" .. end_chr .. ")" -- debug stuff? |
||
if end_chr == duplicate_char then -- if same as separator |
if end_chr == duplicate_char then -- if same as separator |
||
str = f.sub(str, 1, -2); |
str = f.sub(str, 1, -2); -- remove it |
||
elseif end_chr == "'" then -- if it might be wiki-markup |
elseif end_chr == "'" then -- if it might be wiki-markup |
||
if f.sub(str, -3, -1) == duplicate_char .. "''" then |
if f.sub(str, -3, -1) == duplicate_char .. "''" then -- if last three chars of str are sepc'' |
||
str = f.sub(str, 1, -4) .. "''"; -- remove them and add back '' |
str = f.sub(str, 1, -4) .. "''"; -- remove them and add back '' |
||
elseif f.sub(str, -5, -1) == duplicate_char .. "]]''" then -- if last five chars of str are sepc]]'' |
elseif f.sub(str, -5, -1) == duplicate_char .. "]]''" then -- if last five chars of str are sepc]]'' |
||
Line 1,008: | Line 1,018: | ||
end |
end |
||
elseif end_chr == "]" then -- if it might be wiki-markup |
elseif end_chr == "]" then -- if it might be wiki-markup |
||
if f.sub(str, -3, -1) == duplicate_char .. "]]" then |
if f.sub(str, -3, -1) == duplicate_char .. "]]" then -- if last three chars of str are sepc]] wikilink |
||
trim = true; |
trim = true; |
||
elseif f.sub(str, -3, -1) == duplicate_char .. '"]' then |
elseif f.sub(str, -3, -1) == duplicate_char .. '"]' then -- if last three chars of str are sepc"] quoted external link |
||
trim = true; |
trim = true; |
||
elseif f.sub(str, -2, -1) == duplicate_char .. "]" then |
elseif f.sub(str, -2, -1) == duplicate_char .. "]" then -- if last two chars of str are sepc] external link |
||
trim = true; |
trim = true; |
||
elseif f.sub(str, -4, -1) == duplicate_char .. "'']" then -- normal case when |url=something & |title=Title. |
elseif f.sub(str, -4, -1) == duplicate_char .. "'']" then -- normal case when |url=something & |title=Title. |
||
Line 1,019: | Line 1,029: | ||
elseif end_chr == " " then -- if last char of output string is a space |
elseif end_chr == " " then -- if last char of output string is a space |
||
if f.sub(str, -2, -1) == duplicate_char .. " " then -- if last two chars of str are <sepc><space> |
if f.sub(str, -2, -1) == duplicate_char .. " " then -- if last two chars of str are <sepc><space> |
||
str = f.sub(str, 1, -3); |
str = f.sub(str, 1, -3); -- remove them both |
||
end |
end |
||
end |
end |
||
Line 1,034: | Line 1,044: | ||
end |
end |
||
end |
end |
||
str = str .. value; |
str = str .. value; -- add it to the output string |
||
end |
end |
||
end |
end |
||
Line 1,059: | Line 1,069: | ||
For Vancouver style, author/editor names are supposed to be rendered in Latin |
For Vancouver style, author/editor names are supposed to be rendered in Latin |
||
(read ASCII) characters. When a name uses characters that contain diacritical |
(read ASCII) characters. When a name uses characters that contain diacritical |
||
those characters are to converted to the corresponding Latin |
marks, those characters are to be converted to the corresponding Latin |
||
is written using a non-Latin alphabet or logogram, that |
character. When a name is written using a non-Latin alphabet or logogram, that |
||
into Latin characters. The module doesn't do this |
name is to be transliterated into Latin characters. The module doesn't do this |
||
so editors may/must. |
|||
This test allows |first= and |last= names to contain any of the letters defined |
This test allows |first= and |last= names to contain any of the letters defined |
||
Line 1,091: | Line 1,102: | ||
]] |
]] |
||
local function is_good_vanc_name (last, first, suffix) |
local function is_good_vanc_name (last, first, suffix, position) |
||
if not suffix then |
if not suffix then |
||
if first:find ('[,%s]') then -- when there is a space or comma, might be first name/initials + generational suffix |
if first:find ('[,%s]') then -- when there is a space or comma, might be first name/initials + generational suffix |
||
Line 1,100: | Line 1,111: | ||
if utilities.is_set (suffix) then |
if utilities.is_set (suffix) then |
||
if not is_suffix (suffix) then |
if not is_suffix (suffix) then |
||
add_vanc_error (cfg.err_msg_supl.suffix); |
add_vanc_error (cfg.err_msg_supl.suffix, position); |
||
return false; -- not a name with an appropriate suffix |
return false; -- not a name with an appropriate suffix |
||
end |
end |
||
Line 1,106: | Line 1,117: | ||
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 (cfg.err_msg_supl['non-Latin char']); |
add_vanc_error (cfg.err_msg_supl['non-Latin char'], position); |
||
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,130: | Line 1,141: | ||
]] |
]] |
||
local function reduce_to_initials(first) |
local function reduce_to_initials(first, position) |
||
local name, suffix = mw.ustring.match(first, "^(%u+) ([%dJS][%drndth]+)$"); |
local name, suffix = mw.ustring.match(first, "^(%u+) ([%dJS][%drndth]+)$"); |
||
Line 1,143: | Line 1,154: | ||
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 (cfg.err_msg_supl.suffix); |
add_vanc_error (cfg.err_msg_supl.suffix, position); -- 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,166: | Line 1,177: | ||
end |
end |
||
if 3 > i then |
if 3 > i then |
||
table.insert (initials, mw.ustring.sub(names[i], 1, 1)); |
table.insert (initials, mw.ustring.sub(names[i], 1, 1)); -- insert the initial at end of initials table |
||
end |
end |
||
i = i + 1; -- bump the counter |
i = i + 1; -- bump the counter |
||
Line 1,232: | Line 1,243: | ||
if ("vanc" == format) then -- if Vancouver format |
if ("vanc" == format) then -- if Vancouver format |
||
one = one:gsub ('%.', ''); -- remove periods from surnames (http://www.ncbi.nlm.nih.gov/books/NBK7271/box/A35029/) |
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 |
if not person.corporate and is_good_vanc_name (one, first, nil, i) then -- and name is all Latin characters; corporate authors not tested |
||
first = reduce_to_initials (first); |
first = reduce_to_initials (first, i); -- attempt to convert first name(s) to initials |
||
end |
end |
||
end |
end |
||
Line 1,273: | Line 1,284: | ||
end |
end |
||
--[[--------------------< M A K E _ C I T E R E F _ I D >----------------------- |
|||
--[[--------------------------< A N C H O R _ I D >----------------------------- |
|||
Generates a CITEREF anchor ID if we have at least one name or a date. Otherwise |
Generates a CITEREF anchor ID if we have at least one name or a date. Otherwise |
||
Line 1,284: | Line 1,294: | ||
]] |
]] |
||
local function |
local function make_citeref_id (namelist, year) |
||
local names={}; |
local names={}; -- a table for the one to four names and year |
||
for i,v in ipairs (namelist) do |
for i,v in ipairs (namelist) do -- loop through the list and take up to the first four last names |
||
names[i] = v.last |
names[i] = v.last |
||
if i == 4 then break end |
if i == 4 then break end -- if four then done |
||
end |
end |
||
table.insert (names, year); |
table.insert (names, year); -- add the year at the end |
||
local id = table.concat(names); |
local id = table.concat(names); -- concatenate names and year for CITEREF id |
||
if utilities.is_set (id) then |
if utilities.is_set (id) then -- if concatenation is not an empty string |
||
return "CITEREF" .. id; |
return "CITEREF" .. id; -- add the CITEREF portion |
||
else |
else |
||
return ''; |
return ''; -- return an empty string; no reason to include CITEREF id in this citation |
||
end |
end |
||
end |
end |
||
Line 1,432: | Line 1,442: | ||
first, accept_name = utilities.has_accept_as_written (first); -- remove accept-this-as-written markup when it wraps all of <first> |
first, accept_name = utilities.has_accept_as_written (first); -- remove accept-this-as-written markup when it wraps all of <first> |
||
if not accept_name then |
if not accept_name then -- <first> not wrapped in accept-as-written markup |
||
name_has_ed_markup (first, list_name); -- check for extraneous 'editor' annotation |
name_has_ed_markup (first, list_name); -- check for extraneous 'editor' annotation |
||
name_is_numeric (first, list_name); -- check for names that are composed of digits and punctuation |
name_is_numeric (first, list_name); -- check for names that are composed of digits and punctuation |
||
Line 1,517: | Line 1,527: | ||
--[[ |
--[[---------------------< G E T _ I S O 6 3 9 _ C O D E >---------------------- |
||
Validates language names provided in |language= parameter if not an ISO639-1 or 639-2 code. |
Validates language names provided in |language= parameter if not an ISO639-1 or 639-2 code. |
||
Line 1,655: | Line 1,665: | ||
end |
end |
||
--[[-----------------------< S E T _ C S _ S T Y L E >-------------------------- |
|||
Gets the default CS style configuration for the given mode. |
|||
--[[----------------------< S E T _ C S 1 _ S T Y L E >------------------------- |
|||
Returns default separator and either postscript as passed in or the default. |
|||
In CS1, the default postscript and separator are '.'. |
|||
Set style settings for CS1 citation templates. Returns separator and postscript settings |
|||
In CS2, the default postscript is the empty string and the default separator is ','. |
|||
At en.wiki, for cs1: |
|||
ps gets: '.' |
|||
sep gets: '.' |
|||
]] |
]] |
||
local function set_cs_style (postscript, mode) |
|||
if utilities.is_set(postscript) then |
|||
local function set_cs1_style (ps) |
|||
-- emit a maintenance message if user postscript is the default cs1 postscript |
|||
if not utilities.is_set (ps) then -- unless explicitly set to something |
|||
-- we catch the opposite case for cs2 in set_style |
|||
ps = cfg.presentation['ps_cs1']; -- terminate the rendered citation |
|||
if mode == 'cs1' and postscript == cfg.presentation['ps_' .. mode] then |
|||
utilities.set_message ('maint_postscript'); |
|||
end |
|||
else |
|||
postscript = cfg.presentation['ps_' .. mode]; |
|||
end |
end |
||
return cfg.presentation[' |
return cfg.presentation['sep_' .. mode], postscript; |
||
end |
end |
||
--[[--------------------------< S E T _ S T Y L E >----------------------------- |
|||
Sets the separator and postscript styles. Checks the |mode= first and the |
|||
--[[-----------------------< S E T _ C S 2 _ S T Y L E >------------------------ |
|||
#invoke CitationClass second. Removes the postscript if postscript == none. |
|||
Set style settings for CS2 citation templates. Returns separator, postscript, ref settings |
|||
At en.wiki, for cs2: |
|||
ps gets: '' (empty string - no terminal punctuation) |
|||
sep gets: ',' |
|||
]] |
]] |
||
local function set_style (mode, postscript, cite_class) |
|||
local function set_cs2_style (ps, ref) |
|||
if not utilities.is_set (ps) then -- if |postscript= has not been set, set cs2 default |
|||
ps = cfg.presentation['ps_cs2']; -- terminate the rendered citation |
|||
end |
|||
if not utilities.is_set (ref) then -- if |ref= is not set |
|||
ref = "harv"; -- set default |ref=harv |
|||
end |
|||
return cfg.presentation['sep_cs2'], ps, ref; -- element separator |
|||
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 >-------- |
|||
When |mode= is not set or when its value is invalid, use config.CitationClass and |
|||
parameter values to establish rendered style. |
|||
]] |
|||
local function get_settings_from_cite_class (ps, ref, cite_class) |
|||
local sep; |
local sep; |
||
if 'cs2' == mode then |
|||
if (cite_class == "citation") then -- for citation templates (CS2) |
|||
sep, |
sep, postscript = set_cs_style (postscript, 'cs2'); |
||
elseif 'cs1' == mode then |
|||
else -- not a citation template so CS1 |
|||
sep, |
sep, postscript = set_cs_style (postscript, 'cs1'); |
||
elseif 'citation' == cite_class then |
|||
sep, postscript = set_cs_style (postscript, 'cs2'); |
|||
else |
|||
sep, postscript = set_cs_style (postscript, 'cs1'); |
|||
end |
end |
||
if cfg.keywords_xlate[postscript:lower()] == 'none' then |
|||
return sep, ps, ref -- return them all |
|||
-- emit a maintenance message if user postscript is the default cs2 postscript |
|||
end |
|||
-- we catch the opposite case for cs1 in set_cs_style |
|||
if 'cs2' == mode or 'citation' == cite_class then |
|||
utilities.set_message ('maint_postscript'); |
|||
--[[--------------------------< S E T _ S T Y L E >------------------------------------------------------------ |
|||
end |
|||
postscript = ''; |
|||
Establish basic style settings to be used when rendering the citation. Uses |mode= |
|||
if set and valid or uses config.CitationClass from the template's #invoke: to establish style. |
|||
]] |
|||
local function set_style (mode, ps, ref, cite_class) |
|||
local sep; |
|||
if 'cs2' == mode then -- if this template is to be rendered in CS2 (citation) style |
|||
sep, ps, ref = set_cs2_style (ps, ref); |
|||
elseif 'cs1' == mode then -- if this template is to be rendered in CS1 (cite xxx) style |
|||
sep, ps = set_cs1_style (ps); |
|||
else -- anything but cs1 or cs2 |
|||
sep, ps, ref = get_settings_from_cite_class (ps, ref, cite_class); -- get settings based on the template's CitationClass |
|||
end |
|||
if cfg.keywords_xlate[ps:lower()] == 'none' then -- if assigned value is 'none' then |
|||
ps = ''; -- set to empty string |
|||
end |
end |
||
return sep, |
return sep, postscript |
||
end |
end |
||
--[=[-------------------------< I S _ P D F >----------------------------------- |
--[=[-------------------------< I S _ P D F >----------------------------------- |
||
Line 1,801: | Line 1,776: | ||
]] |
]] |
||
local function get_display_names (max, count, list_name, etal) |
local function get_display_names (max, count, list_name, etal, param) |
||
if utilities.is_set (max) then |
if utilities.is_set (max) then |
||
if 'etal' == max:lower():gsub("[ '%.]", '') then -- the :gsub() portion makes 'etal' from a variety of 'et al.' spellings and stylings |
if 'etal' == max:lower():gsub("[ '%.]", '') then -- the :gsub() portion makes 'etal' from a variety of 'et al.' spellings and stylings |
||
Line 1,809: | Line 1,784: | ||
max = tonumber (max); -- make it a number |
max = tonumber (max); -- make it a number |
||
if max >= count then -- if |display-xxxxors= value greater than or equal to number of authors/editors |
if max >= count then -- if |display-xxxxors= value greater than or equal to number of authors/editors |
||
table.insert( z.message_tail, {utilities.set_message ('err_disp_name', { |
table.insert( z.message_tail, {utilities.set_message ('err_disp_name', {param, max}, true)}); -- add error message |
||
max = nil; |
max = nil; |
||
end |
end |
||
else -- not a valid keyword or number |
else -- not a valid keyword or number |
||
table.insert( z.message_tail, {utilities.set_message ('err_disp_name', { |
table.insert( z.message_tail, {utilities.set_message ('err_disp_name', {param, max}, true)}); -- add error message |
||
max = nil; -- unset; as if |display-xxxxors= had not been set |
max = nil; -- unset; as if |display-xxxxors= had not been set |
||
end |
end |
||
Line 1,834: | Line 1,809: | ||
]] |
]] |
||
local function extra_text_in_page_check ( |
local function extra_text_in_page_check (val, name) |
||
if not val:match (cfg.vol_iss_pg_patterns.good_ppattern) then |
|||
local good_pattern = '^P[^%.PpGg]'; -- OK to begin with uppercase P: P7 (page 7 of section P), but not p123 (page 123) |
|||
for _, pattern in ipairs (cfg.vol_iss_pg_patterns.bad_ppatterns) do -- spin through the selected sequence table of patterns |
|||
local bad_pattern = '^[Pp][PpGg]?%.?[ %d]'; |
|||
if val:match (pattern) then -- when a match, error so |
|||
table.insert (z.message_tail, {utilities.set_message ('err_extra_text_pages', {name}, true)}); -- add error message |
|||
return; -- and done |
|||
end |
|||
end |
|||
end |
|||
end |
|||
if not page:match (good_pattern) and (page:match (bad_pattern) or page:match ('^[Pp]ages?') or page:match ('^[Pp]gs.?')) then |
|||
--[[--------------------------< E X T R A _ T E X T _ I N _ V O L _ I S S _ C H E C K >------------------------ |
|||
table.insert( z.message_tail, { utilities.set_message ( 'err_extra_text_pages')}); -- add error |
|||
Adds error if |volume= or |issue= has what appears to be some form of redundant 'type' indicator. |
|||
For |volume=: |
|||
'V.', or 'Vol.' (with or without the dot) abbreviations or 'Volume' in the first characters of the parameter |
|||
content (all case insensitive). 'V' and 'v' (without the dot) are presumed to be roman numerals so |
|||
are allowed. |
|||
For |issue=: |
|||
'No.', 'I.', 'Iss.' (with or without the dot) abbreviations, or 'Issue' in the first characters of the |
|||
parameter content (all case insensitive). |
|||
Single character values ('v', 'i', 'n') allowed when not followed by separator character ('.', ':', '=', or |
|||
whitespace character) – param values are trimmed of whitespace by MediaWiki before delivered to the module. |
|||
<val> is |volume= or |issue= parameter value |
|||
<name> is |volume= or |issue= parameter name for error message |
|||
<selector> is 'v' for |volume=, 'i' for |issue= |
|||
sets error message on failure; returns nothing |
|||
]] |
|||
local function extra_text_in_vol_iss_check (val, name, selector) |
|||
if not utilities.is_set (val) then |
|||
return; |
|||
end |
|||
local patterns = 'v' == selector and cfg.vol_iss_pg_patterns.vpatterns or cfg.vol_iss_pg_patterns.ipatterns; |
|||
local handler = 'v' == selector and 'err_extra_text_volume' or 'err_extra_text_issue'; |
|||
val = val:lower(); -- force parameter value to lower case |
|||
for _, pattern in ipairs (patterns) do -- spin through the selected sequence table of patterns |
|||
if val:match (pattern) then -- when a match, error so |
|||
table.insert (z.message_tail, {utilities.set_message (handler, {name}, true)}); -- add error message |
|||
return; -- and done |
|||
end |
|||
end |
end |
||
end |
end |
||
Line 1,863: | Line 1,882: | ||
if name_table[i]:match ('^%(%(.*[^%)][^%)]$') then -- first segment of corporate with one or more commas; this segment has the opening doubled parentheses |
if name_table[i]:match ('^%(%(.*[^%)][^%)]$') then -- first segment of corporate with one or more commas; this segment has the opening doubled parentheses |
||
local name = name_table[i]; |
local name = name_table[i]; |
||
i = i + 1; |
i = i + 1; -- bump indexer to next segment |
||
while name_table[i] do |
while name_table[i] do |
||
name = name .. ', ' .. name_table[i]; -- concatenate with previous segments |
name = name .. ', ' .. name_table[i]; -- concatenate with previous segments |
||
Line 1,919: | Line 1,938: | ||
v_name, accept_name = utilities.has_accept_as_written (v_name); -- remove accept-this-as-written markup when it wraps all of <v_name> |
v_name, accept_name = utilities.has_accept_as_written (v_name); -- remove accept-this-as-written markup when it wraps all of <v_name> |
||
-- if v_name:match ('^%(%(.+%)%)$') then -- corporate authors are wrapped in doubled parentheses to suppress vanc formatting and error detection |
|||
-- last = v_name:match ('^%(%((.+)%)%)$') -- remove doubled parentheses |
|||
if accept_name then |
if accept_name then |
||
last = v_name; |
last = v_name; |
||
Line 1,926: | Line 1,943: | ||
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 (cfg.err_msg_supl.punctuation); |
add_vanc_error (cfg.err_msg_supl.punctuation, i); |
||
end |
end |
||
local lastfirstTable = {} |
local lastfirstTable = {} |
||
Line 1,940: | Line 1,957: | ||
first = ''; -- unset |
first = ''; -- unset |
||
last = v_name; -- last empty because something wrong with first |
last = v_name; -- last empty because something wrong with first |
||
add_vanc_error (cfg.err_msg_supl.name); |
add_vanc_error (cfg.err_msg_supl.name, i); |
||
end |
end |
||
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 (cfg.err_msg_supl['missing comma']); |
add_vanc_error (cfg.err_msg_supl['missing comma'], i); -- 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 (cfg.err_msg_supl. |
add_vanc_error (cfg.err_msg_supl.initials, i); -- matches a space between two initials |
||
end |
end |
||
else |
else |
||
Line 1,954: | Line 1,971: | ||
if utilities.is_set (first) then |
if utilities.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 (cfg.err_msg_supl.initials); |
add_vanc_error (cfg.err_msg_supl.initials, i); -- too many initials; mixed case initials (which may be ok Romanization); hyphenated initials |
||
end |
end |
||
is_good_vanc_name (last, first, suffix); -- check first and last before restoring the suffix which may have a non-Latin digit |
is_good_vanc_name (last, first, suffix, i); -- check first and last before restoring the suffix which may have a non-Latin digit |
||
if utilities.is_set (suffix) then |
if utilities.is_set (suffix) then |
||
first = first .. ' ' .. suffix; -- if there was a suffix concatenate with the initials |
first = first .. ' ' .. suffix; -- if there was a suffix concatenate with the initials |
||
Line 1,963: | Line 1,980: | ||
else |
else |
||
if not corporate then |
if not corporate then |
||
is_good_vanc_name (last, ''); |
is_good_vanc_name (last, '', nil, i); |
||
end |
end |
||
end |
end |
||
Line 2,177: | Line 2,194: | ||
]] |
]] |
||
local function insource_loc_get (page, pages, at) |
local function insource_loc_get (page, page_orig, pages, pages_orig, at) |
||
local ws_url, ws_label, coins_pages, L; -- for Wikisource interwiki-links; TODO: this corrupts page metadata (span remains in place after cleanup; fix there?) |
local ws_url, ws_label, coins_pages, L; -- for Wikisource interwiki-links; TODO: this corrupts page metadata (span remains in place after cleanup; fix there?) |
||
Line 2,185: | Line 2,202: | ||
at = ''; |
at = ''; |
||
end |
end |
||
extra_text_in_page_check (page); |
extra_text_in_page_check (page, page_orig); -- emit error message when |page= value begins with what looks like p., pp., etc. |
||
ws_url, ws_label, L = wikisource_url_make (page); -- make ws URL from |page= interwiki link; link portion L becomes tooltip label |
ws_url, ws_label, L = wikisource_url_make (page); -- make ws URL from |page= interwiki link; link portion L becomes tooltip label |
||
Line 2,197: | Line 2,214: | ||
at = ''; -- unset |
at = ''; -- unset |
||
end |
end |
||
extra_text_in_page_check (pages); |
extra_text_in_page_check (pages, pages_orig); -- emit error message when |page= value begins with what looks like p., pp., etc. |
||
ws_url, ws_label, L = wikisource_url_make (pages); -- make ws URL from |pages= interwiki link; link portion L becomes tooltip label |
ws_url, ws_label, L = wikisource_url_make (pages); -- make ws URL from |pages= interwiki link; link portion L becomes tooltip label |
||
Line 2,215: | Line 2,232: | ||
return page, pages, at, coins_pages; |
return page, pages, at, coins_pages; |
||
end |
|||
--[[--------------------------< I S _ U N I Q U E _ A R C H I V E _ U R L >------------------------------------ |
|||
add error message when |archive-url= value is same as |url= or chapter-url= (or alias...) value |
|||
]] |
|||
local function is_unique_archive_url (archive, url, c_url, source, date) |
|||
if utilities.is_set (archive) then |
|||
if archive == url or archive == c_url then |
|||
table.insert (z.message_tail, {utilities.set_message ('err_bad_url', {utilities.wrap_style ('parameter', source)}, true)}); -- add error message |
|||
return '', ''; -- unset |archive-url= and |archive-date= because same as |url= or |chapter-url= |
|||
end |
|||
end |
|||
return archive, date; |
|||
end |
end |
||
Line 2,364: | Line 2,398: | ||
]] |
]] |
||
local function citation0( config, args) |
local function citation0( config, args ) |
||
--[[ |
--[[ |
||
Load Input Parameters |
Load Input Parameters |
||
Line 2,374: | Line 2,408: | ||
-- Pick out the relevant fields from the arguments. Different citation templates |
-- Pick out the relevant fields from the arguments. Different citation templates |
||
-- define different field names for the same underlying things. |
-- define different field names for the same underlying things. |
||
local Mode = is_valid_parameter_value (A['Mode'], A:ORIGIN('Mode'), cfg.keywords_lists['mode'], ''); |
|||
local author_etal; |
local author_etal; |
||
local a = {}; -- authors list from |lastn= / |firstn= pairs or |vauthors= |
local a = {}; -- authors list from |lastn= / |firstn= pairs or |vauthors= |
||
local Authors; |
local Authors; |
||
local NameListStyle = is_valid_parameter_value (A['NameListStyle'], A:ORIGIN('NameListStyle'), cfg.keywords_lists['name-list-style'], ''); |
local NameListStyle = is_valid_parameter_value (A['NameListStyle'], A:ORIGIN('NameListStyle'), cfg.keywords_lists['name-list-style'], ''); |
||
local Collaboration = A['Collaboration']; |
local Collaboration = A['Collaboration']; |
||
Line 2,389: | Line 2,420: | ||
a, author_etal = extract_names (args, 'AuthorList'); -- fetch author list from |authorn= / |lastn= / |firstn=, |author-linkn=, and |author-maskn= |
a, author_etal = extract_names (args, 'AuthorList'); -- fetch author list from |authorn= / |lastn= / |firstn=, |author-linkn=, and |author-maskn= |
||
elseif 2 == selected then |
elseif 2 == selected then |
||
NameListStyle = 'vanc'; -- override whatever |name-list-style= might be |
NameListStyle = 'vanc'; -- override whatever |name-list-style= might be |
||
a, author_etal = parse_vauthors_veditors (args, args.vauthors, 'AuthorList'); -- fetch author list from |vauthors=, |author-linkn=, and |author-maskn= |
a, author_etal = parse_vauthors_veditors (args, args.vauthors, 'AuthorList'); -- fetch author list from |vauthors=, |author-linkn=, and |author-maskn= |
||
elseif 3 == selected then |
elseif 3 == selected then |
||
Line 2,401: | Line 2,432: | ||
end |
end |
||
end |
end |
||
local Others = A['Others']; |
|||
local editor_etal; |
local editor_etal; |
||
local e = {}; -- editors list from |editor-lastn= / |editor-firstn= pairs or |veditors= |
local e = {}; -- editors list from |editor-lastn= / |editor-firstn= pairs or |veditors= |
||
local Editors; |
|||
do -- to limit scope of selected |
do -- to limit scope of selected |
||
Line 2,417: | Line 2,445: | ||
end |
end |
||
end |
end |
||
local translator_etal; |
|||
local t = {}; -- translators list from |translator-lastn= / translator-firstn= pairs |
|||
local Translators; -- assembled translators name list |
|||
t = extract_names (args, 'TranslatorList'); -- fetch translator list from |translatorn= / |translator-lastn=, -firstn=, -linkn=, -maskn= |
|||
local interviewer_etal; |
|||
local interviewers_list = {}; |
|||
local Interviewers; -- used later |
|||
interviewers_list = extract_names (args, 'InterviewerList'); -- process preferred interviewers parameters |
|||
local contributor_etal; |
|||
local c = {}; -- contributors list from |contributor-lastn= / contributor-firstn= pairs |
|||
local Contributors; -- assembled contributors name list |
|||
local Chapter = A['Chapter']; -- done here so that we have access to |contribution= from |chapter= aliases |
local Chapter = A['Chapter']; -- done here so that we have access to |contribution= from |chapter= aliases |
||
local Chapter_origin = A:ORIGIN ('Chapter'); |
local Chapter_origin = A:ORIGIN ('Chapter'); |
||
local Contribution; -- because contribution is required for contributor(s) |
local Contribution; -- because contribution is required for contributor(s) |
||
if 'contribution' == |
if 'contribution' == Chapter_origin then |
||
Contribution = |
Contribution = Chapter; -- get the name of the contribution |
||
end |
end |
||
local c = {}; -- contributors list from |contributor-lastn= / contributor-firstn= pairs |
|||
if utilities.in_array (config.CitationClass, {"book", "citation"}) and not utilities.is_set (A['Periodical']) then -- |contributor= and |contribution= only supported in book cites |
if utilities.in_array (config.CitationClass, {"book", "citation"}) and not utilities.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,459: | Line 2,474: | ||
end |
end |
||
if utilities.is_set (Others) then |
|||
if 0 == #a and 0 == #e then -- add maint cat when |others= has value and used without |author=, |editor= |
|||
utilities.set_message ('maint_others'); |
|||
end |
|||
end |
|||
local Year = A['Year']; |
|||
local PublicationDate = A['PublicationDate']; |
|||
local OrigDate = A['OrigDate']; |
|||
local Date = A['Date']; |
|||
local LayDate = A['LayDate']; |
|||
------------------------------------------------- Get title data |
|||
local Title = A['Title']; |
local Title = A['Title']; |
||
local ScriptTitle = A['ScriptTitle']; |
|||
local BookTitle = A['BookTitle']; |
|||
local Conference = A['Conference']; |
|||
local TransTitle = A['TransTitle']; |
|||
local TransTitle_origin = A:ORIGIN ('TransTitle'); |
|||
local TitleNote = A['TitleNote']; |
|||
local TitleLink = A['TitleLink']; |
local TitleLink = A['TitleLink']; |
||
local auto_select = ''; -- default is auto |
local auto_select = ''; -- default is auto |
||
local accept_link; |
local accept_link; |
||
TitleLink, accept_link = utilities.has_accept_as_written(TitleLink, true); |
TitleLink, accept_link = utilities.has_accept_as_written(TitleLink, true); -- test for accept-this-as-written markup |
||
if (not accept_link) and utilities.in_array (TitleLink, {'none', 'pmc', 'doi'}) then -- check for special keywords |
if (not accept_link) and utilities.in_array (TitleLink, {'none', 'pmc', 'doi'}) then -- check for special keywords |
||
auto_select = TitleLink; |
auto_select = TitleLink; -- remember selection for later |
||
TitleLink = ''; |
TitleLink = ''; -- treat as if |title-link= would have been empty |
||
end |
end |
||
Line 2,491: | Line 2,488: | ||
local Section = ''; -- {{cite map}} only; preset to empty string for concatenation if not used |
local Section = ''; -- {{cite map}} only; preset to empty string for concatenation if not used |
||
if 'map' == config.CitationClass and 'section' == Chapter_origin then |
|||
Section = A['Chapter']; -- get |section= from |chapter= alias list; |chapter= and the other aliases not supported in {{cite map}} |
|||
Chapter = ''; -- unset for now; will be reset later from |map= if present |
|||
end |
|||
local ScriptChapter = A['ScriptChapter']; |
|||
local ScriptChapter_origin = A:ORIGIN ('ScriptChapter'); |
|||
local ChapterLink -- = A['ChapterLink']; -- deprecated as a parameter but still used internally by cite episode |
|||
local TransChapter = A['TransChapter']; |
|||
local TransChapter_origin = A:ORIGIN ('TransChapter'); |
|||
local TitleType = A['TitleType']; |
|||
local Degree = A['Degree']; |
|||
local Docket = A['Docket']; |
|||
local ArchiveFormat = A['ArchiveFormat']; |
|||
local ArchiveDate; |
|||
local ArchiveURL; |
|||
ArchiveURL, ArchiveDate = archive_url_check (A['ArchiveURL'], A['ArchiveDate']) |
|||
local UrlStatus = is_valid_parameter_value (A['UrlStatus'], A:ORIGIN('UrlStatus'), cfg.keywords_lists['url-status'], ''); |
|||
local URL = A['URL'] |
|||
local URL_origin = A:ORIGIN('URL'); -- get name of parameter that holds URL |
|||
local ChapterURL = A['ChapterURL']; |
|||
local ChapterURL_origin = A:ORIGIN('ChapterURL'); -- get name of parameter that holds ChapterURL |
|||
local ConferenceFormat = A['ConferenceFormat']; |
|||
local ConferenceURL = A['ConferenceURL']; |
|||
local ConferenceURL_origin = A:ORIGIN('ConferenceURL'); -- get name of parameter that holds ConferenceURL |
|||
local Periodical = A['Periodical']; |
local Periodical = A['Periodical']; |
||
Line 2,542: | Line 2,514: | ||
local ScriptPeriodical = A['ScriptPeriodical']; |
local ScriptPeriodical = A['ScriptPeriodical']; |
||
local ScriptPeriodical_origin = A:ORIGIN('ScriptPeriodical'); |
|||
-- web and news not tested for now because of |
-- web and news not tested for now because of |
||
Line 2,553: | Line 2,524: | ||
end |
end |
||
end |
end |
||
local TransPeriodical = A['TransPeriodical']; |
|||
local TransPeriodical_origin = A:ORIGIN ('TransPeriodical'); |
|||
local Series = A['Series']; |
|||
local Volume; |
local Volume; |
||
local ScriptPeriodical_origin = A:ORIGIN('ScriptPeriodical'); |
|||
local Issue; |
|||
local Page; |
|||
local Pages; |
|||
local At; |
|||
if 'citation' == config.CitationClass then |
if 'citation' == config.CitationClass then |
||
if utilities.is_set (Periodical) then |
if utilities.is_set (Periodical) then |
||
Line 2,580: | Line 2,542: | ||
Volume = A['Volume']; |
Volume = A['Volume']; |
||
end |
end |
||
extra_text_in_vol_iss_check (Volume, A:ORIGIN ('Volume'), 'v'); |
|||
local Issue; |
|||
if 'citation' == config.CitationClass then |
if 'citation' == config.CitationClass then |
||
if utilities.is_set (Periodical) and utilities.in_array (Periodical_origin, {'journal', 'magazine', 'newspaper', 'periodical', 'work'}) or -- {{citation}} renders issue for these 'periodicals' |
if utilities.is_set (Periodical) and utilities.in_array (Periodical_origin, {'journal', 'magazine', 'newspaper', 'periodical', 'work'}) or -- {{citation}} renders issue for these 'periodicals' |
||
Line 2,591: | Line 2,555: | ||
end |
end |
||
end |
end |
||
extra_text_in_vol_iss_check (Issue, A:ORIGIN ('Issue'), 'i'); |
|||
local |
local Page; |
||
local Pages; |
|||
local At; |
|||
if not utilities.in_array (config.CitationClass, cfg.templates_not_using_page) then |
if not utilities.in_array (config.CitationClass, cfg.templates_not_using_page) then |
||
Page = A['Page']; |
Page = A['Page']; |
||
Line 2,598: | Line 2,565: | ||
At = A['At']; |
At = A['At']; |
||
end |
end |
||
local QuotePage = A['QuotePage']; |
|||
local QuotePages = hyphen_to_dash (A['QuotePages']); |
|||
local Edition = A['Edition']; |
local Edition = A['Edition']; |
||
Line 2,629: | Line 2,594: | ||
end |
end |
||
local URL = A['URL'] |
|||
local UrlAccess = is_valid_parameter_value (A['UrlAccess'], A:ORIGIN('UrlAccess'), cfg.keywords_lists['url-access'], nil); |
local UrlAccess = is_valid_parameter_value (A['UrlAccess'], A:ORIGIN('UrlAccess'), cfg.keywords_lists['url-access'], nil); |
||
if not utilities.is_set (URL) and utilities.is_set (UrlAccess) then |
|||
if not utilities.is_set (URL) and utilities.is_set (UrlAccess) then |
|||
UrlAccess = nil; |
|||
UrlAccess = nil; |
|||
table.insert( z.message_tail, { utilities.set_message ( 'err_param_access_requires_param', {'url'}, true ) } ); |
|||
table.insert( z.message_tail, { utilities.set_message ( 'err_param_access_requires_param', {'url'}, true ) } ); |
|||
end |
|||
end |
|||
local ChapterURL = A['ChapterURL']; |
|||
local ChapterUrlAccess = is_valid_parameter_value (A['ChapterUrlAccess'], A:ORIGIN('ChapterUrlAccess'), cfg.keywords_lists['url-access'], nil); |
local ChapterUrlAccess = is_valid_parameter_value (A['ChapterUrlAccess'], A:ORIGIN('ChapterUrlAccess'), cfg.keywords_lists['url-access'], nil); |
||
if not utilities.is_set (ChapterURL) and utilities.is_set (ChapterUrlAccess) then |
if not utilities.is_set (ChapterURL) and utilities.is_set (ChapterUrlAccess) then |
||
Line 2,647: | Line 2,615: | ||
end |
end |
||
local this_page = mw.title.getCurrentTitle(); -- also used for COinS and for language |
|||
local Via = A['Via']; |
|||
local AccessDate = A['AccessDate']; |
|||
local Agency = A['Agency']; |
|||
local Language = A['Language']; |
|||
local Format = A['Format']; |
|||
local ChapterFormat = A['ChapterFormat']; |
|||
local DoiBroken = A['DoiBroken']; |
|||
local ID = A['ID']; |
|||
local ASINTLD = A['ASINTLD']; |
|||
local Embargo = A['Embargo']; |
|||
local Class = A['Class']; -- arxiv class identifier |
|||
local Quote = A['Quote']; |
|||
local ScriptQuote = A['ScriptQuote']; |
|||
local TransQuote = A['TransQuote']; |
|||
local LayFormat = A['LayFormat']; |
|||
local LayURL = A['LayURL']; |
|||
local LaySource = A['LaySource']; |
|||
local Transcript = A['Transcript']; |
|||
local TranscriptFormat = A['TranscriptFormat']; |
|||
local TranscriptURL = A['TranscriptURL'] |
|||
local TranscriptURL_origin = A:ORIGIN('TranscriptURL'); -- get name of parameter that holds TranscriptURL |
|||
local no_tracking_cats = is_valid_parameter_value (A['NoTracking'], A:ORIGIN('NoTracking'), cfg.keywords_lists['yes_true_y'], nil); |
local no_tracking_cats = is_valid_parameter_value (A['NoTracking'], A:ORIGIN('NoTracking'), cfg.keywords_lists['yes_true_y'], nil); |
||
-- local variables that are not cs1 parameters |
|||
local use_lowercase; -- controls capitalization of certain static text |
|||
local this_page = mw.title.getCurrentTitle(); -- also used for COinS and for language |
|||
local anchor_year; -- used in the CITEREF identifier |
|||
local COinS_date = {}; -- holds date info extracted from |date= for the COinS metadata by Module:Date verification |
|||
local DF = is_valid_parameter_value (A['DF'], A:ORIGIN('DF'), cfg.keywords_lists['df'], ''); |
|||
if not utilities.is_set (DF) then |
|||
DF = cfg.global_df; -- local |df= if present overrides global df set by {{use xxx date}} template |
|||
end |
|||
local sepc; -- separator between citation elements for CS1 a period, for CS2, a comma |
|||
local PostScript; |
|||
local Ref = A['Ref']; |
|||
if 'harv' == Ref then |
|||
utilities.set_message ('maint_ref_harv'); -- add maint cat to identify templates that have this now-extraneous param value |
|||
elseif not utilities.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 |
|||
-- 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 |
||
Line 2,713: | Line 2,635: | ||
local coins_pages; |
local coins_pages; |
||
Page, Pages, At, coins_pages = insource_loc_get (Page, Pages, At); |
Page, Pages, At, coins_pages = insource_loc_get (Page, A:ORIGIN('Page'), Pages, A:ORIGIN('Pages'), At); |
||
local NoPP = is_valid_parameter_value (A['NoPP'], A:ORIGIN('NoPP'), cfg.keywords_lists['yes_true_y'], nil); |
local NoPP = is_valid_parameter_value (A['NoPP'], A:ORIGIN('NoPP'), cfg.keywords_lists['yes_true_y'], nil); |
||
Line 2,727: | Line 2,649: | ||
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 |
||
local URL_origin = A:ORIGIN('URL'); -- get name of parameter that holds URL |
|||
local ChapterURL_origin = A:ORIGIN('ChapterURL'); -- get name of parameter that holds ChapterURL |
|||
local ScriptChapter = A['ScriptChapter']; |
|||
local ScriptChapter_origin = A:ORIGIN ('ScriptChapter'); |
|||
local Format = A['Format']; |
|||
local ChapterFormat = A['ChapterFormat']; |
|||
local TransChapter = A['TransChapter']; |
|||
local TransChapter_origin = A:ORIGIN ('TransChapter'); |
|||
local TransTitle = A['TransTitle']; |
|||
local ScriptTitle = A['ScriptTitle']; |
|||
--[[ |
--[[ |
||
Line 2,768: | Line 2,701: | ||
TransChapter = TransTitle; |
TransChapter = TransTitle; |
||
ChapterURL = URL; |
ChapterURL = URL; |
||
ChapterURL_origin = |
ChapterURL_origin = URL_origin; |
||
ChapterUrlAccess = UrlAccess; |
ChapterUrlAccess = UrlAccess; |
||
Line 2,792: | Line 2,725: | ||
-- special case for cite techreport. |
-- special case for cite techreport. |
||
local ID = A['ID']; |
|||
if (config.CitationClass == "techreport") then -- special case for cite techreport |
if (config.CitationClass == "techreport") then -- special case for cite techreport |
||
if utilities.is_set (A['Number']) then -- cite techreport uses 'number', which other citations alias to 'issue' |
if utilities.is_set (A['Number']) then -- cite techreport uses 'number', which other citations alias to 'issue' |
||
Line 2,803: | Line 2,737: | ||
-- 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. |
||
local ChapterLink -- = A['ChapterLink']; -- deprecated as a parameter but still used internally by cite episode |
|||
local Conference = A['Conference']; |
|||
local BookTitle = A['BookTitle']; |
|||
local TransTitle_origin = A:ORIGIN ('TransTitle'); |
|||
if 'conference' == config.CitationClass then |
if 'conference' == config.CitationClass then |
||
if utilities.is_set (BookTitle) then |
if utilities.is_set (BookTitle) then |
||
Line 2,824: | Line 2,762: | ||
Conference = ''; -- not cite conference or cite speech so make sure this is empty string |
Conference = ''; -- not cite conference or cite speech so make sure this is empty string |
||
end |
end |
||
-- CS1/2 mode |
|||
local Mode = is_valid_parameter_value (A['Mode'], A:ORIGIN('Mode'), cfg.keywords_lists['mode'], ''); |
|||
-- separator character and postscript |
|||
local sepc, PostScript = set_style (Mode:lower(), A['PostScript'], config.CitationClass); |
|||
-- controls capitalization of certain static text |
|||
local use_lowercase = ( sepc == ',' ); |
|||
-- cite map oddities |
-- cite map oddities |
||
local Cartography = ""; |
local Cartography = ""; |
||
Line 2,856: | Line 2,801: | ||
-- 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. |
||
local Series = A['Series']; |
|||
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,890: | Line 2,836: | ||
ChapterURL = URL; |
ChapterURL = URL; |
||
ChapterUrlAccess = UrlAccess; |
ChapterUrlAccess = UrlAccess; |
||
ChapterURL_origin = |
ChapterURL_origin = URL_origin; |
||
Title = Series; -- promote series to title |
Title = Series; -- promote series to title |
||
Line 2,917: | Line 2,863: | ||
-- handle type parameter for those CS1 citations that have default values |
-- handle type parameter for those CS1 citations that have default values |
||
local TitleType = A['TitleType']; |
|||
local Degree = A['Degree']; |
|||
if utilities.in_array (config.CitationClass, {"AV-media-notes", "interview", "mailinglist", "map", "podcast", "pressrelease", "report", "techreport", "thesis"}) then |
if utilities.in_array (config.CitationClass, {"AV-media-notes", "interview", "mailinglist", "map", "podcast", "pressrelease", "report", "techreport", "thesis"}) then |
||
TitleType = set_titletype (config.CitationClass, TitleType); |
TitleType = set_titletype (config.CitationClass, TitleType); |
||
Line 2,930: | Line 2,878: | ||
-- legacy: promote PublicationDate to Date if neither Date nor Year are set. |
-- legacy: promote PublicationDate to Date if neither Date nor Year are set. |
||
local Date = A['Date']; |
|||
local Date_origin; -- to hold the name of parameter promoted to Date; required for date error messaging |
local Date_origin; -- to hold the name of parameter promoted to Date; required for date error messaging |
||
local PublicationDate = A['PublicationDate']; |
|||
local Year = A['Year']; |
|||
if not utilities.is_set (Date) then |
if not utilities.is_set (Date) then |
||
Line 2,954: | Line 2,905: | ||
Date validation supporting code is in Module:Citation/CS1/Date_validation |
Date validation supporting code is in Module:Citation/CS1/Date_validation |
||
]] |
]] |
||
local DF = is_valid_parameter_value (A['DF'], A:ORIGIN('DF'), cfg.keywords_lists['df'], ''); |
|||
if not utilities.is_set (DF) then |
|||
DF = cfg.global_df; -- local |df= if present overrides global df set by {{use xxx date}} template |
|||
end |
|||
local ArchiveURL; |
|||
local ArchiveDate; |
|||
local ArchiveFormat = A['ArchiveFormat']; |
|||
ArchiveURL, ArchiveDate = archive_url_check (A['ArchiveURL'], A['ArchiveDate']) |
|||
ArchiveFormat = style_format (ArchiveFormat, ArchiveURL, 'archive-format', 'archive-url'); |
|||
ArchiveURL, ArchiveDate = is_unique_archive_url (ArchiveURL, URL, ChapterURL, A:ORIGIN('ArchiveURL'), ArchiveDate); -- add error message when URL or ChapterURL == ArchiveURL |
|||
local AccessDate = A['AccessDate']; |
|||
local LayDate = A['LayDate']; |
|||
local COinS_date = {}; -- holds date info extracted from |date= for the COinS metadata by Module:Date verification |
|||
local DoiBroken = A['DoiBroken']; |
|||
local Embargo = A['Embargo']; |
|||
local anchor_year; -- used in the CITEREF identifier |
|||
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,978: | Line 2,951: | ||
if utilities.is_set (Year) and utilities.is_set (Date) then -- both |date= and |year= not normally needed; |
if utilities.is_set (Year) and utilities.is_set (Date) then -- both |date= and |year= not normally needed; |
||
validation.year_date_check (Year, A:ORIGIN ('Year'), Date, A:ORIGIN ('Date'), error_list); |
|||
if 0 == mismatch then -- |year= does not match a year-value in |date= |
|||
table.insert (error_list, '<code class="cs1-code">|year= / |date= mismatch</code>'); |
|||
elseif 1 == mismatch then -- |year= matches year-value in |date= |
|||
utilities.set_message ('maint_date_year'); -- add a maint cat |
|||
end |
|||
end |
end |
||
Line 2,989: | Line 2,957: | ||
local modified = false; -- flag |
local modified = false; -- flag |
||
if validation.edtf_transform (date_parameters_list) then -- edtf dates to MOS compliant format |
|||
modified = true; |
|||
end |
|||
if utilities.is_set (DF) then -- if we need to reformat dates |
if utilities.is_set (DF) then -- if we need to reformat dates |
||
modified = validation.reformat_dates (date_parameters_list, DF); -- reformat to DF format, use long month names if appropriate |
modified = validation.reformat_dates (date_parameters_list, DF); -- reformat to DF format, use long month names if appropriate |
||
Line 3,020: | Line 2,992: | ||
local ID_list = {}; -- sequence table of rendered identifiers |
local ID_list = {}; -- sequence table of rendered identifiers |
||
local ID_list_coins = {}; -- table of identifiers and their values from args; key is same as cfg.id_handlers's key |
local ID_list_coins = {}; -- table of identifiers and their values from args; key is same as cfg.id_handlers's key |
||
local Class = A['Class']; -- arxiv class identifier |
|||
ID_list, ID_list_coins = identifiers.identifier_lists_get (args, {DoiBroken = DoiBroken, ASINTLD = ASINTLD, Embargo = Embargo, Class = Class}); |
|||
local ID_support = { |
|||
{A['ASINTLD'], 'ASIN', 'err_asintld_missing_asin', A:ORIGIN ('ASINTLD')}, |
|||
{DoiBroken, 'DOI', 'err_doibroken_missing_doi', A:ORIGIN ('DoiBroken')}, |
|||
{Embargo, 'PMC', 'err_embargo_missing_pmc', A:ORIGIN ('Embargo')}, |
|||
} |
|||
ID_list, ID_list_coins = identifiers.identifier_lists_get (args, {DoiBroken = DoiBroken, ASINTLD = A['ASINTLD'], Embargo = Embargo, Class = Class}, ID_support); |
|||
if utilities.is_set (DoiBroken) and not ID_list_coins['DOI'] then |
|||
table.insert (z.message_tail, {utilities.set_message ('err_doibroken_missing_doi', A:ORIGIN('DoiBroken'))}); |
|||
end |
|||
-- 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. |
||
Line 3,038: | Line 3,014: | ||
if config.CitationClass == "journal" and not utilities.is_set (URL) and not utilities.is_set (TitleLink) and not utilities.in_array (cfg.keywords_xlate[Title], {'off', 'none'}) then -- TODO: remove 'none' once existing citations have been switched to 'off', so 'none' can be used as token for "no title" instead |
if config.CitationClass == "journal" and not utilities.is_set (URL) and not utilities.is_set (TitleLink) and not utilities.in_array (cfg.keywords_xlate[Title], {'off', 'none'}) then -- TODO: remove 'none' once existing citations have been switched to 'off', so 'none' can be used as token for "no title" instead |
||
if 'none' ~= cfg.keywords_xlate[auto_select] then -- if auto-linking not disabled |
|||
if identifiers.auto_link_urls[auto_select] then |
if identifiers.auto_link_urls[auto_select] then -- manual selection |
||
URL = identifiers.auto_link_urls[auto_select]; |
URL = identifiers.auto_link_urls[auto_select]; -- set URL to be the same as identifier's external link |
||
URL_origin = cfg.id_handlers[auto_select:upper()].parameters[1]; |
URL_origin = cfg.id_handlers[auto_select:upper()].parameters[1]; -- set URL_origin to parameter name for use in error message if citation is missing a |title= |
||
elseif identifiers.auto_link_urls['pmc'] then |
elseif identifiers.auto_link_urls['pmc'] then -- auto-select PMC |
||
URL = identifiers.auto_link_urls['pmc']; |
URL = identifiers.auto_link_urls['pmc']; -- set URL to be the same as the PMC external link if not embargoed |
||
URL_origin = cfg.id_handlers['PMC'].parameters[1]; |
URL_origin = cfg.id_handlers['PMC'].parameters[1]; -- set URL_origin to parameter name for use in error message if citation is missing a |title= |
||
elseif identifiers.auto_link_urls['doi'] then |
elseif identifiers.auto_link_urls['doi'] then -- auto-select DOI |
||
URL = identifiers.auto_link_urls['doi']; |
URL = identifiers.auto_link_urls['doi']; |
||
URL_origin = cfg.id_handlers['DOI'].parameters[1]; |
URL_origin = cfg.id_handlers['DOI'].parameters[1]; |
||
Line 3,095: | Line 3,071: | ||
coins_author = c; -- use that instead |
coins_author = c; -- use that instead |
||
end |
end |
||
local QuotePage = A['QuotePage']; |
|||
local QuotePages = hyphen_to_dash (A['QuotePages']); |
|||
-- this is the function call to COinS() |
-- this is the function call to COinS() |
||
Line 3,130: | Line 3,109: | ||
end |
end |
||
local Editors; |
|||
local EditorCount; -- used only for choosing {ed.) or (eds.) annotation at end of editor name-list |
|||
local Contributors; -- assembled contributors name list |
|||
local contributor_etal; |
|||
local Translators; -- assembled translators name list |
|||
local translator_etal; |
|||
local t = {}; -- translators list from |translator-lastn= / translator-firstn= pairs |
|||
t = extract_names (args, 'TranslatorList'); -- fetch translator list from |translatorn= / |translator-lastn=, -firstn=, -linkn=, -maskn= |
|||
local Interviewers; |
|||
local interviewers_list = {}; |
|||
interviewers_list = extract_names (args, 'InterviewerList'); -- process preferred interviewers parameters |
|||
local interviewer_etal; |
|||
-- Now perform various field substitutions. |
-- Now perform various field substitutions. |
||
-- We also add leading spaces and surrounding markup and punctuation to the |
-- We also add leading spaces and surrounding markup and punctuation to the |
||
-- various parts of the citation, but only when they are non-nil. |
-- various parts of the citation, but only when they are non-nil. |
||
local EditorCount; -- used only for choosing {ed.) or (eds.) annotation at end of editor name-list |
|||
do |
do |
||
local last_first_list; |
local last_first_list; |
||
Line 3,143: | Line 3,134: | ||
do -- do editor name list first because the now unsupported coauthors used to modify control table |
do -- do editor name list first because the now unsupported coauthors used to modify control table |
||
control.maximum , editor_etal = get_display_names (A['DisplayEditors'], #e, 'editors', editor_etal); |
control.maximum , editor_etal = get_display_names (A['DisplayEditors'], #e, 'editors', editor_etal, A:ORIGIN ('DisplayEditors')); |
||
Editors, EditorCount = list_people (control, e, editor_etal); |
Editors, EditorCount = list_people (control, e, editor_etal); |
||
Line 3,151: | Line 3,142: | ||
end |
end |
||
do -- now do interviewers |
do -- now do interviewers |
||
control.maximum |
control.maximum, interviewer_etal = get_display_names (A['DisplayInterviewers'], #interviewers_list, 'interviewers', interviewer_etal, A:ORIGIN ('DisplayInterviewers')); |
||
Interviewers = list_people (control, interviewers_list, interviewer_etal); |
Interviewers = list_people (control, interviewers_list, interviewer_etal); |
||
end |
end |
||
do -- now do translators |
do -- now do translators |
||
control.maximum |
control.maximum, translator_etal = get_display_names (A['DisplayTranslators'], #t, 'translators', translator_etal, A:ORIGIN ('DisplayTranslators')); |
||
Translators = list_people (control, t, translator_etal); |
Translators = list_people (control, t, translator_etal); |
||
end |
end |
||
do -- now do contributors |
do -- now do contributors |
||
control.maximum |
control.maximum, contributor_etal = get_display_names (A['DisplayContributors'], #c, 'contributors', contributor_etal, A:ORIGIN ('DisplayContributors')); |
||
Contributors = list_people (control, c, contributor_etal); |
Contributors = list_people (control, c, contributor_etal); |
||
end |
end |
||
do -- now do authors |
do -- now do authors |
||
control.maximum |
control.maximum, author_etal = get_display_names (A['DisplayAuthors'], #a, 'authors', author_etal, A:ORIGIN ('DisplayAuthors')); |
||
last_first_list = list_people(control, a, author_etal); |
last_first_list = list_people (control, a, author_etal); |
||
if utilities.is_set (Authors) then |
if utilities.is_set (Authors) then |
||
Line 3,183: | Line 3,174: | ||
end |
end |
||
local ConferenceFormat = A['ConferenceFormat']; |
|||
-- apply |[xx-]format= styling; at the end, these parameters hold correctly styled format annotation, |
|||
local ConferenceURL = A['ConferenceURL']; |
|||
-- 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'); |
|||
ConferenceFormat = style_format (ConferenceFormat, ConferenceURL, 'conference-format', 'conference-url'); |
ConferenceFormat = style_format (ConferenceFormat, ConferenceURL, 'conference-format', 'conference-url'); |
||
Format = style_format (Format, URL, 'format', 'url'); |
Format = style_format (Format, URL, 'format', 'url'); |
||
LayFormat = style_format (LayFormat, LayURL, 'lay-format', 'lay-url'); |
|||
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 |
||
Line 3,210: | Line 3,198: | ||
end |
end |
||
local UrlStatus = is_valid_parameter_value (A['UrlStatus'], A:ORIGIN('UrlStatus'), cfg.keywords_lists['url-status'], ''); |
|||
local OriginalURL, OriginalURL_origin, OriginalFormat, OriginalAccess; |
|||
local OriginalURL |
|||
local OriginalURL_origin |
|||
local OriginalFormat |
|||
local OriginalAccess; |
|||
UrlStatus = UrlStatus:lower(); -- used later when assembling archived text |
UrlStatus = UrlStatus:lower(); -- used later when assembling archived text |
||
if utilities.is_set ( ArchiveURL ) then |
if utilities.is_set ( ArchiveURL ) then |
||
Line 3,377: | Line 3,369: | ||
end |
end |
||
local ConferenceURL_origin = A:ORIGIN('ConferenceURL'); -- get name of parameter that holds ConferenceURL |
|||
if utilities.is_set (Conference) then |
if utilities.is_set (Conference) then |
||
if utilities.is_set (ConferenceURL) then |
if utilities.is_set (ConferenceURL) then |
||
Line 3,386: | Line 3,379: | ||
end |
end |
||
local Position = ''; |
|||
if not utilities.is_set (Position) then |
if not utilities.is_set (Position) then |
||
local Minutes = A['Minutes']; |
local Minutes = A['Minutes']; |
||
Line 3,432: | Line 3,426: | ||
end |
end |
||
local Others = A['Others']; |
|||
if utilities.is_set (Language) then |
|||
if utilities.is_set (Others) and 0 == #a and 0 == #e then -- add maint cat when |others= has value and used without |author=, |editor= |
|||
Language = language_parameter (Language); -- format, categories, name from ISO639-1, etc. |
|||
if config.CitationClass == "AV-media-notes" |
|||
else |
|||
or config.CitationClass == "audio-visual" then -- special maint for AV/M which has a lot of 'false' positives right now |
|||
Language=""; -- language not specified so make sure this is an empty string; |
|||
utilities.set_message ('maint_others_avm') |
|||
--[[ TODO: need to extract the wrap_msg from language_parameter |
|||
else |
|||
so that we can solve parentheses bunching problem with Format/Language/TitleType |
|||
utilities.set_message ('maint_others'); |
|||
]] |
|||
end |
|||
end |
end |
||
Others = utilities.is_set (Others) and (sepc .. " " .. Others) or ""; |
Others = utilities.is_set (Others) and (sepc .. " " .. Others) or ""; |
||
Line 3,450: | Line 3,444: | ||
end |
end |
||
local TitleNote = A['TitleNote']; |
|||
TitleNote = utilities.is_set (TitleNote) and (sepc .. " " .. TitleNote) or ""; |
TitleNote = utilities.is_set (TitleNote) and (sepc .. " " .. TitleNote) or ""; |
||
if utilities.is_set (Edition) then |
if utilities.is_set (Edition) then |
||
Line 3,461: | Line 3,456: | ||
Series = utilities.is_set (Series) and wrap_msg ('series', {sepc, Series}) or ""; -- not the same as SeriesNum |
Series = utilities.is_set (Series) and wrap_msg ('series', {sepc, Series}) or ""; -- not the same as SeriesNum |
||
local Agency = A['Agency']; |
|||
OrigDate = utilities.is_set (OrigDate) and wrap_msg ('origdate', OrigDate) or ''; |
|||
Agency = utilities.is_set (Agency) and wrap_msg ('agency', {sepc, Agency}) or ""; |
Agency = utilities.is_set (Agency) and wrap_msg ('agency', {sepc, Agency}) or ""; |
||
Volume = format_volume_issue (Volume, Issue, config.CitationClass, Periodical_origin, sepc, use_lowercase); |
Volume = format_volume_issue (Volume, Issue, config.CitationClass, Periodical_origin, sepc, use_lowercase); |
||
------------------------------------ totally unrelated data |
|||
Via = utilities.is_set (Via) and wrap_msg ('via', Via) or ''; |
|||
if utilities.is_set (AccessDate) then |
if utilities.is_set (AccessDate) then |
||
Line 3,479: | Line 3,471: | ||
if utilities.is_set (ID) then ID = sepc .. " " .. ID; end |
if utilities.is_set (ID) then ID = sepc .. " " .. ID; end |
||
local Docket = A['Docket']; |
|||
if "thesis" == config.CitationClass and utilities.is_set (Docket) then |
if "thesis" == config.CitationClass and utilities.is_set (Docket) then |
||
ID = sepc .. " Docket " .. Docket .. ID; |
ID = sepc .. " Docket " .. Docket .. ID; |
||
Line 3,490: | Line 3,484: | ||
end |
end |
||
local Quote = A['Quote']; |
|||
local TransQuote = A['TransQuote']; |
|||
local ScriptQuote = A['ScriptQuote']; |
|||
if utilities.is_set (Quote) or utilities.is_set (TransQuote) or utilities.is_set (ScriptQuote) then |
if utilities.is_set (Quote) or utilities.is_set (TransQuote) or utilities.is_set (ScriptQuote) then |
||
Line 3,498: | Line 3,495: | ||
end |
end |
||
Quote = utilities.wrap_style ('quoted-text', Quote ); |
Quote = utilities.wrap_style ('quoted-text', Quote ); -- wrap in <q>...</q> tags |
||
if utilities.is_set (ScriptQuote) then |
if utilities.is_set (ScriptQuote) then |
||
Quote = script_concatenate (Quote, ScriptQuote, 'script-quote'); |
Quote = script_concatenate (Quote, ScriptQuote, 'script-quote'); -- <bdi> tags, lang attribute, categorization, etc.; must be done after quote is wrapped |
||
end |
end |
||
Line 3,511: | Line 3,508: | ||
end |
end |
||
if utilities.is_set (QuotePage) or utilities.is_set (QuotePages) then -- add page prefix |
|||
-- if not utilities.in_array (config.CitationClass, cfg.templates_not_using_page) |
|||
if utilities.is_set (QuotePage) or utilities.is_set (QuotePages) then -- add page prefix |
|||
local quote_prefix = ''; |
local quote_prefix = ''; |
||
if utilities.is_set (QuotePage) then |
if utilities.is_set (QuotePage) then |
||
extra_text_in_page_check (QuotePage); |
extra_text_in_page_check (QuotePage, 'quote-page'); -- add to maint cat if |quote-page= value begins with what looks like p., pp., etc. |
||
if not NoPP then |
if not NoPP then |
||
quote_prefix = utilities.substitute (cfg.messages['p-prefix'], {sepc, QuotePage}), '', '', ''; |
quote_prefix = utilities.substitute (cfg.messages['p-prefix'], {sepc, QuotePage}), '', '', ''; |
||
Line 3,522: | Line 3,518: | ||
end |
end |
||
elseif utilities.is_set (QuotePages) then |
elseif utilities.is_set (QuotePages) then |
||
extra_text_in_page_check (QuotePages); |
extra_text_in_page_check (QuotePages, 'quote-pages'); -- add to maint cat if |quote-pages= value begins with what looks like p., pp., etc. |
||
if tonumber(QuotePages) ~= nil and not NoPP then -- if only digits, assume single page |
if tonumber(QuotePages) ~= nil and not NoPP then -- if only digits, assume single page |
||
quote_prefix = utilities.substitute (cfg.messages['p-prefix'], {sepc, QuotePages}), '', ''; |
quote_prefix = utilities.substitute (cfg.messages['p-prefix'], {sepc, QuotePages}), '', ''; |
||
Line 3,538: | Line 3,534: | ||
PostScript = ""; -- cs1|2 does not supply terminal punctuation when |quote= is set |
PostScript = ""; -- cs1|2 does not supply terminal punctuation when |quote= is set |
||
end |
|||
-- We check length of PostScript here because it will have been nuked by |
|||
-- the quote parameters. We'd otherwise emit a message even if there wasn't |
|||
-- a displayed postscript. |
|||
-- TODO: Should the max size (1) be configurable? |
|||
-- TODO: Should we check a specific pattern? |
|||
if utilities.is_set(PostScript) and mw.ustring.len(PostScript) > 1 then |
|||
utilities.set_message('maint_postscript') |
|||
end |
end |
||
Line 3,583: | Line 3,588: | ||
local Lay = ''; |
local Lay = ''; |
||
local LaySource = A['LaySource']; |
|||
local LayURL = A['LayURL']; |
|||
local LayFormat = A['LayFormat']; |
|||
LayFormat = style_format (LayFormat, LayURL, 'lay-format', 'lay-url'); |
|||
if utilities.is_set (LayURL) then |
if utilities.is_set (LayURL) then |
||
if utilities.is_set (LayDate) then LayDate = " (" .. LayDate .. ")" end |
if utilities.is_set (LayDate) then LayDate = " (" .. LayDate .. ")" end |
||
Line 3,599: | Line 3,608: | ||
end |
end |
||
local TranscriptURL = A['TranscriptURL'] |
|||
local TranscriptFormat = A['TranscriptFormat']; |
|||
TranscriptFormat = style_format (TranscriptFormat, TranscriptURL, 'transcript-format', 'transcripturl'); |
|||
local Transcript = A['Transcript']; |
|||
local TranscriptURL_origin = A:ORIGIN('TranscriptURL'); -- get name of parameter that holds TranscriptURL |
|||
if utilities.is_set (Transcript) then |
if utilities.is_set (Transcript) then |
||
if utilities.is_set (TranscriptURL) then |
if utilities.is_set (TranscriptURL) then |
||
Line 3,624: | Line 3,638: | ||
end |
end |
||
local TransPeriodical = A['TransPeriodical']; |
|||
local TransPeriodical_origin = A:ORIGIN ('TransPeriodical'); |
|||
-- Several of the above rely upon detecting this as nil, so do it last. |
-- Several of the above rely upon detecting this as nil, so do it last. |
||
if (utilities.is_set (Periodical) or utilities.is_set (ScriptPeriodical) or utilities.is_set (TransPeriodical)) then |
if (utilities.is_set (Periodical) or utilities.is_set (ScriptPeriodical) or utilities.is_set (TransPeriodical)) then |
||
Line 3,631: | Line 3,647: | ||
Periodical = format_periodical (ScriptPeriodical, ScriptPeriodical_origin, Periodical, TransPeriodical, TransPeriodical_origin); |
Periodical = format_periodical (ScriptPeriodical, ScriptPeriodical_origin, Periodical, TransPeriodical, TransPeriodical_origin); |
||
end |
end |
||
end |
|||
local Language = A['Language']; |
|||
if utilities.is_set (Language) then |
|||
Language = language_parameter (Language); -- format, categories, name from ISO639-1, etc. |
|||
else |
|||
Language=''; -- language not specified so make sure this is an empty string; |
|||
--[[ TODO: need to extract the wrap_msg from language_parameter |
|||
so that we can solve parentheses bunching problem with Format/Language/TitleType |
|||
]] |
|||
end |
end |
||
Line 3,687: | Line 3,713: | ||
end |
end |
||
local Via = A['Via']; |
|||
Via = utilities.is_set (Via) and wrap_msg ('via', Via) or ''; |
|||
local idcommon; |
local idcommon; |
||
if 'audio-visual' == config.CitationClass or 'episode' == config.CitationClass then -- special case for cite AV media & cite episode position transcript |
if 'audio-visual' == config.CitationClass or 'episode' == config.CitationClass then -- special case for cite AV media & cite episode position transcript |
||
Line 3,697: | Line 3,725: | ||
local pgtext = Position .. Sheet .. Sheets .. Page .. Pages .. At; |
local pgtext = Position .. Sheet .. Sheets .. Page .. Pages .. At; |
||
local OrigDate = A['OrigDate']; |
|||
OrigDate = utilities.is_set (OrigDate) and wrap_msg ('origdate', OrigDate) or ''; |
|||
if utilities.is_set (Date) then |
if utilities.is_set (Date) then |
||
if utilities.is_set (Authors) or utilities.is_set (Editors) then -- date follows authors or editors when authors not set |
if utilities.is_set (Authors) or utilities.is_set (Editors) then -- date follows authors or editors when authors not set |
||
Line 3,772: | Line 3,802: | ||
text = safe_join( {text, PostScript}, sepc ); |
text = safe_join( {text, PostScript}, sepc ); |
||
-- Now enclose the whole thing in a <cite |
-- Now enclose the whole thing in a <cite> element |
||
local options = {}; |
local options = {}; |
||
Line 3,780: | Line 3,810: | ||
options.class = string.format ('%s %s', 'citation', utilities.is_set (Mode) and Mode or 'cs2'); |
options.class = string.format ('%s %s', 'citation', utilities.is_set (Mode) and Mode or 'cs2'); |
||
end |
end |
||
local Ref = A['Ref']; |
|||
if utilities.is_set (Ref) and 'none' ~= cfg.keywords_xlate[Ref:lower()] then |
|||
if 'harv' == Ref then -- need to check this before setting to default |
|||
utilities.set_message ('maint_ref_harv'); -- add maint cat to identify templates that have this now-extraneous param value |
|||
elseif not utilities.is_set (Ref) then |
|||
Ref = 'harv'; -- set as default when not set externally |
|||
end |
|||
if 'none' ~= cfg.keywords_xlate[Ref:lower()] then |
|||
local id = Ref |
local id = Ref |
||
local namelist = {}; -- holds selected contributor, author, editor name list |
|||
if ('harv' == Ref ) then |
|||
local year = first_set ({Year, anchor_year}, 2); -- Year first for legacy citations and for YMD dates that require disambiguation |
|||
local namelist = {}; -- holds selected contributor, author, editor name list |
|||
local year = first_set ({Year, anchor_year}, 2); -- Year first for legacy citations and for YMD dates that require disambiguation |
|||
if #c > 0 then -- if there is a contributor list |
|||
namelist = c; -- select it |
|||
elseif #a > 0 then -- or an author list |
|||
namelist = a; |
|||
elseif #e > 0 then -- or an editor list |
|||
namelist = e; |
|||
end |
|||
local citeref_id |
|||
if #namelist > 0 then -- if there are names in namelist |
|||
if #namelist > 0 then -- if there are names in namelist |
|||
citeref_id = make_citeref_id (namelist, year); -- go make the CITEREF anchor |
|||
else |
|||
else |
|||
id = ''; -- unset |
|||
citeref_id = ''; -- unset |
|||
end |
|||
end |
|||
if citeref_id == Ref then |
|||
utilities.set_message ('maint_ref_duplicates_default'); |
|||
end |
|||
if 'harv' == Ref then |
|||
id = citeref_id |
|||
end |
end |
||
options.id = id; |
options.id = id; |
||
Line 3,879: | Line 3,920: | ||
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 |
||
if empty then return nil; end -- |
if empty then return nil; end -- empty deprecated parameters are treated as unknowns |
||
deprecated_parameter (name); -- parameter is deprecated but still supported |
deprecated_parameter (name); -- parameter is deprecated but still supported |
||
return true; |
|||
end |
|||
if 'discouraged' == state then |
|||
discouraged_parameter (name); -- parameter is discouraged but still supported |
|||
return true; |
return true; |
||
end |
end |
||
Line 4,071: | Line 4,116: | ||
error_text, error_state = utilities.set_message ('err_parameter_ignored_suggest', {k, param}, true); -- set the suggestion error message |
error_text, error_state = utilities.set_message ('err_parameter_ignored_suggest', {k, param}, true); -- set the suggestion error message |
||
else |
else |
||
error_text, error_state = utilities.set_message ( 'err_parameter_ignored', { |
error_text, error_state = utilities.set_message ( 'err_parameter_ignored', {k}, true ); -- suggested param not supported by this template |
||
v = ''; -- unset |
v = ''; -- unset |
||
end |
end |
||
end |
end |
||
end |
end |
||
if not utilities.is_set (error_text) then -- couldn't match with a pattern, is there an explicit suggestion? |
if not utilities.is_set (error_text) then -- couldn't match with a pattern, is there an explicit suggestion? |
||
if suggestions.suggestions[ k:lower() ] ~= nil then |
if (suggestions.suggestions[ k:lower() ] ~= nil) and validate (suggestions.suggestions[ k:lower() ], config.CitationClass) then |
||
error_text, error_state = utilities.set_message ( 'err_parameter_ignored_suggest', {k, suggestions.suggestions[ k:lower() ]}, true ); |
error_text, error_state = utilities.set_message ( 'err_parameter_ignored_suggest', {k, suggestions.suggestions[ k:lower() ]}, true ); |
||
else |
else |