| Line 1: |
Line 1: |
| − | 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 8: |
| | | | |
| | 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 152: |
| | end | | end |
| | | | |
| − | for _, d in ipairs ({'cash', 'company', 'today', 'org'}) do -- look for single letter second level domain names for these top level domains | + | for _, d in ipairs (cfg.single_letter_2nd_lvl_domains_t) 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 263: |
| | | | |
| | local function link_title_ok (link, lorig, title, torig) | | local function link_title_ok (link, lorig, title, torig) |
| − | local orig; | + | 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 399: |
| | 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"]); -- programmer error; valid parameter name does not have matching meta-parameter |
| | end | | end |
| | end | | end |
| Line 764: |
Line 762: |
| | 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.emoji[mw.ustring.codepoint (v, position+1)] then -- is zwj followed by a character listed in emoji{}? | + | elseif cfg.emoji_t[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,103: |
| | | | |
| | return table.concat(initials) -- Vancouver format does not include spaces. | | return table.concat(initials) -- Vancouver format does not include spaces. |
| | + | end |
| | + | |
| | + | |
| | + | --[[--------------------------< I N T E R W I K I _ P R E F I X E N _ G E T >---------------------------------- |
| | + | |
| | + | extract interwiki prefixen from <value>. Returns two one or two values: |
| | + | false – no prefixen |
| | + | nil – prefix exists but not recognized |
| | + | project prefix, language prefix – when value has either of: |
| | + | :<project>:<language>:<article> |
| | + | :<language>:<project>:<article> |
| | + | project prefix, nil – when <value> has only a known single-letter prefix |
| | + | nil, language prefix – when <value> has only a known language prefix |
| | + | |
| | + | accepts single-letter project prefixen: 'd' (wikidata), 's' (wikisource), and 'w' (wikipedia) prefixes; at this |
| | + | writing, the other single-letter prefixen (b (wikibook), c (commons), m (meta), n (wikinews), q (wikiquote), and |
| | + | v (wikiversity)) are not supported. |
| | + | |
| | + | ]] |
| | + | |
| | + | local function interwiki_prefixen_get (value, is_link) |
| | + | if not value:find (':%l+:') then -- if no prefix |
| | + | return false; -- abandon; boolean here to distinguish from nil fail returns later |
| | + | end |
| | + | |
| | + | local prefix_patterns_linked_t = { -- sequence of valid interwiki and inter project prefixen |
| | + | '^%[%[:([dsw]):(%l%l+):', -- wikilinked; project and language prefixes |
| | + | '^%[%[:(%l%l+):([dsw]):', -- wikilinked; language and project prefixes |
| | + | '^%[%[:([dsw]):', -- wikilinked; project prefix |
| | + | '^%[%[:(%l%l+):', -- wikilinked; language prefix |
| | + | } |
| | + | |
| | + | local prefix_patterns_unlinked_t = { -- sequence of valid interwiki and inter project prefixen |
| | + | '^:([dsw]):(%l%l+):', -- project and language prefixes |
| | + | '^:(%l%l+):([dsw]):', -- language and project prefixes |
| | + | '^:([dsw]):', -- project prefix |
| | + | '^:(%l%l+):', -- language prefix |
| | + | } |
| | + | |
| | + | local cap1, cap2; |
| | + | for _, pattern in ipairs ((is_link and prefix_patterns_linked_t) or prefix_patterns_unlinked_t) do |
| | + | cap1, cap2 = value:match (pattern); |
| | + | if cap1 then |
| | + | break; -- found a match so stop looking |
| | + | end |
| | + | end |
| | + | |
| | + | if cap1 and cap2 then -- when both then :project:language: or :language:project: (both forms allowed) |
| | + | if 1 == #cap1 then -- length == 1 then :project:language: |
| | + | if cfg.inter_wiki_map[cap2] then -- is language prefix in the interwiki map? |
| | + | return cap1, cap2; -- return interwiki project and interwiki language |
| | + | end |
| | + | else -- here when :language:project: |
| | + | if cfg.inter_wiki_map[cap1] then -- is language prefix in the interwiki map? |
| | + | return cap2, cap1; -- return interwiki project and interwiki language |
| | + | end |
| | + | end |
| | + | return nil; -- unknown interwiki language |
| | + | elseif not (cap1 or cap2) then -- both are nil? |
| | + | return nil; -- we got something that looks like a project prefix but isn't; return fail |
| | + | elseif 1 == #cap1 then -- here when one capture |
| | + | return cap1, nil; -- length is 1 so return project, nil language |
| | + | else -- here when one capture and its length it more than 1 |
| | + | if cfg.inter_wiki_map[cap1] then -- is language prefix in the interwiki map? |
| | + | return nil, cap1; -- return nil project, language |
| | + | end |
| | + | end |
| | end | | end |
| | | | |
| Line 1,175: |
Line 1,240: |
| | 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) |
| | + | local proj, tag = interwiki_prefixen_get (one, true); -- get the interwiki prefixen if present |
| | + | |
| | + | if 'w' == proj and ('Wikipedia' == mw.site.namespaces.Project['name']) then |
| | + | proj = nil; -- for stuff like :w:de:<article>, :w is unnecessary TODO: maint cat? |
| | + | end |
| | + | if proj then |
| | + | proj = ({['d'] = 'Wikidata', ['s'] = 'Wikisource', ['w'] = 'Wikipedia'})[proj]; -- :w (wikipedia) for linking from a non-wikipedia project |
| | + | if proj then |
| | + | one = one .. utilities.wrap_style ('interproj', proj); -- add resized leading space, brackets, static text, language name |
| | + | tag = nil; -- unset; don't do both project and language |
| | + | end |
| | + | end |
| | + | if tag == cfg.this_wiki_code then |
| | + | tag = nil; -- stuff like :en:<article> at en.wiki is pointless TODO: maint cat? |
| | + | end |
| | + | if tag then |
| | + | local lang = cfg.lang_code_remap[tag] or cfg.mw_languages_by_tag_t[tag]; |
| | + | if lang then -- error messaging done in extract_names() where we know parameter names |
| | + | one = one .. utilities.wrap_style ('interwiki', lang); -- add resized leading space, brackets, static text, language name |
| | + | end |
| | + | end |
| | + | |
| | 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,494: |
Line 1,582: |
| | 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 ); |
| − | | + | |
| | + | if last then -- error check |lastn= alias for unknown interwiki link prefix; done here because this is where we have the parameter name |
| | + | local project, language = interwiki_prefixen_get (last, true); -- true because we expect interwiki links in |lastn= to be wikilinked |
| | + | if nil == project and nil == language then -- when both are nil |
| | + | utilities.set_message ('err_bad_paramlink', last_alias); -- not known, emit an error message -- TODO: err_bad_interwiki? |
| | + | last = utilities.remove_wiki_link (last); -- remove wikilink markup; show display value only |
| | + | end |
| | + | end |
| | + | |
| | + | if link then -- error check |linkn= alias for unknown interwiki link prefix |
| | + | local project, language = interwiki_prefixen_get (link, false); -- false because wiki links in |author-linkn= is an error |
| | + | if nil == project and nil == language then -- when both are nil |
| | + | utilities.set_message ('err_bad_paramlink', link_alias); -- not known, emit an error message -- TODO: err_bad_interwiki? |
| | + | link = nil; -- unset so we don't link |
| | + | link_alias = nil; |
| | + | end |
| | + | end |
| | + | |
| | 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,633: |
Line 1,738: |
| | 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, lang_subtag}, lang_subtag); -- categorize it; tag appended to allow for multiple language categorization
| |
| | utilities.add_prop_cat ('foreign-lang-source', {name, tag}, lang_subtag); -- categorize it; tag appended to allow for multiple language categorization | | utilities.add_prop_cat ('foreign-lang-source', {name, tag}, 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) |
| Line 1,682: |
Line 1,786: |
| | 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 2,089: |
Line 2,194: |
| | | | |
| | | | |
| − | --[[-------------------------< 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 parameters as a single string; or formatted volume | + | returns the concatenation of the formatted volume and issue (or journal article number) parameters as a single |
| − | or formatted issue, or an empty string if neither are set. | + | string; or formatted volume or formatted issue, or an empty string if neither are set. |
| | | | |
| | ]] | | ]] |
| | | | |
| − | local function format_volume_issue (volume, issue, cite_class, origin, sepc, lower) | + | local function format_volume_issue (volume, issue, article, cite_class, origin, sepc, lower) |
| − | if not utilities.is_set (volume) and not utilities.is_set (issue) then | + | if not utilities.is_set (volume) and not utilities.is_set (issue) and not utilities.is_set (article) then |
| | return ''; | | return ''; |
| | end | | end |
| Line 2,113: |
Line 2,218: |
| | 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,123: |
Line 2,228: |
| | end | | end |
| | end | | end |
| − | if utilities.is_set (issue) then | + | vol = vol .. (utilities.is_set (issue) and utilities.substitute (cfg.messages['j-issue'], issue) or '') |
| − | return vol .. utilities.substitute (cfg.messages['j-issue'], issue);
| + | vol = vol .. (utilities.is_set (article) and utilities.substitute (cfg.messages['j-article-num'], article) or '') |
| − | end
| |
| | return vol; | | return vol; |
| | end | | end |
| Line 2,131: |
Line 2,235: |
| | 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 |
| | + | |
| | + | if 'conference' == cite_class and utilities.is_set (article) then -- |article-number= supported only in journal and conference cites |
| | + | if utilities.is_set (volume) and utilities.is_set (article) then -- both volume and article number |
| | + | return wrap_msg ('vol-art', {sepc, utilities.hyphen_to_dash (volume), article}, lower); |
| | + | elseif utilities.is_set (article) then -- article number alone; when volume alone, handled below |
| | + | return wrap_msg ('art', {sepc, article}, lower); |
| | + | end |
| | end | | end |
| | | | |
| Line 2,504: |
Line 2,616: |
| | 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) .. ' and ' .. utilities.wrap_style ('parameter', 'mailinglist')}); | + | utilities.set_message ('err_redundant_parameters', {utilities.wrap_style ('parameter', Periodical_origin) .. cfg.presentation['sep_list_pair'] .. utilities.wrap_style ('parameter', 'mailinglist')}); |
| | end | | end |
| | | | |
| Line 2,552: |
Line 2,664: |
| | end | | end |
| | end | | end |
| | + | |
| | + | local ArticleNumber; |
| | + | |
| | + | if utilities.in_array (config.CitationClass, {'journal', 'conference'}) or ('citation' == config.CitationClass and utilities.is_set (Periodical) and 'journal' == Periodical_origin) then |
| | + | ArticleNumber = A['ArticleNumber']; |
| | + | 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,557: |
Line 2,676: |
| | local Pages; | | local Pages; |
| | local At; | | local At; |
| − | if not utilities.in_array (config.CitationClass, cfg.templates_not_using_page) then | + | local QuotePage; |
| | + | local QuotePages; |
| | + | if not utilities.in_array (config.CitationClass, cfg.templates_not_using_page) then -- TODO: rewrite to emit ignored parameter error message? |
| | 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']; |
| | + | QuotePage = A['QuotePage']; |
| | + | QuotePages = utilities.hyphen_to_dash (A['QuotePages']); |
| | end | | end |
| | | | |
| Line 2,614: |
Line 2,737: |
| | -- 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 utilities.in_array (this_page.nsText, cfg.uncategorized_namespaces) then | + | if cfg.uncategorized_namespaces[this_page.namespace] then -- is this page's namespace id one of the uncategorized namespace ids? |
| | no_tracking_cats = "true"; -- set no_tracking_cats | | no_tracking_cats = "true"; -- set no_tracking_cats |
| | end | | end |
| Line 2,679: |
Line 2,802: |
| | if ('encyclopaedia' == config.CitationClass) or ('citation' == config.CitationClass and utilities.is_set (Encyclopedia)) then | | if ('encyclopaedia' == config.CitationClass) or ('citation' == config.CitationClass and utilities.is_set (Encyclopedia)) then |
| | if utilities.is_set (Periodical) and utilities.is_set (Encyclopedia) then -- when both set emit an error TODO: make a function for this and similar? | | 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 ('err_redundant_parameters', {utilities.wrap_style ('parameter', A:ORIGIN ('Encyclopedia')) .. ' and ' .. utilities.wrap_style ('parameter', Periodical_origin)}); | + | utilities.set_message ('err_redundant_parameters', {utilities.wrap_style ('parameter', A:ORIGIN ('Encyclopedia')) .. cfg.presentation['sep_list_pair'] .. utilities.wrap_style ('parameter', Periodical_origin)}); |
| | end | | end |
| | | | |
| Line 2,725: |
Line 2,848: |
| | 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') .. ' and ' .. utilities.wrap_style ('parameter', 'number')}); | + | utilities.set_message ('err_redundant_parameters', {utilities.wrap_style ('parameter', 'id') .. cfg.presentation['sep_list_pair'] .. utilities.wrap_style ('parameter', 'number')}); |
| | end | | end |
| | end | | end |
| Line 2,771: |
Line 2,894: |
| | 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') .. ' and ' .. utilities.wrap_style ('parameter', Chapter_origin)}); -- add error message | + | utilities.set_message ('err_redundant_parameters', {utilities.wrap_style ('parameter', 'map') .. cfg.presentation['sep_list_pair'] .. utilities.wrap_style ('parameter', Chapter_origin)}); -- add error message |
| | end | | end |
| | Chapter = A['Map']; | | Chapter = A['Map']; |
| Line 2,814: |
Line 2,937: |
| | | | |
| | 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') .. ' and ' .. utilities.wrap_style ('parameter', 'seriesno')}); -- add error message | + | utilities.set_message ('err_redundant_parameters', {utilities.wrap_style ('parameter', 'season') .. cfg.presentation['sep_list_pair'] .. utilities.wrap_style ('parameter', 'seriesno')}); -- add error message |
| | SeriesNumber = ''; -- unset; prefer |season= over |seriesno= | | SeriesNumber = ''; -- unset; prefer |season= over |seriesno= |
| | end | | end |
| Line 2,994: |
Line 3,117: |
| | | | |
| | -- Account for the oddities that are {{cite arxiv}}, {{cite biorxiv}}, {{cite citeseerx}}, {{cite ssrn}}, before generation of COinS data. | | -- Account for the oddities that are {{cite arxiv}}, {{cite biorxiv}}, {{cite citeseerx}}, {{cite ssrn}}, before generation of COinS data. |
| − | if utilities.in_array (config.CitationClass, whitelist.preprint_template_list) then | + | if utilities.in_array (config.CitationClass, whitelist.preprint_template_list) then -- |arxiv= or |eprint= required for cite arxiv; |biorxiv=, |citeseerx=, |ssrn= required for their templates |
| − | 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
| + | if not (args[cfg.id_handlers[config.CitationClass:upper()].parameters[1]] or -- can't use ID_list_coins k/v table here because invalid parameters omitted |
| − | utilities.set_message ('err_' .. config.CitationClass .. '_missing'); -- add error message | + | args[cfg.id_handlers[config.CitationClass:upper()].parameters[2]]) then -- which causes unexpected parameter missing error message |
| | + | utilities.set_message ('err_' .. config.CitationClass .. '_missing'); -- add error message |
| | end | | end |
| | | | |
| Line 3,063: |
Line 3,187: |
| | 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,081: |
Line 3,202: |
| | ['Volume'] = Volume, | | ['Volume'] = Volume, |
| | ['Issue'] = Issue, | | ['Issue'] = Issue, |
| | + | ['ArticleNumber'] = ArticleNumber, |
| | ['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,378: |
Line 3,500: |
| | 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') .. ' and ' .. utilities.wrap_style ('parameter', 'time')}); | + | utilities.set_message ('err_redundant_parameters', {utilities.wrap_style ('parameter', 'minutes') .. cfg.presentation['sep_list_pair'] .. utilities.wrap_style ('parameter', 'time')}); |
| | end | | end |
| | Position = " " .. Minutes .. " " .. cfg.messages['minutes']; | | Position = " " .. Minutes .. " " .. cfg.messages['minutes']; |
| Line 3,450: |
Line 3,572: |
| | 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, config.CitationClass, Periodical_origin, sepc, use_lowercase); | + | Volume = format_volume_issue (Volume, Issue, ArticleNumber, config.CitationClass, Periodical_origin, sepc, use_lowercase); |
| | | | |
| | if utilities.is_set (AccessDate) then | | if utilities.is_set (AccessDate) then |
| Line 3,486: |
Line 3,608: |
| | end | | end |
| | end | | end |
| − | | + | |
| | + | Quote = kern_quotes (Quote); -- kern if needed |
| | 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,684: |
Line 3,807: |
| | | | |
| | 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 not (utilities.is_set (Authors) or utilities.is_set (Editors)) then |
| | + | Others = Others:gsub ('^' .. sepc .. ' ', ''); -- when no authors and no editors, strip leading sepc and space |
| | + | end |
| | 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,779: |
Line 3,905: |
| | if utilities.is_set (Date) then | | if utilities.is_set (Date) then |
| | if EditorCount <= 1 then | | if EditorCount <= 1 then |
| − | Editors = Editors .. ", " .. cfg.messages['editor']; | + | Editors = Editors .. cfg.presentation['sep_name'] .. cfg.messages['editor']; |
| | else | | else |
| − | Editors = Editors .. ", " .. cfg.messages['editors']; | + | Editors = Editors .. cfg.presentation['sep_name'] .. cfg.messages['editors']; |
| | end | | end |
| | else | | else |
| Line 4,076: |
Line 4,202: |
| | 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 |
| − | local sandbox = '/sandbox' -- i18n: replace this rvalue with the name that your wiki uses to identify sandbox subpages | + | |
| | + | 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 |
| | + | -- i18n: set the name that your wiki uses to identify sandbox subpages from sandbox template invoke (or can be set here) |
| | + | local sandbox = ((config.SandboxPath and '' ~= config.SandboxPath) and config.SandboxPath) or '/sandbox'; -- sandbox path from {{#invoke:Citation/CS1/sandbox|citation|SandboxPath=/...}} |
| | is_sandbox = nil ~= string.find (frame:getTitle(), sandbox, 1, true); -- is this invoke the sandbox module? | | is_sandbox = nil ~= string.find (frame:getTitle(), sandbox, 1, true); -- is this invoke the sandbox module? |
| | sandbox = is_sandbox and sandbox or ''; -- use i18n sandbox to load sandbox modules when this module is the sandox; live modules else | | sandbox = is_sandbox and sandbox or ''; -- use i18n sandbox to load sandbox modules when this module is the sandox; live modules else |
| Line 4,103: |
Line 4,236: |
| | 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,127: |
Line 4,254: |
| | 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 |
| − | if is_sandbox then -- did the {{#invoke:}} use sandbox version? | + | suggestions = mw.loadData ('Module:Citation/CS1/Suggestions' .. sandbox); --load sandbox version of suggestion module when {{#invoke:Citation/CS1/sandbox|...}}; live module else |
| − | 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 |