Editing Module:Citation/CS1
Jump to navigation
Jump to search
Warning: You are not logged in. Your IP address will be publicly visible if you make any edits. If you log in or create an account, your edits will be attributed to your username, along with other benefits.
The edit can be undone. Please check the comparison below to verify that this is what you want to do, and then publish the changes below to finish undoing the edit.
Latest revision | Your text | ||
Line 1: | Line 1: | ||
require (' | require ('Module:No globals'); | ||
--[[--------------------------< F O R W A R D D E C L A R A T I O N S >-------------------------------------- | --[[--------------------------< F O R W A R D D E C L A R A T I O N S >-------------------------------------- | ||
Line 10: | Line 10: | ||
local utilities; -- functions in Module:Citation/CS1/Utilities | local utilities; -- functions in Module:Citation/CS1/Utilities | ||
local z = {}; -- table of tables in Module:Citation/CS1/Utilities | local z ={}; -- table of tables in Module:Citation/CS1/Utilities | ||
local identifiers; -- functions and tables in Module:Citation/CS1/Identifiers | local identifiers; -- functions and tables in Module:Citation/CS1/Identifiers | ||
Line 154: | Line 154: | ||
end | end | ||
for _, d in ipairs ( | for _, d in ipairs ({'cash', 'company', 'today', 'org'}) do -- look for single letter second level domain names for these top level domains | ||
if domain:match ('%f[%w][%w]%.' .. d) then | if domain:match ('%f[%w][%w]%.' .. d) then | ||
return true | return true | ||
Line 265: | Line 265: | ||
local function link_title_ok (link, lorig, title, torig) | local function link_title_ok (link, lorig, title, torig) | ||
local orig; | |||
if utilities.is_set (link) then -- don't bother if <param>-link doesn't have a value | if utilities.is_set (link) then -- don't bother if <param>-link doesn't have a value | ||
if not link_param_ok (link) then -- check |<param>-link= markup | if not link_param_ok (link) then -- check |<param>-link= markup | ||
Line 401: | Line 401: | ||
utilities.set_message ('err_bare_url_missing_title', {utilities.wrap_style ('parameter', source)}); | utilities.set_message ('err_bare_url_missing_title', {utilities.wrap_style ('parameter', source)}); | ||
else | else | ||
error (cfg.messages["bare_url_no_origin"]); | error (cfg.messages["bare_url_no_origin"]); | ||
end | end | ||
end | end | ||
Line 529: | Line 529: | ||
lang = script_value:match('^(%l%l%l?)%s*:%s*%S.*'); -- get the language prefix or nil if there is no script | lang = script_value:match('^(%l%l%l?)%s*:%s*%S.*'); -- get the language prefix or nil if there is no script | ||
if not utilities.is_set (lang) then | if not utilities.is_set (lang) then | ||
utilities.set_message ('err_script_parameter', {script_param, | utilities.set_message ('err_script_parameter', {script_param, 'missing title part'}); -- prefix without 'title'; add error message | ||
return ''; -- script_value was just the prefix so return empty string | return ''; -- script_value was just the prefix so return empty string | ||
end | end | ||
-- if we get this far we have prefix and script | -- if we get this far we have prefix and script | ||
name = cfg. | 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 -- is prefix a proper ISO 639-1 language code? | 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 | ||
Line 540: | Line 540: | ||
utilities.add_prop_cat ('script', {name, lang}) | utilities.add_prop_cat ('script', {name, lang}) | ||
else | else | ||
utilities.set_message ('err_script_parameter', {script_param, | utilities.set_message ('err_script_parameter', {script_param, 'unknown language code'}); -- unknown script-language; add error message | ||
end | end | ||
lang = ' lang="' .. lang .. '" '; -- convert prefix into a lang attribute | lang = ' lang="' .. lang .. '" '; -- convert prefix into a lang attribute | ||
else | else | ||
utilities.set_message ('err_script_parameter', {script_param, | utilities.set_message ('err_script_parameter', {script_param, 'invalid language code'}); -- invalid language code; add error message | ||
lang = ''; -- invalid so set lang to empty string | lang = ''; -- invalid so set lang to empty string | ||
end | end | ||
else | else | ||
utilities.set_message ('err_script_parameter', {script_param, | utilities.set_message ('err_script_parameter', {script_param, 'missing prefix'}); -- no language code prefix; add error message | ||
end | end | ||
script_value = utilities.substitute (cfg.presentation['bdi'], {lang, script_value}); -- isolate in case script is RTL | script_value = utilities.substitute (cfg.presentation['bdi'], {lang, script_value}); -- isolate in case script is RTL | ||
Line 764: | Line 764: | ||
if mw.ustring.find (v, cfg.indic_script) then -- it's ok if one of the Indic scripts | if mw.ustring.find (v, cfg.indic_script) then -- it's ok if one of the Indic scripts | ||
position = nil; -- unset position | position = nil; -- unset position | ||
elseif cfg. | elseif cfg.emoji[mw.ustring.codepoint (v, position+1)] then -- is zwj followed by a character listed in emoji{}? | ||
position = nil; -- unset position | position = nil; -- unset position | ||
end | end | ||
Line 1,105: | Line 1,105: | ||
return table.concat(initials) -- Vancouver format does not include spaces. | return table.concat(initials) -- Vancouver format does not include spaces. | ||
end | end | ||
Line 1,242: | Line 1,175: | ||
one = utilities.make_wikilink (person.link, one); -- link author/editor | one = utilities.make_wikilink (person.link, one); -- link author/editor | ||
end | end | ||
if one then -- if <one> has a value (name, mdash replacement, or mask text replacement) | if one then -- if <one> has a value (name, mdash replacement, or mask text replacement) | ||
table.insert (name_list, one); -- add it to the list of names | table.insert (name_list, one); -- add it to the list of names | ||
table.insert (name_list, sep_one); -- add the proper name-list separator | table.insert (name_list, sep_one); -- add the proper name-list separator | ||
Line 1,290: | Line 1,200: | ||
local result = table.concat (name_list); -- construct list | local result = table.concat (name_list); -- construct list | ||
if etal and utilities.is_set (result) then -- etal may be set by |display-authors=etal but we might not have a last-first list | if etal and utilities.is_set (result) then -- etal may be set by |display-authors=etal but we might not have a last-first list | ||
result = result .. sep .. cfg.messages['et al']; | result = result .. sep .. ' ' .. cfg.messages['et al']; -- we've got a last-first list and etal so add et al. | ||
end | end | ||
Line 1,406: | Line 1,316: | ||
semicolons. Escaped semicolons are ones used as part of selected HTML entities. | semicolons. Escaped semicolons are ones used as part of selected HTML entities. | ||
If the condition is met, the function adds the multiple name maintenance category. | If the condition is met, the function adds the multiple name maintenance category. | ||
returns nothing | returns nothing | ||
Line 1,419: | Line 1,321: | ||
]] | ]] | ||
local function name_has_mult_names (name, list_name | local function name_has_mult_names (name, list_name) | ||
local _, commas, semicolons, nbsps; | local _, commas, semicolons, nbsps; | ||
if utilities.is_set (name) then | if utilities.is_set (name) then | ||
_, commas = name:gsub (',', ''); -- count the number of commas | _, commas = name:gsub (',', ''); -- count the number of commas | ||
Line 1,435: | Line 1,336: | ||
-- from semicolons to 'escape' them. If additional entities are added, | -- from semicolons to 'escape' them. If additional entities are added, | ||
-- they also can be subtracted. | -- they also can be subtracted. | ||
if | if 1 < commas or 0 < (semicolons - nbsps) then | ||
utilities.set_message ('maint_mult_names', cfg.special_case_translation [list_name]); -- add a maint message | utilities.set_message ('maint_mult_names', cfg.special_case_translation [list_name]); -- add a maint message | ||
end | end | ||
Line 1,442: | Line 1,343: | ||
--[ | --[[--------------------------< I S _ G E N E R I C >---------------------------------------------------------- | ||
Compares values assigned to various | Compares values assigned to various parameter according to the string provided as <item> in the function call: | ||
'generic_names': |last=, |first=, |editor-last=, etc value against list of known generic name patterns | |||
'generic_names' | 'generic_titles': |title= | ||
'generic_titles' | Returns true when pattern matches; nil else | ||
The k/v pairs in cfg.special_case_translation[item] each contain two tables, one for English and one for another | |||
'local' language.Each of those tables contain another table that holds the string or pattern (whole or fragment) | |||
in index [1]. index [2] is a Boolean that tells string.find() or mw.ustring.find() to do plain-text search (true) | |||
Each of the | |||
[2] | |||
or a pattern search (false). The intent of all this complexity is to make these searches as fast as possible so | or a pattern search (false). The intent of all this complexity is to make these searches as fast as possible so | ||
that we don't run out of processing time on very large articles. | that we don't run out of processing time on very large articles. | ||
]] | |||
] | |||
local function is_generic (item, value | local function is_generic (item, value) | ||
local test_val; | local test_val; | ||
for _, generic_value in ipairs (cfg.special_case_translation[item]) do -- spin through the list of known generic value fragments | |||
test_val = generic_value['en'][2] and value:lower() or value; -- when set to 'true', plaintext search using lowercase value | |||
if test_val:find (generic_value['en'][1], 1, generic_value['en'][2]) then | |||
return true; -- found English generic value so done | |||
elseif generic_value['local'] then -- to keep work load down, generic_<value>['local'] should be nil except when there is a local version of the generic value | |||
test_val = generic_value['local'][2] and mw.ustring.lower(value) or value; -- when set to 'true', plaintext search using lowercase value | |||
if mw.ustring.find (test_val, generic_value['local'][1], 1, generic_value['local'][2]) then -- mw.ustring() because might not be Latin script | |||
return true; -- found local generic value so done | |||
end | end | ||
end | end | ||
Line 1,530: | Line 1,406: | ||
if not accept_name then -- <last> not wrapped in accept-as-written markup | if not accept_name then -- <last> not wrapped in accept-as-written markup | ||
name_has_mult_names (last, list_name); -- check for multiple names in the parameter | name_has_mult_names (last, list_name); -- check for multiple names in the parameter (last only) | ||
name_is_numeric (last, list_name); -- check for names that are composed of digits and punctuation | name_is_numeric (last, list_name); -- check for names that are composed of digits and punctuation | ||
name_is_generic (last, last_alias); -- check for names found in the generic names list | name_is_generic (last, last_alias); -- check for names found in the generic names list | ||
Line 1,540: | Line 1,416: | ||
if not accept_name then -- <first> not wrapped in accept-as-written markup | if not accept_name then -- <first> not wrapped in accept-as-written markup | ||
name_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 | ||
name_is_generic (first, first_alias); -- check for names found in the generic names list | name_is_generic (first, first_alias); -- check for names found in the generic names list | ||
Line 1,594: | Line 1,469: | ||
link, link_alias = utilities.select_one ( args, cfg.aliases[list_name .. '-Link'], 'err_redundant_parameters', i ); | link, link_alias = utilities.select_one ( args, cfg.aliases[list_name .. '-Link'], 'err_redundant_parameters', i ); | ||
mask = utilities.select_one ( args, cfg.aliases[list_name .. '-Mask'], 'err_redundant_parameters', i ); | mask = utilities.select_one ( args, cfg.aliases[list_name .. '-Mask'], 'err_redundant_parameters', i ); | ||
last, etal = name_has_etal (last, etal, false, last_alias); -- find and remove variations on et al. | last, etal = name_has_etal (last, etal, false, last_alias); -- find and remove variations on et al. | ||
first, etal = name_has_etal (first, etal, false, first_alias); -- find and remove variations on et al. | first, etal = name_has_etal (first, etal, false, first_alias); -- find and remove variations on et al. | ||
Line 1,654: | Line 1,512: | ||
This function looks for: | This function looks for: | ||
<lang_param> as a tag in cfg. | <lang_param> as a tag in cfg.lang_code_remap{} | ||
<lang_param> as a name in cfg.lang_name_remap{} | <lang_param> as a name in cfg.lang_name_remap{} | ||
Line 1,663: | Line 1,521: | ||
and look for the new <lang_param> in cfg.mw_languages_by_tag_t{} | and look for the new <lang_param> in cfg.mw_languages_by_tag_t{} | ||
on success, | on success, return name and matching tag; on failure return nil | ||
]] | ]] | ||
Line 1,672: | Line 1,530: | ||
local tag; | local tag; | ||
name = cfg. | name = cfg.lang_code_remap[lang_param_lc]; -- assume <lang_param_lc> is a tag; attempt to get remapped language name | ||
if name then -- when <name>, <lang_param> is a tag for a remapped language name | if name then -- when <name>, <lang_param> is a tag for a remapped language name | ||
return name, | return name, lang_param; -- so return <name> from remap and <lang_param> | ||
end | end | ||
tag = lang_param_lc:match ('^(%a%a%a?)%-.*'); -- still assuming that <lang_param_lc> is a tag; strip script, region, variant subtags | tag = lang_param_lc:match ('^(%a%a%a?)%-.*'); -- still assuming that <lang_param_lc> is a tag; strip script, region, variant subtags | ||
name = cfg. | name = cfg.lang_code_remap[tag]; -- attempt to get remapped language name with language subtag only | ||
if name then -- when <name>, <tag> is a tag for a remapped language name | if name then -- when <name>, <tag> is a tag for a remapped language name | ||
return name, tag; -- so return <name> from remap and <tag> | return name, tag; -- so return <name> from remap and <tag> | ||
Line 1,696: | Line 1,554: | ||
if name then | if name then | ||
return name, | return name, lang_param; -- <lang_param_lc> is a tag so return <name> and the tag | ||
end | end | ||
Line 1,743: | Line 1,601: | ||
for _, lang in ipairs (names_t) do -- reuse lang here because we don't yet know if lang is a language name or a language tag | for _, lang in ipairs (names_t) do -- reuse lang here because we don't yet know if lang is a language name or a language tag | ||
name, tag = name_tag_get (lang); -- attempt to get name/tag pair for <lang> | name, tag = name_tag_get (lang); -- attempt to get name/tag pair for <lang> | ||
if utilities.is_set (tag) then | if utilities.is_set (tag) then | ||
lang_subtag = tag:gsub ('^(%a%a%a?)%-.*', '%1'); | lang_subtag = tag:lower():gsub ('^(%a%a%a?)%-.*', '%1'); -- for categorization, strip any IETF-like tags from language tag | ||
if cfg.this_wiki_code ~= lang_subtag then -- when the language is not the same as this wiki's language | if cfg.this_wiki_code ~= lang_subtag then -- when the language is not the same as this wiki's language | ||
if 2 == lang_subtag:len() then -- and is a two-character tag | if 2 == lang_subtag:len() then -- and is a two-character tag | ||
utilities.add_prop_cat ('foreign-lang-source', {name, | utilities.add_prop_cat ('foreign-lang-source', {name, lang_subtag}, lang_subtag); -- categorize it; tag appended to allow for multiple language categorization | ||
else -- or is a recognized language (but has a three-character tag) | else -- or is a recognized language (but has a three-character tag) | ||
utilities.add_prop_cat ('foreign-lang-source-2', {lang_subtag}, lang_subtag); -- categorize it differently TODO: support multiple three-character tag categories per cs1|2 template? | utilities.add_prop_cat ('foreign-lang-source-2', {lang_subtag}, lang_subtag); -- categorize it differently TODO: support multiple three-character tag categories per cs1|2 template? | ||
Line 1,798: | Line 1,656: | ||
return cfg.presentation['sep_' .. mode], postscript; | return cfg.presentation['sep_' .. mode], postscript; | ||
end | end | ||
--[[--------------------------< S E T _ S T Y L E >----------------------------- | --[[--------------------------< S E T _ S T Y L E >----------------------------- | ||
Line 1,889: | Line 1,746: | ||
inputs: | inputs: | ||
max: A['DisplayAuthors'] or A['DisplayEditors'] | max: A['DisplayAuthors'] or A['DisplayEditors']; a number or some flavor of etal | ||
count: #a or #e | count: #a or #e | ||
list_name: 'authors' or 'editors' | list_name: 'authors' or 'editors' | ||
etal: author_etal or editor_etal | etal: author_etal or editor_etal | ||
]] | ]] | ||
Line 1,908: | Line 1,760: | ||
elseif max:match ('^%d+$') then -- if is a string of numbers | elseif max:match ('^%d+$') then -- if is a string of numbers | ||
max = tonumber (max); -- make it a number | max = tonumber (max); -- make it a number | ||
if | if max >= count then -- if |display-xxxxors= value greater than or equal to number of authors/editors | ||
utilities.set_message ('err_disp_name', {param, max}); -- add error message | utilities.set_message ('err_disp_name', {param, max}); -- add error message | ||
max = nil; | max = nil; | ||
end | end | ||
else -- not a valid keyword or number | else -- not a valid keyword or number | ||
utilities.set_message ('err_disp_name', {param, max}); | utilities.set_message ('err_disp_name', {param, max}); -- 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 2,211: | Line 2,063: | ||
--[[-------------------------< F O R M A T _ V O L U M E _ I S S U E > | --[[-------------------------< F O R M A T _ V O L U M E _ I S S U E >---------------------------------------- | ||
returns the concatenation of the formatted volume and issue | returns the concatenation of the formatted volume and issue parameters as a single string; or formatted volume | ||
string; or formatted volume or formatted issue, or an empty string if neither are set. | or formatted issue, or an empty string if neither are set. | ||
]] | ]] | ||
local function format_volume_issue (volume, issue | local function format_volume_issue (volume, issue, cite_class, origin, sepc, lower) | ||
if not utilities.is_set (volume) and not utilities.is_set (issue | if not utilities.is_set (volume) and not utilities.is_set (issue) then | ||
return ''; | return ''; | ||
end | end | ||
Line 2,235: | Line 2,087: | ||
if is_journal then -- journal-style formatting | if is_journal then -- journal-style formatting | ||
local vol = ''; | local vol = ''; | ||
if utilities.is_set (volume) then | if utilities.is_set (volume) then | ||
if is_numeric_vol then -- |volume= value all digits or all uppercase Roman numerals? | if is_numeric_vol then -- |volume= value all digits or all uppercase Roman numerals? | ||
Line 2,245: | Line 2,097: | ||
end | end | ||
end | end | ||
if utilities.is_set (issue) then | |||
return vol .. utilities.substitute (cfg.messages['j-issue'], issue); | |||
end | |||
return vol; | return vol; | ||
end | end | ||
Line 2,252: | Line 2,105: | ||
if 'podcast' == cite_class and utilities.is_set (issue) then | if 'podcast' == cite_class and utilities.is_set (issue) then | ||
return wrap_msg ('issue', {sepc, issue}, lower); | return wrap_msg ('issue', {sepc, issue}, lower); | ||
end | end | ||
Line 2,429: | Line 2,274: | ||
for timestamp errors when the timestamp has a wildcard, return the URL unmodified | for timestamp errors when the timestamp has a wildcard, return the URL unmodified | ||
for timestamp errors when the timestamp does not have a wildcard, return with timestamp limited to six digits plus wildcard (/yyyymm*/) | for timestamp errors when the timestamp does not have a wildcard, return with timestamp limited to six digits plus wildcard (/yyyymm*/) | ||
]=] | ]=] | ||
Line 2,440: | Line 2,281: | ||
local path, timestamp, flag; -- portions of the archive.org URL | local path, timestamp, flag; -- portions of the archive.org URL | ||
if (not url:match('//web%.archive%.org/')) and (not url:match('//liveweb%.archive%.org/')) then -- also deprecated liveweb Wayback machine URL | if (not url:match('//web%.archive%.org/')) and (not url:match('//liveweb%.archive%.org/')) then -- also deprecated liveweb Wayback machine URL | ||
return url, date; -- not an archive.org archive, return ArchiveURL and ArchiveDate | return url, date; -- not an archive.org archive, return ArchiveURL and ArchiveDate | ||
Line 2,474: | Line 2,310: | ||
err_msg = cfg.err_msg_supl.flag; | err_msg = cfg.err_msg_supl.flag; | ||
else | else | ||
return url, date | return url, date; -- return ArchiveURL and ArchiveDate | ||
end | end | ||
end | end | ||
Line 2,481: | Line 2,317: | ||
if is_preview_mode then | if is_preview_mode then | ||
return url, date | return url, date; -- preview mode so return ArchiveURL and ArchiveDate | ||
else | else | ||
return '', ''; -- return empty strings for ArchiveURL and ArchiveDate | return '', ''; -- return empty strings for ArchiveURL and ArchiveDate | ||
Line 2,548: | Line 2,384: | ||
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 | 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,567: | Line 2,393: | ||
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, | 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 | ||
Authors = A['Authors']; -- use content of |authors= | Authors = A['Authors']; -- use content of |authors= | ||
Line 2,623: | Line 2,449: | ||
local TitleLink = A['TitleLink']; | local TitleLink = A['TitleLink']; | ||
local auto_select = ''; | local auto_select = ''; -- default is auto | ||
local accept_link; | local accept_link; | ||
TitleLink, accept_link = utilities.has_accept_as_written (TitleLink, true); -- test for accept-this-as-written markup | TitleLink, accept_link = utilities.has_accept_as_written (TitleLink, true); -- test for accept-this-as-written markup | ||
Line 2,640: | Line 2,466: | ||
local Periodical = A['Periodical']; | local Periodical = A['Periodical']; | ||
local Periodical_origin = | local Periodical_origin = ''; | ||
if utilities.is_set (Periodical) then | if utilities.is_set (Periodical) then | ||
Periodical_origin = A:ORIGIN('Periodical'); -- get the name of the periodical parameter | |||
local i; | local i; | ||
Periodical, i = utilities.strip_apostrophe_markup (Periodical); -- strip apostrophe markup so that metadata isn't contaminated | Periodical, i = utilities.strip_apostrophe_markup (Periodical); -- strip apostrophe markup so that metadata isn't contaminated | ||
Line 2,674: | Line 2,478: | ||
if 'mailinglist' == config.CitationClass then -- special case for {{cite mailing list}} | if 'mailinglist' == config.CitationClass then -- special case for {{cite mailing list}} | ||
if utilities.is_set (Periodical) and utilities.is_set (A ['MailingList']) then -- both set emit an error TODO: make a function for this and similar? | if utilities.is_set (Periodical) and utilities.is_set (A ['MailingList']) then -- both set emit an error TODO: make a function for this and similar? | ||
utilities.set_message ('err_redundant_parameters', {utilities.wrap_style ('parameter', Periodical_origin) .. | utilities.set_message ('err_redundant_parameters', {utilities.wrap_style ('parameter', Periodical_origin) .. ' and ' .. utilities.wrap_style ('parameter', 'mailinglist')}); | ||
end | end | ||
Line 2,680: | Line 2,484: | ||
Periodical_origin = A:ORIGIN('MailingList'); | Periodical_origin = A:ORIGIN('MailingList'); | ||
end | end | ||
local ScriptPeriodical = A['ScriptPeriodical']; | |||
-- web and news not tested for now because of | -- web and news not tested for now because of | ||
Line 2,692: | Line 2,498: | ||
local Volume; | local Volume; | ||
local ScriptPeriodical_origin = A:ORIGIN('ScriptPeriodical'); | |||
if 'citation' == config.CitationClass then | if 'citation' == config.CitationClass then | ||
if utilities.is_set (Periodical) then | if utilities.is_set (Periodical) then | ||
if not utilities.in_array (Periodical_origin, | if not utilities.in_array (Periodical_origin, {'website', 'mailinglist'}) then -- {{citation}} does not render volume for these 'periodicals' --TODO: move 'array' to ~/Configuration | ||
Volume = A['Volume']; -- but does for all other 'periodicals' | Volume = A['Volume']; -- but does for all other 'periodicals' | ||
end | end | ||
Line 2,712: | Line 2,518: | ||
local Issue; | local Issue; | ||
if 'citation' == config.CitationClass then | if 'citation' == config.CitationClass then | ||
if utilities.is_set (Periodical) and utilities.in_array (Periodical_origin, | if utilities.is_set (Periodical) and utilities.in_array (Periodical_origin, {'journal', 'magazine', 'newspaper', 'periodical', 'work'}) or -- {{citation}} renders issue for these 'periodicals'--TODO: move 'array' to ~/Configuration | ||
Issue = utilities.hyphen_to_dash (A['Issue']); | utilities.is_set (ScriptPeriodical) and utilities.in_array (ScriptPeriodical_origin, {'script-journal', 'script-magazine', 'script-newspaper', 'script-periodical', 'script-work'}) then -- and these 'script-periodicals' | ||
Issue = utilities.hyphen_to_dash (A['Issue']); | |||
end | end | ||
elseif utilities.in_array (config.CitationClass, cfg.templates_using_issue) then -- conference & map books do not support issue; {{citation}} listed here because included in settings table | elseif utilities.in_array (config.CitationClass, cfg.templates_using_issue) then -- conference & map books do not support issue; {{citation}} listed here because included in settings table | ||
Line 2,720: | Line 2,527: | ||
end | end | ||
end | end | ||
extra_text_in_vol_iss_check (Issue, A:ORIGIN ('Issue'), 'i'); | extra_text_in_vol_iss_check (Issue, A:ORIGIN ('Issue'), 'i'); | ||
Line 2,732: | Line 2,532: | ||
local Pages; | local Pages; | ||
local At; | local At; | ||
if not utilities.in_array (config.CitationClass, cfg.templates_not_using_page) then | |||
if not utilities.in_array (config.CitationClass, cfg.templates_not_using_page) then | |||
Page = A['Page']; | Page = A['Page']; | ||
Pages = utilities.hyphen_to_dash (A['Pages']); | Pages = utilities.hyphen_to_dash (A['Pages']); | ||
At = A['At']; | At = A['At']; | ||
end | end | ||
Line 2,748: | Line 2,544: | ||
local PublisherName = A['PublisherName']; | local PublisherName = A['PublisherName']; | ||
local PublisherName_origin = A:ORIGIN('PublisherName'); | local PublisherName_origin = A:ORIGIN('PublisherName'); | ||
if utilities.is_set ( | if utilities.is_set (PublisherName) then | ||
local i = 0; | local i = 0; | ||
PublisherName, i = utilities.strip_apostrophe_markup (PublisherName); -- strip apostrophe markup so that metadata isn't contaminated; publisher is never italicized | PublisherName, i = utilities.strip_apostrophe_markup (PublisherName); -- strip apostrophe markup so that metadata isn't contaminated; publisher is never italicized | ||
if i | if i then -- non-zero when markup was stripped so emit an error message | ||
utilities.set_message ('err_apostrophe_markup', {PublisherName_origin}); | utilities.set_message ('err_apostrophe_markup', {PublisherName_origin}); | ||
end | end | ||
end | end | ||
Line 2,764: | Line 2,556: | ||
if 'newsgroup' == config.CitationClass then | if 'newsgroup' == config.CitationClass then | ||
if utilities.is_set ( | if utilities.is_set (PublisherName) then -- general use parameter |publisher= not allowed in cite newsgroup | ||
utilities.set_message ('err_parameter_ignored', {PublisherName_origin}); | utilities.set_message ('err_parameter_ignored', {PublisherName_origin}); | ||
end | end | ||
Line 2,797: | Line 2,589: | ||
-- check this page to see if it is in one of the namespaces that cs1 is not supposed to add to the error categories | -- check this page to see if it is in one of the namespaces that cs1 is not supposed to add to the error categories | ||
if not utilities.is_set (no_tracking_cats) then -- ignore if we are already not going to categorize this page | if not utilities.is_set (no_tracking_cats) then -- ignore if we are already not going to categorize this page | ||
if cfg.uncategorized_namespaces | if utilities.in_array (this_page.nsText, cfg.uncategorized_namespaces) then | ||
no_tracking_cats = "true"; -- set no_tracking_cats | no_tracking_cats = "true"; -- set no_tracking_cats | ||
end | end | ||
Line 2,826: | Line 2,618: | ||
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 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 ChapterURL_origin = A:ORIGIN('ChapterURL'); -- get name of parameter that holds ChapterURL | ||
Line 2,841: | Line 2,633: | ||
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 |title= then map |title= to |article= and |encyclopedia= to |title= | ||
|encyclopedia= and |article= then map |encyclopedia= to |title= | |encyclopedia= and |article= then map |encyclopedia= to |title= | ||
|trans-title= maps to |trans-chapter= when |title= is re-mapped | |trans-title= maps to |trans-chapter= when |title= is re-mapped | ||
Line 2,861: | Line 2,653: | ||
if ('encyclopaedia' == config.CitationClass) or ('citation' == config.CitationClass and utilities.is_set (Encyclopedia)) then | if ('encyclopaedia' == config.CitationClass) or ('citation' == config.CitationClass and utilities.is_set (Encyclopedia)) then | ||
if utilities.is_set (Periodical) and utilities.is_set (Encyclopedia) then -- when both | if utilities.is_set (Periodical) and utilities.is_set (Encyclopedia) then -- when both set emit an error TODO: make a function for this and similar? | ||
utilities.set_message (' | utilities.set_message ('err_redundant_parameters', {utilities.wrap_style ('parameter', A:ORIGIN ('Encyclopedia')) .. ' and ' .. utilities.wrap_style ('parameter', Periodical_origin)}); | ||
end | end | ||
if utilities.is_set (Encyclopedia) then | if utilities.is_set (Encyclopedia) then | ||
Periodical = Encyclopedia; -- error or no, set Periodical to Encyclopedia | Periodical = Encyclopedia; -- error or no, set Periodical to Encyclopedia; allow periodical without encyclopedia | ||
Periodical_origin = A:ORIGIN ('Encyclopedia'); | Periodical_origin = A:ORIGIN ('Encyclopedia'); | ||
end | |||
if utilities.is_set (Periodical) then -- Periodical is set when |encyclopedia= is set | |||
if utilities.is_set (Title) or utilities.is_set (ScriptTitle) then | if utilities.is_set (Title) or utilities.is_set (ScriptTitle) then | ||
if not utilities.is_set (Chapter) then | if not utilities.is_set (Chapter) then | ||
Chapter = Title; -- |encyclopedia= and |title= are set so map |title= to |article= and |encyclopedia= to |title= | Chapter = Title; -- |encyclopedia= and |title= are set so map |title= to |article= and |encyclopedia= to |title= | ||
ScriptChapter = ScriptTitle; | ScriptChapter = ScriptTitle; | ||
ScriptChapter_origin = A:ORIGIN('ScriptTitle') | ScriptChapter_origin = A:ORIGIN('ScriptTitle') | ||
Line 2,893: | Line 2,687: | ||
end | end | ||
elseif utilities.is_set (Chapter) or utilities.is_set (ScriptChapter) then -- |title= not set | elseif utilities.is_set (Chapter) or utilities.is_set (ScriptChapter) then -- |title= not set | ||
Title = Periodical; -- |encyclopedia= set and |article= set so map |encyclopedia= to |title= | Title = Periodical; -- |encyclopedia= set and |article= set so map |encyclopedia= to |title= | ||
Periodical = ''; -- redundant so unset | Periodical = ''; -- redundant so unset | ||
end | end | ||
Line 2,906: | Line 2,700: | ||
ID = A['Number']; -- yes, use it | ID = A['Number']; -- yes, use it | ||
else -- ID has a value so emit error message | else -- ID has a value so emit error message | ||
utilities.set_message ('err_redundant_parameters', {utilities.wrap_style ('parameter', 'id') .. | utilities.set_message ('err_redundant_parameters', {utilities.wrap_style ('parameter', 'id') .. ' and ' .. utilities.wrap_style ('parameter', 'number')}); | ||
end | end | ||
end | end | ||
Line 2,939: | Line 2,733: | ||
-- CS1/2 mode | -- CS1/2 mode | ||
local | local Mode = is_valid_parameter_value (A['Mode'], A:ORIGIN('Mode'), cfg.keywords_lists['mode'], ''); | ||
-- separator character and postscript | -- separator character and postscript | ||
local sepc, PostScript = set_style (Mode:lower(), A['PostScript'], config.CitationClass); | local sepc, PostScript = set_style (Mode:lower(), A['PostScript'], config.CitationClass); | ||
Line 2,962: | Line 2,746: | ||
if config.CitationClass == "map" then | if config.CitationClass == "map" then | ||
if utilities.is_set (Chapter) then --TODO: make a function for this and similar? | if utilities.is_set (Chapter) then --TODO: make a function for this and similar? | ||
utilities.set_message ('err_redundant_parameters', {utilities.wrap_style ('parameter', 'map') .. | utilities.set_message ('err_redundant_parameters', {utilities.wrap_style ('parameter', 'map') .. ' and ' .. utilities.wrap_style ('parameter', Chapter_origin)}); -- add error message | ||
end | end | ||
Chapter = A['Map']; | Chapter = A['Map']; | ||
Line 3,005: | Line 2,789: | ||
if utilities.is_set (Season) and utilities.is_set (SeriesNumber) then -- these are mutually exclusive so if both are set TODO: make a function for this and similar? | if utilities.is_set (Season) and utilities.is_set (SeriesNumber) then -- these are mutually exclusive so if both are set TODO: make a function for this and similar? | ||
utilities.set_message ('err_redundant_parameters', {utilities.wrap_style ('parameter', 'season') .. | utilities.set_message ('err_redundant_parameters', {utilities.wrap_style ('parameter', 'season') .. ' and ' .. utilities.wrap_style ('parameter', 'seriesno')}); -- add error message | ||
SeriesNumber = ''; -- unset; prefer |season= over |seriesno= | SeriesNumber = ''; -- unset; prefer |season= over |seriesno= | ||
end | end | ||
Line 3,022: | Line 2,806: | ||
ChapterUrlAccess = UrlAccess; | ChapterUrlAccess = UrlAccess; | ||
ChapterURL_origin = URL_origin; | ChapterURL_origin = URL_origin; | ||
Title = Series; -- promote series to title | Title = Series; -- promote series to title | ||
TitleLink = SeriesLink; | TitleLink = SeriesLink; | ||
Line 3,036: | Line 2,819: | ||
TransTitle = ''; | TransTitle = ''; | ||
ScriptTitle = ''; | ScriptTitle = ''; | ||
else -- now oddities that are cite serial | else -- now oddities that are cite serial | ||
Line 3,052: | Line 2,834: | ||
local TitleType = A['TitleType']; | local TitleType = A['TitleType']; | ||
local Degree = A['Degree']; | local Degree = A['Degree']; | ||
if utilities.in_array (config.CitationClass, {'AV-media-notes | if utilities.in_array (config.CitationClass, {'AV-media-notes', 'interview', 'mailinglist', 'map', 'podcast', 'pressrelease', 'report', 'speech', 'techreport', 'thesis'}) then | ||
TitleType = set_titletype (config.CitationClass, TitleType); | TitleType = set_titletype (config.CitationClass, TitleType); | ||
if utilities.is_set (Degree) and "Thesis" == TitleType then -- special case for cite thesis | if utilities.is_set (Degree) and "Thesis" == TitleType then -- special case for cite thesis | ||
Line 3,101: | Line 2,883: | ||
local ArchiveDate; | local ArchiveDate; | ||
local ArchiveFormat = A['ArchiveFormat']; | local ArchiveFormat = A['ArchiveFormat']; | ||
ArchiveURL, ArchiveDate = archive_url_check (A['ArchiveURL'], A['ArchiveDate']) | |||
ArchiveURL, ArchiveDate | |||
ArchiveFormat = style_format (ArchiveFormat, ArchiveURL, 'archive-format', 'archive-url'); | 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 | 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 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 COinS_date = {}; -- holds date info extracted from |date= for the COinS metadata by Module:Date verification | ||
local DoiBroken = A['DoiBroken']; | local DoiBroken = A['DoiBroken']; | ||
Line 3,123: | Line 2,905: | ||
['doi-broken-date'] = {val = DoiBroken, name = A:ORIGIN ('DoiBroken')}, | ['doi-broken-date'] = {val = DoiBroken, name = A:ORIGIN ('DoiBroken')}, | ||
['pmc-embargo-date'] = {val = Embargo, name = A:ORIGIN ('Embargo')}, | ['pmc-embargo-date'] = {val = Embargo, name = A:ORIGIN ('Embargo')}, | ||
['lay-date'] = {val = LayDate, name = A:ORIGIN ('LayDate')}, | |||
['publication-date'] = {val = PublicationDate, name = A:ORIGIN ('PublicationDate')}, | ['publication-date'] = {val = PublicationDate, name = A:ORIGIN ('PublicationDate')}, | ||
['year'] = {val = Year, name = A:ORIGIN ('Year')}, | ['year'] = {val = Year, name = A:ORIGIN ('Year')}, | ||
Line 3,164: | Line 2,946: | ||
Date = date_parameters_list['date'].val; | Date = date_parameters_list['date'].val; | ||
DoiBroken = date_parameters_list['doi-broken-date'].val; | DoiBroken = date_parameters_list['doi-broken-date'].val; | ||
LayDate = date_parameters_list['lay-date'].val; | |||
PublicationDate = date_parameters_list['publication-date'].val; | PublicationDate = date_parameters_list['publication-date'].val; | ||
end | end | ||
else | else | ||
Line 3,175: | Line 2,953: | ||
end | end | ||
end -- end of do | end -- end of do | ||
local ID_list = {}; -- sequence table of rendered identifiers | local ID_list = {}; -- sequence table of rendered identifiers | ||
Line 3,205: | Line 2,966: | ||
ID_list, ID_list_coins = identifiers.identifier_lists_get (args, {DoiBroken = DoiBroken, ASINTLD = A['ASINTLD'], Embargo = Embargo, Class = Class}, ID_support); | ID_list, ID_list_coins = identifiers.identifier_lists_get (args, {DoiBroken = DoiBroken, ASINTLD = A['ASINTLD'], Embargo = Embargo, Class = Class}, ID_support); | ||
-- Account for the oddities that are {{cite arxiv}}, {{cite biorxiv}}, {{cite citeseerx | -- Account for the oddities that are {{cite arxiv}}, {{cite biorxiv}}, {{cite citeseerx}}, {{cite ssrn}}, before generation of COinS data. | ||
if utilities.in_array (config.CitationClass, whitelist. | if utilities.in_array (config.CitationClass, whitelist.preprint_template_list) then | ||
if not utilities.is_set (ID_list_coins[config.CitationClass:upper()]) then -- |arxiv= or |eprint= required for cite arxiv; |biorxiv= & |citeseerx= required for their templates | |||
utilities.set_message ('err_' .. config.CitationClass .. '_missing'); -- add error message | |||
end | end | ||
Periodical = ({['arxiv'] = 'arXiv', ['biorxiv'] = 'bioRxiv', ['citeseerx'] = 'CiteSeerX | Periodical = ({['arxiv'] = 'arXiv', ['biorxiv'] = 'bioRxiv', ['citeseerx'] = 'CiteSeerX', ['ssrn'] = 'Social Science Research Network'})[config.CitationClass]; | ||
end | end | ||
Line 3,231: | Line 2,991: | ||
end | end | ||
if utilities.is_set (URL) | if utilities.is_set (URL) and utilities.is_set (AccessDate) then -- access date requires |url=; identifier-created URL is not |url= | ||
utilities.set_message ('err_accessdate_missing_url'); -- add an error message | |||
AccessDate = ''; -- unset | |||
end | end | ||
end | end | ||
Line 3,276: | Line 3,029: | ||
end | end | ||
local QuotePage = A['QuotePage']; | |||
local QuotePages = utilities.hyphen_to_dash (A['QuotePages']); | |||
-- this is the function call to COinS() | -- this is the function call to COinS() | ||
local OCinSoutput = metadata.COinS({ | local OCinSoutput = metadata.COinS({ | ||
Line 3,284: | Line 3,040: | ||
['Title'] = metadata.make_coins_title (coins_title, ScriptTitle), -- Title and ScriptTitle stripped of bold / italic / accept-as-written markup | ['Title'] = metadata.make_coins_title (coins_title, ScriptTitle), -- Title and ScriptTitle stripped of bold / italic / accept-as-written markup | ||
['PublicationPlace'] = PublicationPlace, | ['PublicationPlace'] = PublicationPlace, | ||
['Date'] = COinS_date.rftdate, -- COinS_date | ['Date'] = COinS_date.rftdate, -- COinS_date has correctly formatted date if Date is valid; | ||
['Season'] = COinS_date.rftssn, | ['Season'] = COinS_date.rftssn, | ||
['Quarter'] = COinS_date.rftquarter, | ['Quarter'] = COinS_date.rftquarter, | ||
['Chron'] = COinS_date.rftchron, | ['Chron'] = COinS_date.rftchron or (not COinS_date.rftdate and Date) or '', -- chron but if not set and invalid date format use Date; keep this last bit? | ||
['Series'] = Series, | ['Series'] = Series, | ||
['Volume'] = Volume, | ['Volume'] = Volume, | ||
['Issue'] = Issue, | ['Issue'] = Issue, | ||
['Pages'] = coins_pages or metadata.get_coins_pages (first_set ({Sheet, Sheets, Page, Pages, At, QuotePage, QuotePages}, 7)), -- pages stripped of external links | ['Pages'] = coins_pages or metadata.get_coins_pages (first_set ({Sheet, Sheets, Page, Pages, At, QuotePage, QuotePages}, 7)), -- pages stripped of external links | ||
['Edition'] = Edition, | ['Edition'] = Edition, | ||
Line 3,301: | Line 3,056: | ||
}, config.CitationClass); | }, config.CitationClass); | ||
-- Account for the oddities that are {{cite arxiv}}, {{cite biorxiv}}, {{cite citeseerx | -- Account for the oddities that are {{cite arxiv}}, {{cite biorxiv}}, {{cite citeseerx}}, and {{cite ssrn}} AFTER generation of COinS data. | ||
if utilities.in_array (config.CitationClass, whitelist. | if utilities.in_array (config.CitationClass, whitelist.preprint_template_list) then -- we have set rft.jtitle in COinS to arXiv, bioRxiv, CiteSeerX, or ssrn now unset so it isn't displayed | ||
Periodical = ''; -- periodical not allowed in these templates; if article has been published, use cite journal | Periodical = ''; -- periodical not allowed in these templates; if article has been published, use cite journal | ||
end | end | ||
Line 3,330: | Line 3,085: | ||
local last_first_list; | local last_first_list; | ||
local control = { | local control = { | ||
format = NameListStyle, -- empty string | format = NameListStyle, -- empty string or 'vanc' | ||
maximum = nil, -- as if display-authors or display-editors not set | maximum = nil, -- as if display-authors or display-editors not set | ||
mode = Mode | mode = Mode | ||
Line 3,336: | Line 3,091: | ||
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, A:ORIGIN ('DisplayEditors')); | |||
Editors, EditorCount = list_people (control, e, editor_etal); | Editors, EditorCount = list_people (control, e, editor_etal); | ||
Line 3,353: | Line 3,099: | ||
end | end | ||
do -- now do interviewers | do -- now do interviewers | ||
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, 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, 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, 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); | ||
Line 3,426: | Line 3,137: | ||
-- 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 (utilities.in_array (config.CitationClass, {'web', 'news', 'journal', 'magazine', 'pressrelease', 'podcast', 'newsgroup', 'arxiv', 'biorxiv', 'citeseerx | if not (utilities.in_array (config.CitationClass, {'web', 'news', 'journal', 'magazine', 'pressrelease', 'podcast', 'newsgroup', 'arxiv', 'biorxiv', 'citeseerx', 'ssrn'}) or | ||
('citation' == config.CitationClass and (utilities.is_set (Periodical) or utilities.is_set (ScriptPeriodical)) and not utilities.is_set (Encyclopedia))) then | ('citation' == config.CitationClass and (utilities.is_set (Periodical) or utilities.is_set (ScriptPeriodical)) and not utilities.is_set (Encyclopedia))) then | ||
ChapterFormat = style_format (ChapterFormat, ChapterURL, 'chapter-format', 'chapter-url'); | ChapterFormat = style_format (ChapterFormat, ChapterURL, 'chapter-format', 'chapter-url'); | ||
Line 3,479: | Line 3,190: | ||
end | end | ||
if utilities.in_array (config.CitationClass, {'web', 'news', 'journal', 'magazine', 'pressrelease', 'podcast', 'newsgroup', 'arxiv', 'biorxiv', 'citeseerx | if utilities.in_array (config.CitationClass, {'web', 'news', 'journal', 'magazine', 'pressrelease', 'podcast', 'newsgroup', 'arxiv', 'biorxiv', 'citeseerx', 'ssrn'}) or -- if any of the 'periodical' cites except encyclopedia | ||
('citation' == config.CitationClass and (utilities.is_set (Periodical) or utilities.is_set (ScriptPeriodical)) and not utilities.is_set (Encyclopedia)) then | ('citation' == config.CitationClass and (utilities.is_set (Periodical) or utilities.is_set (ScriptPeriodical)) and not utilities.is_set (Encyclopedia)) then | ||
local chap_param; | local chap_param; | ||
Line 3,552: | Line 3,263: | ||
end | end | ||
if (not plain_title) and (utilities.in_array (config.CitationClass, {'web', 'news', 'journal', 'magazine | if (not plain_title) and (utilities.in_array (config.CitationClass, {'web', 'news', 'journal', 'magazine', 'pressrelease', 'podcast', 'newsgroup', 'mailinglist', 'interview', 'arxiv', 'biorxiv', 'citeseerx', 'ssrn'}) or | ||
('citation' == config.CitationClass and (utilities.is_set (Periodical) or utilities.is_set (ScriptPeriodical)) and not utilities.is_set (Encyclopedia)) or | ('citation' == config.CitationClass and (utilities.is_set (Periodical) or utilities.is_set (ScriptPeriodical)) and not utilities.is_set (Encyclopedia)) or | ||
('map' == config.CitationClass and (utilities.is_set (Periodical) or utilities.is_set (ScriptPeriodical)))) then -- special case for cite map when the map is in a periodical treat as an article | ('map' == config.CitationClass and (utilities.is_set (Periodical) or utilities.is_set (ScriptPeriodical)))) then -- special case for cite map when the map is in a periodical treat as an article | ||
Line 3,633: | Line 3,344: | ||
if utilities.is_set (Minutes) then | if utilities.is_set (Minutes) then | ||
if utilities.is_set (Time) then --TODO: make a function for this and similar? | if utilities.is_set (Time) then --TODO: make a function for this and similar? | ||
utilities.set_message ('err_redundant_parameters', {utilities.wrap_style ('parameter', 'minutes') .. | utilities.set_message ('err_redundant_parameters', {utilities.wrap_style ('parameter', 'minutes') .. ' and ' .. utilities.wrap_style ('parameter', 'time')}); | ||
end | end | ||
Position = " " .. Minutes .. " " .. cfg.messages['minutes']; | Position = " " .. Minutes .. " " .. cfg.messages['minutes']; | ||
Line 3,705: | Line 3,416: | ||
local Agency = A['Agency']; | local Agency = A['Agency']; | ||
Agency = utilities.is_set (Agency) and wrap_msg ('agency', {sepc, Agency}) or ""; | Agency = utilities.is_set (Agency) and wrap_msg ('agency', {sepc, Agency}) or ""; | ||
Volume = format_volume_issue (Volume, Issue | Volume = format_volume_issue (Volume, Issue, config.CitationClass, Periodical_origin, sepc, use_lowercase); | ||
if utilities.is_set (AccessDate) then | if utilities.is_set (AccessDate) then | ||
Line 3,741: | Line 3,452: | ||
end | end | ||
end | end | ||
Quote = utilities.wrap_style ('quoted-text', Quote ); -- wrap in <q>...</q> tags | Quote = utilities.wrap_style ('quoted-text', Quote ); -- wrap in <q>...</q> tags | ||
Line 3,795: | Line 3,505: | ||
local Archived; | local Archived; | ||
if utilities.is_set (ArchiveURL) then | if utilities.is_set (ArchiveURL) then | ||
local arch_text; | |||
if not utilities.is_set (ArchiveDate) then | |||
utilities.set_message ('err_archive_missing_date'); | |||
if utilities.is_set (ArchiveDate) then | |||
utilities.set_message (' | |||
ArchiveDate = ''; -- empty string for concatenation | ArchiveDate = ''; -- empty string for concatenation | ||
end | end | ||
if "live" == UrlStatus then | if "live" == UrlStatus then | ||
arch_text = cfg.messages['archived']; | arch_text = cfg.messages['archived']; | ||
Line 3,848: | Line 3,544: | ||
end | end | ||
else -- OriginalUrl not set | else -- OriginalUrl not set | ||
arch_text = cfg.messages['archived-missing']; | |||
if sepc ~= "." then arch_text = arch_text:lower() end | |||
utilities.set_message ('err_archive_missing_url'); | utilities.set_message ('err_archive_missing_url'); | ||
Archived = ''; -- empty string for concatenation | Archived = ''; -- empty string for concatenation | ||
Line 3,857: | Line 3,555: | ||
end | end | ||
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 (LayDate) then LayDate = " (" .. LayDate .. ")" end | |||
if utilities.is_set (LaySource) then | |||
LaySource = " – ''" .. utilities.safe_for_italics (LaySource) .. "''"; | |||
else | |||
LaySource = ""; | |||
end | |||
if sepc == '.' then | |||
Lay = sepc .. " " .. external_link( LayURL, cfg.messages['lay summary'], A:ORIGIN('LayURL'), nil ) .. LayFormat .. LaySource .. LayDate | |||
else | |||
Lay = sepc .. " " .. external_link( LayURL, cfg.messages['lay summary']:lower(), A:ORIGIN('LayURL'), nil ) .. LayFormat .. LaySource .. LayDate | |||
end | |||
elseif utilities.is_set (LayFormat) then -- Test if |lay-format= is given without giving a |lay-url= | |||
Lay = sepc .. LayFormat; -- if set and LayURL not set, then LayFormat has error message | |||
end | |||
local TranscriptURL = A['TranscriptURL'] | local TranscriptURL = A['TranscriptURL'] | ||
Line 3,908: | Line 3,606: | ||
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,950: | Line 3,650: | ||
if utilities.in_array (config.CitationClass, {"journal", "citation"}) and utilities.is_set (Periodical) then | if utilities.in_array (config.CitationClass, {"journal", "citation"}) and utilities.is_set (Periodical) then | ||
if utilities.is_set (Others) then Others = safe_join ({Others, sepc .. " "}, sepc) end -- add terminal punctuation & space; check for dup sepc; TODO why do we need to do this here? | if utilities.is_set (Others) then Others = safe_join ({Others, sepc .. " "}, sepc) end -- add terminal punctuation & space; check for dup sepc; TODO why do we need to do this here? | ||
tcommon = safe_join( {Others, Title, TitleNote, Conference, Periodical, Format, TitleType, Series, Language, Edition, Publisher, Agency, Volume}, sepc ); | tcommon = safe_join( {Others, Title, TitleNote, Conference, Periodical, Format, TitleType, Series, Language, Edition, Publisher, Agency, Volume}, sepc ); | ||
Line 3,990: | Line 3,687: | ||
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 | ||
idcommon = safe_join( { ID_list, URL, Archived, Transcript, AccessDate, Via, Lay, Quote }, sepc ); | |||
else | else | ||
idcommon = safe_join( { ID_list, URL, Archived, AccessDate, Via, Lay, Quote }, sepc ); | |||
end | end | ||
Line 4,018: | Line 3,713: | ||
end | end | ||
if utilities.is_set (Editors) then | if utilities.is_set (Editors) then | ||
local in_text = | local in_text = " "; | ||
local post_text = | local post_text = ""; | ||
if utilities.is_set (Chapter) and 0 == #c then | if utilities.is_set (Chapter) and 0 == #c then | ||
in_text = cfg.messages['in'] .. | in_text = in_text .. cfg.messages['in'] .. " " | ||
if (sepc ~= '.') then | if (sepc ~= '.') then | ||
in_text = in_text:lower() | in_text = in_text:lower() -- lowercase for cs2 | ||
end | end | ||
end | end | ||
if EditorCount <= 1 then | if EditorCount <= 1 then | ||
post_text = | post_text = " (" .. cfg.messages['editor'] .. ")"; -- be consistent with no-author, no-date case | ||
else | else | ||
post_text = | post_text = " (" .. cfg.messages['editors'] .. ")"; | ||
end | end | ||
Editors = terminate_name_list (in_text .. Editors .. post_text, sepc); -- terminate with 0 or 1 sepc and a space | Editors = terminate_name_list (in_text .. Editors .. post_text, sepc); -- terminate with 0 or 1 sepc and a space | ||
Line 4,050: | Line 3,745: | ||
if utilities.is_set (Date) then | if utilities.is_set (Date) then | ||
if EditorCount <= 1 then | if EditorCount <= 1 then | ||
Editors = Editors .. | Editors = Editors .. ", " .. cfg.messages['editor']; | ||
else | else | ||
Editors = Editors .. | Editors = Editors .. ", " .. cfg.messages['editors']; | ||
end | end | ||
else | else | ||
Line 4,127: | Line 3,822: | ||
local template_name = ('citation' == config.CitationClass) and 'citation' or 'cite ' .. (cfg.citation_class_map_t[config.CitationClass] or config.CitationClass); | local template_name = ('citation' == config.CitationClass) and 'citation' or 'cite ' .. (cfg.citation_class_map_t[config.CitationClass] or config.CitationClass); | ||
local template_link = '[[Template:' .. template_name .. '|' .. template_name .. ']]'; | local template_link = '[[Template:' .. template_name .. '|' .. template_name .. ']]'; -- TODO: if kept, these require some sort of i18n | ||
local msg_prefix = '<code class="cs1-code">{{' .. template_link .. '}}</code>: '; | local msg_prefix = '<code class="cs1-code">{{' .. template_link .. '}}</code>: '; | ||
Line 4,196: | Line 3,891: | ||
local function validate (name, cite_class, empty) | local function validate (name, cite_class, empty) | ||
local name = tostring (name); | local name = tostring (name); | ||
local enum_name; -- | local enum_name; -- for enumerated parameters, is name with enumerator replaced with '#' | ||
local state; | local state; | ||
local function state_test (state, name) -- local function to do testing of state values | local function state_test (state, name) -- local function to do testing of state values | ||
Line 4,216: | Line 3,911: | ||
return nil; | return nil; | ||
end | end | ||
if | if utilities.in_array (cite_class, whitelist.preprint_template_list ) then -- limited parameter sets allowed for these templates | ||
state = whitelist. | state = whitelist.limited_basic_arguments[name]; | ||
if true == state_test (state, name) then return true; end | if true == state_test (state, name) then return true; end | ||
state = whitelist.preprint_arguments[cite_class][name]; -- look in the parameter-list for the template identified by cite_class | |||
state = whitelist. | |||
if true == state_test (state, name) then return true; end | if true == state_test (state, name) then return true; end | ||
state = whitelist. | -- limited enumerated parameters list | ||
enum_name = name:gsub("%d+", "#" ); -- replace digit(s) with # (last25 becomes last#) (mw.ustring because non-Western 'local' digits) | |||
state = whitelist.limited_numbered_arguments[enum_name]; | |||
if true == state_test (state, name) then return true; end | if true == state_test (state, name) then return true; end | ||
Line 4,237: | Line 3,927: | ||
end -- end limited parameter-set templates | end -- end limited parameter-set templates | ||
if utilities.in_array (cite_class, whitelist. | if utilities.in_array (cite_class, whitelist.unique_param_template_list) then -- experiment for template-specific parameters for templates that accept parameters from the basic argument list | ||
state = whitelist. | state = whitelist.unique_arguments[cite_class][name]; -- look in the template-specific parameter-lists for the template identified by cite_class | ||
if true == state_test (state, name) then return true; end | if true == state_test (state, name) then return true; end | ||
end -- if here, fall into general validation | end -- if here, fall into general validation | ||
state = whitelist.basic_arguments[name]; -- all other templates; all normal parameters allowed | |||
if true == state_test (state, name) then return true; end | |||
state = whitelist. | -- all enumerated parameters allowed | ||
enum_name = name:gsub("%d+", "#" ); -- replace digit(s) with # (last25 becomes last#) (mw.ustring because non-Western 'local' digits) | |||
state = whitelist.numbered_arguments[enum_name]; | |||
if true == state_test (state, name) then return true; end | if true == state_test (state, name) then return true; end | ||
Line 4,347: | Line 4,042: | ||
local function citation(frame) | local function citation(frame) | ||
Frame = frame; -- save a copy in case we need to display an error message in preview mode | Frame = frame; -- save a copy in case we need to display an error message in preview mode | ||
is_sandbox = nil ~= string.find (frame:getTitle(), 'sandbox', 1, true); | |||
is_sandbox = nil ~= string.find (frame:getTitle(), sandbox, 1, true); | |||
local pframe = frame:getParent() | local pframe = frame:getParent() | ||
local styles; | local styles; | ||
cfg = mw.loadData ('Module:Citation/CS1/Configuration' | if is_sandbox then -- did the {{#invoke:}} use sandbox version? | ||
cfg = mw.loadData ('Module:Citation/CS1/Configuration/sandbox'); -- load sandbox versions of support modules | |||
whitelist = mw.loadData ('Module:Citation/CS1/Whitelist/sandbox'); | |||
utilities = require ('Module:Citation/CS1/Utilities/sandbox'); | |||
validation = require ('Module:Citation/CS1/Date_validation/sandbox'); | |||
identifiers = require ('Module:Citation/CS1/Identifiers/sandbox'); | |||
metadata = require ('Module:Citation/CS1/COinS/sandbox'); | |||
styles = 'Module:Citation/CS1/sandbox/styles.css'; | |||
else -- otherwise | |||
cfg = mw.loadData ('Module:Citation/CS1/Configuration'); -- load live versions of support modules | |||
whitelist = mw.loadData ('Module:Citation/CS1/Whitelist'); | |||
utilities = require ('Module:Citation/CS1/Utilities'); | |||
validation = require ('Module:Citation/CS1/Date_validation'); | |||
identifiers = require ('Module:Citation/CS1/Identifiers'); | |||
metadata = require ('Module:Citation/CS1/COinS'); | |||
styles = 'Module:Citation/CS1/styles.css'; | |||
end | |||
utilities.set_selected_modules (cfg); -- so that functions in Utilities can see the selected cfg tables | utilities.set_selected_modules (cfg); -- so that functions in Utilities can see the selected cfg tables | ||
Line 4,381: | Line 4,077: | ||
local suggestions = {}; -- table where we store suggestions if we need to loadData them | local suggestions = {}; -- table where we store suggestions if we need to loadData them | ||
local error_text; -- used as a flag | local error_text; -- used as a flag | ||
local config = {}; -- table to store parameters from the module {{#invoke:}} | |||
for k, v in pairs( frame.args ) do -- get parameters from the {{#invoke}} frame | |||
config[k] = v; | |||
-- args[k] = v; -- crude debug support that allows us to render a citation from module {{#invoke:}}; skips parameter validation; TODO: keep? | |||
end | |||
local capture; -- the single supported capture when matching unknown parameters using patterns | local capture; -- the single supported capture when matching unknown parameters using patterns | ||
Line 4,399: | Line 4,101: | ||
else | else | ||
if nil == suggestions.suggestions then -- if this table is nil then we need to load it | if nil == suggestions.suggestions then -- if this table is nil then we need to load it | ||
suggestions = mw.loadData ('Module:Citation/CS1/Suggestions' | if is_sandbox then -- did the {{#invoke:}} use sandbox version? | ||
suggestions = mw.loadData( 'Module:Citation/CS1/Suggestions/sandbox' ); -- use the sandbox version | |||
else | |||
suggestions = mw.loadData( 'Module:Citation/CS1/Suggestions' ); -- use the live version | |||
end | |||
end | end | ||
for pattern, param in pairs (suggestions.patterns) do -- loop through the patterns to see if we can suggest a proper parameter | for pattern, param in pairs (suggestions.patterns) do -- loop through the patterns to see if we can suggest a proper parameter |