Module:Citation/CS1 and Module:Citation/CS1/sandbox: Difference between pages
Appearance
(Difference between pages)
Content deleted Content added
sync from sandbox; |
No edit summary |
||
Line 1: | Line 1: | ||
--[[ |
|||
History of changes since last sync: 2025-04-12 |
|||
2025-05-10: maint cat to track {{cite journal}} templates misusing |page= for |article-number=; see Help_talk:Citation_Style_1#|page=_same_value_as_last_n-digits_of_|doi= |
|||
]] |
|||
require ('strict'); |
require ('strict'); |
||
Line 2,721: | Line 2,728: | ||
utilities.set_message ('maint_publisher_location'); -- set a maint message |
utilities.set_message ('maint_publisher_location'); -- set a maint message |
||
return; -- and done |
return; -- and done |
||
end |
|||
end |
|||
end |
|||
--[[--------------------------< I S _ P A G E _ A R T _ N U M >------------------------------------------------ |
|||
compare the trailing (rightmost) characters of the |doi= value against the whole value assigned to |page(s)=. |
|||
return boolean true when: |
|||
|page(s)= has exactly 8 digits and a dot between the fourth and fifth digits matches the trailing 9 characters |
|||
of the |doi= value: |page=12345678 → |page=1234.5678 matches |doi=10.xxxx/yyyy1234.5678 |
|||
|page(s)= is 5 or more characters and matches |doi= values's trailing characters |
|||
|page(s)= begins with a lowercase 'e' and |page(s)= without the 'e' matches |doi= values's trailing |
|||
characters: |page=e12345 → |page=12345 matches |doi=10.xxxx/yyyy12345 |
|||
|page(s)= begins with a uppercase 'CD' followed by (typically) six digits matches |doi= values that ends with |
|||
'CDxxxxxx.pubx' (where 'x' is any single digit) |
|||
return nil when |page(s)= values: |
|||
are ranges separated by underscore, hyphen, emdash, endash, figure dash, or minus character |
|||
are comma- or semicolon-separated lists of pages |
|||
have external urls (has text 'http') |
|||
are digit-only values less than 10000 |
|||
do not match |doi= values's trailing characters |
|||
]] |
|||
local function is_page_art_num (page, doi) |
|||
if not (utilities.is_set (page) and utilities.is_set (doi)) then -- both required |
|||
return; -- abandon; nothing to do |
|||
end |
|||
if page:match ('[,;_−–—‒%-]') then -- when |page(s)= might be a page range or a separated list of pages |
|||
return; -- abandon |
|||
end |
|||
page = page:lower(); -- because doi names are case insensitive |
|||
doi = doi:lower(); -- force these to lowercase for testing |
|||
if page:match ('http') then -- when |page(s)= appears to hold a url |
|||
return; -- abandon |
|||
end |
|||
if tonumber (page) then -- is |page(s)= digits only |
|||
if 10000 > tonumber (page) then -- when |page(s)= less than 10000 |
|||
return; -- abandon |
|||
end |
|||
if doi:match (page .. '$') then -- digits only page number match the last digits in |doi=? |
|||
return true; |
|||
end |
|||
if 8 == page:len() then -- special case when |page(s)= is exactly 8 digits |
|||
local dot_page = page:gsub ('(%d%d%d%d)(%d%d%d%d)', '%1.%2'); -- make a |page=xxxx.yyyy version commonly used in |doi= |
|||
if doi:match (dot_page .. '$') then -- 8-digit dotted page number match the last characters in |doi=? |
|||
return true; |
|||
end |
|||
end |
|||
else -- here when |page(s)= is alpha-numeric |
|||
if 4 < page:len() then -- when |page(s)= is five or more characters |
|||
if doi:match (page .. '$') then -- alpha-numeric page match the last characters in |doi=? |
|||
return true; |
|||
end |
|||
local epage = page:match ('^e([%w]+)$'); -- if first character of |page= is 'e', remove it |
|||
if epage and doi:match (epage .. '$') then -- page number match the last characters in |doi=? |
|||
return true; |
|||
end |
|||
local cdpage = page:match ('^cd%d+$'); -- if first characters of |page= are 'CD' and last characters are digits (typically 6 digits) |
|||
if cdpage and doi:match (cdpage .. '%.pub%d$') then -- page number matches doi 'CDxxxxxx.pubx' where 'x' is a digit |
|||
return true; |
|||
end |
|||
end |
end |
||
end |
end |
||
Line 3,460: | Line 3,541: | ||
Title = ''; -- set title to empty string |
Title = ''; -- set title to empty string |
||
utilities.set_message ('maint_untitled'); -- add maint cat |
utilities.set_message ('maint_untitled'); -- add maint cat |
||
end |
|||
if 'journal' == config.CitationClass or ('citation' == config.CitationClass and utilities.is_set (Periodical) and 'journal' == Periodical_origin) then |
|||
if is_page_art_num (Page or Pages, ID_list_coins['DOI']) then -- does |page(s)= look like it holds an article number |
|||
utilities.set_message ('maint_page_art_num'); -- add maint cat |
|||
end |
|||
end |
end |
||
Line 4,373: | Line 4,460: | ||
_, value, _ = utilities.is_wikilink (value); -- extract label portion from wikilink |
_, value, _ = utilities.is_wikilink (value); -- extract label portion from wikilink |
||
end |
end |
||
return value; |
return value; |
||
end |
end |
||
Line 4,474: | Line 4,562: | ||
frame – from template call (citation()); may be nil when called from another module |
frame – from template call (citation()); may be nil when called from another module |
||
args_t – table of all cs1|2 parameters in the template (the parent frame) |
|||
config_t – table of template-supplied parameter (the #invoke frame) |
|||
]] |
]] |
||
local function _citation (frame, |
local function _citation (frame, args_t, config_t) -- save a copy in case we need to display an error message in preview mode |
||
if not frame then |
if not frame then |
||
frame = mw.getCurrentFrame(); -- if called from another module, get a frame for frame-provided functions |
frame = mw.getCurrentFrame(); -- if called from another module, get a frame for frame-provided functions |
||
end |
end |
||
-- i18n: set the name that your wiki uses to identify sandbox subpages from sandbox template invoke (or can be set here) |
-- i18n: set the name that your wiki uses to identify sandbox subpages from sandbox template invoke (or can be set here) |
||
local sandbox = (( |
local sandbox = ((config_t.SandboxPath and '' ~= config_t.SandboxPath) and config_t.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,501: | Line 4,589: | ||
z = utilities.z; -- table of error and category tables in Module:Citation/CS1/Utilities |
z = utilities.z; -- table of error and category tables in Module:Citation/CS1/Utilities |
||
local cite_args_t = {}; -- because args_t is the parent (template) frame args (which cannot be modified); params and their values will be placed here |
|||
is_preview_mode = not utilities.is_set (frame:preprocess ('{{REVISIONID}}')); |
is_preview_mode = not utilities.is_set (frame:preprocess ('{{REVISIONID}}')); |
||
Line 4,509: | Line 4,598: | ||
local capture; -- the single supported capture when matching unknown parameters using patterns |
local capture; -- the single supported capture when matching unknown parameters using patterns |
||
local empty_unknowns = {}; -- sequence table to hold empty unknown params for error message listing |
local empty_unknowns = {}; -- sequence table to hold empty unknown params for error message listing |
||
for k, v in pairs( |
for k, v in pairs (args_t) do -- get parameters from the parent (template) frame |
||
v = mw.ustring.gsub (v, '^%s*(.-)%s*$', '%1'); -- trim leading/trailing whitespace; when v is only whitespace, becomes empty string |
v = mw.ustring.gsub (v, '^%s*(.-)%s*$', '%1'); -- trim leading/trailing whitespace; when v is only whitespace, becomes empty string |
||
if v ~= '' then |
if v ~= '' then |
||
Line 4,515: | Line 4,604: | ||
k = mw.ustring.gsub (k, '%d', cfg.date_names.local_digits); -- for enumerated parameters, translate 'local' digits to Western 0-9 |
k = mw.ustring.gsub (k, '%d', cfg.date_names.local_digits); -- for enumerated parameters, translate 'local' digits to Western 0-9 |
||
end |
end |
||
if not validate( k, |
if not validate( k, config_t.CitationClass ) then |
||
if type (k) ~= 'string' then -- exclude empty numbered parameters |
if type (k) ~= 'string' then -- exclude empty numbered parameters |
||
if v:match("%S+") ~= nil then |
if v:match("%S+") ~= nil then |
||
error_text = utilities.set_message ('err_text_ignored', {v}); |
error_text = utilities.set_message ('err_text_ignored', {v}); |
||
end |
end |
||
elseif validate (k:lower(), |
elseif validate (k:lower(), config_t.CitationClass) then |
||
error_text = utilities.set_message ('err_parameter_ignored_suggest', {k, k:lower()}); -- suggest the lowercase version of the parameter |
error_text = utilities.set_message ('err_parameter_ignored_suggest', {k, k:lower()}); -- suggest the lowercase version of the parameter |
||
else |
else |
||
Line 4,530: | Line 4,619: | ||
if capture then -- if the pattern matches |
if capture then -- if the pattern matches |
||
param = utilities.substitute (param, capture); -- add the capture to the suggested parameter (typically the enumerator) |
param = utilities.substitute (param, capture); -- add the capture to the suggested parameter (typically the enumerator) |
||
if validate (param, |
if validate (param, config_t.CitationClass) then -- validate the suggestion to make sure that the suggestion is supported by this template (necessary for limited parameter lists) |
||
error_text = utilities.set_message ('err_parameter_ignored_suggest', {k, param}); -- set the suggestion error message |
error_text = utilities.set_message ('err_parameter_ignored_suggest', {k, param}); -- set the suggestion error message |
||
else |
else |
||
Line 4,539: | Line 4,628: | ||
end |
end |
||
if not utilities.is_set (error_text) then -- couldn't match with a pattern, is there an explicit suggestion? |
if not utilities.is_set (error_text) then -- couldn't match with a pattern, is there an explicit suggestion? |
||
if (suggestions.suggestions[ k:lower() ] ~= nil) and validate (suggestions.suggestions[ k:lower() ], |
if (suggestions.suggestions[ k:lower() ] ~= nil) and validate (suggestions.suggestions[ k:lower() ], config_t.CitationClass) then |
||
utilities.set_message ('err_parameter_ignored_suggest', {k, suggestions.suggestions[ k:lower() ]}); |
utilities.set_message ('err_parameter_ignored_suggest', {k, suggestions.suggestions[ k:lower() ]}); |
||
else |
else |
||
Line 4,549: | Line 4,638: | ||
end |
end |
||
cite_args_t[k] = v; -- save this parameter and its value |
|||
elseif not utilities.is_set (v) then -- for empty parameters |
elseif not utilities.is_set (v) then -- for empty parameters |
||
if not validate (k, |
if not validate (k, config_t.CitationClass, true) then -- is this empty parameter a valid parameter |
||
k = ('' == k) and '(empty string)' or k; -- when k is empty string (or was space(s) trimmed to empty string), replace with descriptive text |
k = ('' == k) and '(empty string)' or k; -- when k is empty string (or was space(s) trimmed to empty string), replace with descriptive text |
||
table.insert (empty_unknowns, utilities.wrap_style ('parameter', k)); -- format for error message and add to the list |
table.insert (empty_unknowns, utilities.wrap_style ('parameter', k)); -- format for error message and add to the list |
||
end |
end |
||
end |
|||
-- crude debug support that allows us to render a citation from module {{#invoke:}} TODO: keep? |
|||
-- elseif args[k] ~= nil or (k == 'postscript') then -- when args[k] has a value from {{#invoke}} frame (we don't normally do that) |
|||
-- args[k] = v; -- overwrite args[k] with empty string from pframe.args[k] (template frame); v is empty string here |
|||
end -- not sure about the postscript bit; that gets handled in parameter validation; historical artifact? |
|||
end |
end |
||
Line 4,572: | Line 4,658: | ||
local url_param_t = {}; -- table of url-holding paramters and their values |
local url_param_t = {}; -- table of url-holding paramters and their values |
||
for k, v in pairs( |
for k, v in pairs (cite_args_t) do |
||
if 'string' == type (k) then -- don't evaluate positional parameters |
if 'string' == type (k) then -- don't evaluate positional parameters |
||
has_invisible_chars (k, v); -- look for invisible characters |
has_invisible_chars (k, v); -- look for invisible characters |
||
Line 4,578: | Line 4,665: | ||
has_extraneous_punc (k, v); -- look for extraneous terminal punctuation in parameter values |
has_extraneous_punc (k, v); -- look for extraneous terminal punctuation in parameter values |
||
missing_pipe_check (k, v); -- do we think that there is a parameter that is missing a pipe? |
missing_pipe_check (k, v); -- do we think that there is a parameter that is missing a pipe? |
||
cite_args_t[k] = inter_wiki_check (k, v); -- when language interwiki-linked parameter missing leading colon replace with wiki-link label |
|||
if 'string' == type (k) then -- when parameter k is not positional |
if 'string' == type (k) then -- when parameter k is not positional |
||
Line 4,591: | Line 4,678: | ||
has_extraneous_url (non_url_param_t); -- look for url in parameter values where a url does not belong |
has_extraneous_url (non_url_param_t); -- look for url in parameter values where a url does not belong |
||
if has_twl_url (url_param_t) then -- look for url-holding parameters that hold a The Wikipedia Library url |
if has_twl_url (url_param_t) then -- look for url-holding parameters that hold a The Wikipedia Library url |
||
cite_args_t['url-access'] = 'subscription'; |
|||
end |
end |
||
return table.concat ({ |
return table.concat ({ |
||
frame:extensionTag ('templatestyles', '', {src='Module:Citation/CS1' .. sandbox .. '/styles.css'}), |
frame:extensionTag ('templatestyles', '', {src='Module:Citation/CS1' .. sandbox .. '/styles.css'}), |
||
citation0 |
citation0 (config_t, cite_args_t) |
||
}); |
}); |
||
end |
end |