Jump to content

Module:Citation/CS1: Difference between revisions

synch from sandbox;
imported>Rob Kam
m (1 revision imported)
enwiki:Mediawiki>Trappist the monk
(synch from sandbox;)
Line 415: Line 415:
if path then -- if there is a path portion
if path then -- if there is a path portion
path = path:gsub ('[%[%]]', {['[']='%5b',[']']='%5d'}); -- replace '[' and ']' with their percent encoded values
path = path:gsub ('[%[%]]', {['[']='%5b',[']']='%5d'}); -- replace '[' and ']' with their percent encoded values
URL=domain..path; -- and reassemble
URL = table.concat ({domain, path}); -- and reassemble
end
end
base_url = table.concat({ "[", URL, " ", safe_for_url (label), "]" }); -- assemble a wikimarkup url
if is_set (access) then -- access level (subscription, registration, limited)
if is_set (access) then -- access level (subscription, registration, limited)
label = safe_for_url (label); -- replace square brackets and newlines
base_url = substitute (cfg.presentation['ext-link-access-signal'], {cfg.presentation[access].class, cfg.presentation[access].title, base_url}); -- add the appropriate icon
 
base_url = table.concat ( -- assemble external link with access signal
{
'<span class="plainlinks">[', -- opening css and url markup
URL, -- the url
' ', -- the required space
label,
'<span style="padding-left:0.15em">', -- signal spacing css
cfg.presentation[access], -- the appropriate icon
'</span>', -- close signal spacing span
']</span>' -- close url markup and plain links span
});
else
base_url = table.concat({ "[", URL, " ", safe_for_url( label ), "]" }); -- no signal markup
end
end
return table.concat({ base_url, error_str });
return table.concat ({base_url, error_str});
end
end


Line 693: Line 681:
if position then
if position then
if 'nowiki' == capture or 'math' == capture then -- nowiki, math stripmarker (not an error condition)
if 'nowiki' == capture or 'math' == capture or -- nowiki and math stripmarkers (not an error condition)
stripmarker = true; -- set a flag
('templatestyles' == capture and in_array (param, {'id', 'quote'})) then -- templatestyles stripmarker allowed in these parameters
stripmarker = true; -- set a flag
elseif true == stripmarker and 'delete' == char then -- because stripmakers begin and end with the delete char, assume that we've found one end of a stripmarker
elseif true == stripmarker and 'delete' == char then -- because stripmakers begin and end with the delete char, assume that we've found one end of a stripmarker
position = nil; -- unset
position = nil; -- unset
Line 764: Line 753:




--[[--------------------------< V A L I D A T E >--------------------------------------------------------------
--[[--------------------------< N O W R A P _ D A T E >--------------------------------------------------------
 
When date is YYYY-MM-DD format wrap in nowrap span: <span ...>YYYY-MM-DD</span>.  When date is DD MMMM YYYY or is
MMMM DD, YYYY then wrap in nowrap span: <span ...>DD MMMM</span> YYYY or <span ...>MMMM DD,</span> YYYY


Looks for a parameter's name in one of several whitelists.
DOES NOT yet support MMMM YYYY or any of the date ranges.


Parameters in the whitelist can have three values:
true - active, supported parameters
false - deprecated, supported parameters
nil - unsupported parameters
]]
]]


local function validate( name, cite_class )
local function nowrap_date (date)
local name = tostring( name );
local cap='';
local state;
local cap2='';
 
if date:match("^%d%d%d%d%-%d%d%-%d%d$") then
date = substitute (cfg.presentation['nowrap1'], date);
elseif date:match("^%a+%s*%d%d?,%s+%d%d%d%d$") or date:match ("^%d%d?%s*%a+%s+%d%d%d%d$") then
cap, cap2 = string.match (date, "^(.*)%s+(%d%d%d%d)$");
date = substitute (cfg.presentation['nowrap2'], {cap, cap2});
end
if in_array (cite_class, {'arxiv', 'biorxiv', 'citeseerx'}) then -- limited parameter sets allowed for these templates
return date;
state = whitelist.limited_basic_arguments[ name ];
end
if true == state then return true; end -- valid actively supported parameter
 
if false == state then
deprecated_parameter (name); -- parameter is deprecated but still supported
return true;
end


if 'arxiv' == cite_class then -- basic parameters unique to these templates
--[[--------------------------< S E T _ T I T L E T Y P E >----------------------------------------------------
state = whitelist.arxiv_basic_arguments[name];
 
end
This function sets default title types (equivalent to the citation including |type=<default value>) for those templates that have defaults.
if 'biorxiv' == cite_class then
Also handles the special case where it is desirable to omit the title type from the rendered citation (|type=none).
state = whitelist.biorxiv_basic_arguments[name];
 
end
]]
if 'citeseerx' == cite_class then
state = whitelist.citeseerx_basic_arguments[name];
end


if true == state then return true; end -- valid actively supported parameter
local function set_titletype (cite_class, title_type)
if false == state then
if is_set(title_type) then
deprecated_parameter (name); -- parameter is deprecated but still supported
if "none" == title_type then
return true;
title_type = ""; -- if |type=none then type parameter not displayed
end
end
-- limited enumerated parameters list
return title_type; -- if |type= has been set to any other value use that value
name = name:gsub("%d+", "#" ); -- replace digit(s) with # (last25 becomes last#) (mw.ustring because non-Western 'local' digits)
state = whitelist.limited_numbered_arguments[ name ];
if true == state then return true; end -- valid actively supported parameter
if false == state then
deprecated_parameter (name); -- parameter is deprecated but still supported
return true;
end
 
return false; -- not supported because not found or name is set to nil
end -- end limited parameter-set templates
state = whitelist.basic_arguments[ name ]; -- all other templates; all normal parameters allowed
if true == state then return true; end -- valid actively supported parameter
if false == state then
deprecated_parameter (name); -- parameter is deprecated but still supported
return true;
end
end
-- all enumerated parameters allowed
name = name:gsub("%d+", "#" ); -- replace digit(s) with # (last25 becomes last#) (mw.ustring because non-Western 'local' digits)
state = whitelist.numbered_arguments[ name ];


if true == state then return true; end -- valid actively supported parameter
return cfg.title_types [cite_class] or ''; -- set template's default title type; else empty string for concatenation
if false == state then
deprecated_parameter (name); -- parameter is deprecated but still supported
return true;
end
return false; -- not supported because not found or name is set to nil
end
end




--[[--------------------------< N O W R A P _ D A T E >--------------------------------------------------------
--[[--------------------------< H Y P H E N _ T O _ D A S H >--------------------------------------------------
 
Converts a hyphen to a dash under certain conditions.  The hyphen must separate like items; unlike items are
returned unmodified.  These forms are modified:
letter - letter (A - B)
digit - digit (4-5)
digit separator digit - digit separator digit (4.1-4.5 or 4-1-4-5)
letterdigit - letterdigit (A1-A5) (an optional separator between letter and digit is supported – a.1-a.5 or a-1-a-5)
digitletter - digitletter (5a - 5d) (an optional separator between letter and digit is supported – 5.a-5.d or 5-a-5-d)


When date is YYYY-MM-DD format wrap in nowrap span: <span ...>YYYY-MM-DD</span>.  When date is DD MMMM YYYY or is
any other forms are returned unmodified.
MMMM DD, YYYY then wrap in nowrap span: <span ...>DD MMMM</span> YYYY or <span ...>MMMM DD,</span> YYYY


DOES NOT yet support MMMM YYYY or any of the date ranges.
str may be a comma- or semicolon-separated list


]]
]]


local function nowrap_date (date)
local function hyphen_to_dash( str )
local cap='';
if not is_set (str) then
local cap2='';
return str;
 
end
if date:match("^%d%d%d%d%-%d%d%-%d%d$") then
date = substitute (cfg.presentation['nowrap1'], date);
elseif date:match("^%a+%s*%d%d?,%s+%d%d%d%d$") or date:match ("^%d%d?%s*%a+%s+%d%d%d%d$") then
str, count = str:gsub ('^%(%((.+)%)%)$', '%1'); -- remove accept-this-as-written markup when it wraps all of str
cap, cap2 = string.match (date, "^(.*)%s+(%d%d%d%d)$");
if 0 ~= count then -- non-zero when markup removed; zero else
date = substitute (cfg.presentation['nowrap2'], {cap, cap2});
return str; -- nothing to do, we're done
end
end
return date;
local out = {};
local list = mw.text.split (str, '%s*[,;]%s*'); -- split str at comma or semicolon separators if there are any
 
for _, item in ipairs (list) do -- for each item in the list
if mw.ustring.match (item, '^%w*[%.%-]?%w+%s*[%-–—]%s*%w*[%.%-]?%w+$') then -- if a hyphenated range or has endash or emdash separators
if item:match ('%a+[%.%-]?%d+%s*%-%s*%a+[%.%-]?%d+') or -- letterdigit hyphen letterdigit (optional separator between letter and digit)
item:match ('%d+[%.%-]?%a+%s*%-%s*%d+[%.%-]?%a+') or -- digitletter hyphen digitletter (optional separator between digit and letter)
item:match ('%d+[%.%-]%d+%s*%-%s*%d+[%.%-]%d+') or -- digit separator digit hyphen digit separator digit
item:match ('%d+%s*%-%s*%d+') or -- digit hyphen digit
item:match ('%a+%s*%-%s*%a+') then -- letter hyphen letter
item = item:gsub ('(%w*[%.%-]?%w+)%s*%-%s*(%w*[%.%-]?%w+)', '%1–%2'); -- replace hyphen, remove extraneous space characters
else
item = mw.ustring.gsub (item, '%s*[–—]%s*', '–'); -- for endash or emdash separated ranges, replace em with en, remove extraneous white space
end
end
item = item:gsub ('^%(%((.+)%)%)$', '%1'); -- remove the accept-this-as-written markup
table.insert (out, item); -- add the (possibly modified) item to the output table
end
 
return table.concat (out, ', '); -- concatenate the output table into a comma separated string
end
end




--[[--------------------------< S E T _ T I T L E T Y P E >----------------------------------------------------
--[[--------------------------< S A F E _ J O I N >------------------------------------------------------------


This function sets default title types (equivalent to the citation including |type=<default value>) for those templates that have defaults.
Joins a sequence of strings together while checking for duplicate separation characters.
Also handles the special case where it is desirable to omit the title type from the rendered citation (|type=none).


]]
]]


local function set_titletype (cite_class, title_type)
local function safe_join( tbl, duplicate_char )
if is_set(title_type) then
if "none" == title_type then
title_type = ""; -- if |type=none then type parameter not displayed
end
return title_type; -- if |type= has been set to any other value use that value
end
 
return cfg.title_types [cite_class] or ''; -- set template's default title type; else empty string for concatenation
end
 
 
--[[--------------------------< H Y P H E N _ T O _ D A S H >--------------------------------------------------
 
Converts a hyphen to a dash
 
]]
 
local function hyphen_to_dash( str )
if not is_set(str) or str:match( "[%[%]{}<>]" ) ~= nil then
return str;
end
return str:gsub( '-', '–' );
end
 
 
--[[--------------------------< S A F E _ J O I N >------------------------------------------------------------
 
Joins a sequence of strings together while checking for duplicate separation characters.
 
]]
 
local function safe_join( tbl, duplicate_char )
local f = {}; -- create a function table appropriate to type of 'dupicate character'
local f = {}; -- create a function table appropriate to type of 'dupicate character'
if 1 == #duplicate_char then -- for single byte ascii characters use the string library functions
if 1 == #duplicate_char then -- for single byte ascii characters use the string library functions
Line 2,059: Line 2,012:




--[[--------------------------< M I S S I N G _ P I P E _ C H E C K >------------------------------------------
--[[--------------------------< C I T A T I O N 0 >------------------------------------------------------------


Look at the contents of a parameter. If the content has a string of characters and digits followed by an equal
This is the main function doing the majority of the citation formatting.
sign, compare the alphanumeric string to the list of cs1|2 parameters.  If found, then the string is possibly a
parameter that is missing its pipe:
{{cite ... |title=Title access-date=2016-03-17}}
 
cs1|2 shares some parameter names with xml/html atributes: class=, title=, etc.  To prevent false positives xml/html
tags are removed before the search.
 
If a missing pipe is detected, this function adds the missing pipe maintenance category.
 
]]
 
local function missing_pipe_check (value)
local capture;
value = value:gsub ('%b<>', ''); -- remove xml/html tags because attributes: class=, title=, etc
 
capture = value:match ('%s+(%a[%a%d]+)%s*=') or value:match ('^(%a[%a%d]+)%s*='); -- find and categorize parameters with possible missing pipes
if capture and validate (capture) then -- if the capture is a valid parameter name
add_maint_cat ('missing_pipe');
end
end
 
 
--[[--------------------------< C I T A T I O N 0 >------------------------------------------------------------
 
This is the main function doing the majority of the citation formatting.


]]
]]
Line 2,246: Line 2,174:
-- conference & map books do not support issue
-- conference & map books do not support issue
if in_array (config.CitationClass, cfg.templates_using_issue) and not (in_array (config.CitationClass, {'conference', 'map'}) and not is_set (Periodical))then
if in_array (config.CitationClass, cfg.templates_using_issue) and not (in_array (config.CitationClass, {'conference', 'map'}) and not is_set (Periodical))then
Issue = A['Issue'];
Issue = hyphen_to_dash (A['Issue']);
end
end
local Position = '';
local Position = '';
if not in_array (config.CitationClass, cfg.templates_not_using_page) then
if not in_array (config.CitationClass, cfg.templates_not_using_page) then
Page = A['Page'];
Page = A['Page'];
Pages = hyphen_to_dash( A['Pages'] );
Pages = hyphen_to_dash (A['Pages']);
At = A['At'];
At = A['At'];
end
end
Line 2,631: Line 2,559:
local error_message = '';
local error_message = '';
-- AirDate has been promoted to Date so not necessary to check it
-- AirDate has been promoted to Date so not necessary to check it
-- local date_parameters_list = {['access-date']=AccessDate, ['archive-date']=ArchiveDate, ['date']=Date, ['doi-broken-date']=DoiBroken,
-- ['embargo']=Embargo, ['lay-date']=LayDate, ['publication-date']=PublicationDate, ['year']=Year};
local date_parameters_list = {
local date_parameters_list = {
['access-date'] = {val=AccessDate, name=A:ORIGIN ('AccessDate')},
['access-date'] = {val=AccessDate, name=A:ORIGIN ('AccessDate')},
Line 2,954: Line 2,879:


-- Format main title.
-- Format main title.
if '...' == Title:sub (-3) then -- if elipsis is the last three characters of |title=
if is_set (ArchiveURL) and mw.ustring.match (mw.ustring.lower(Title), cfg.special_case_translation['archived_copy']) then -- if title is 'Archived copy' (place holder added by bots that can't find proper title)
Title = mw.ustring.gsub (Title, '(%.%.%.)%.+$', '%1'); -- limit the number of dots to three
add_maint_cat ('archived_copy'); -- add maintenance category before we modify the content of Title
elseif not mw.ustring.find (Title, '%.%s*%a%.') then -- end of title is not a 'dot-(optional space-)letter-dot' initialism
Title = mw.ustring.gsub(Title, '%'..sepc..'$', ''); -- remove any trailing separator character
end
end
if Title:match ('^%(%(.*%)%)$') then -- if keep as written markup:
Title= Title:gsub ('^%(%((.*)%)%)$', '%1') -- remove the markup
else
if '...' == Title:sub (-3) then -- if elipsis is the last three characters of |title=
Title = Title:gsub ('(%.%.%.)%.+$', '%1'); -- limit the number of dots to three
elseif not mw.ustring.find (Title, '%.%s*%a%.$') and -- end of title is not a 'dot-(optional space-)letter-dot' initialism ...
not mw.ustring.find (Title, '%s+%a%.$') then -- ...and not a 'space-letter-dot' initial (''Allium canadense'' L.)
Title = mw.ustring.gsub(Title, '%'..sepc..'$', ''); -- remove any trailing separator character; sepc and ms.ustring() here for languages that use multibyte separator characters
end
end
if is_set(TitleLink) and is_set(Title) then
if is_set(TitleLink) and is_set(Title) then
Title = make_wikilink (TitleLink, Title);
Title = make_wikilink (TitleLink, Title);
Line 3,459: Line 3,394:




--[[--------------------------< C S 1 . C I T A T I O N >------------------------------------------------------
--[[--------------------------< V A L I D A T E >--------------------------------------------------------------


This is used by templates such as {{cite book}} to create the actual citation text.
Looks for a parameter's name in one of several whitelists.


Parameters in the whitelist can have three values:
true - active, supported parameters
false - deprecated, supported parameters
nil - unsupported parameters
]]
]]


function cs1.citation(frame)
local function validate (name, cite_class)
Frame = frame; -- save a copy incase we need to display an error message in preview mode
local name = tostring (name);
local pframe = frame:getParent()
local state;
local validation, utilities, identifiers, metadata;
if nil ~= string.find (frame:getTitle(), 'sandbox', 1, true) then -- did the {{#invoke:}} use sandbox version?
if in_array (cite_class, {'arxiv', 'biorxiv', 'citeseerx'}) then -- limited parameter sets allowed for these templates
cfg = mw.loadData ('Module:Citation/CS1/Configuration/sandbox'); -- load sandbox versions of support modules
state = whitelist.limited_basic_arguments[name];
whitelist = mw.loadData ('Module:Citation/CS1/Whitelist/sandbox');
if true == state then return true; end -- valid actively supported parameter
utilities = require ('Module:Citation/CS1/Utilities/sandbox');
if false == state then
validation = require ('Module:Citation/CS1/Date_validation/sandbox');
deprecated_parameter (name); -- parameter is deprecated but still supported
identifiers = require ('Module:Citation/CS1/Identifiers/sandbox');
return true;
metadata = require ('Module:Citation/CS1/COinS/sandbox');
end
 
state = whitelist[cite_class .. '_basic_arguments'][name]; -- look in the parameter-list for the template identified by cite_class
 
if true == state then return true; end -- valid actively supported parameter
if false == state then
deprecated_parameter (name); -- parameter is deprecated but still supported
return true;
end
-- limited enumerated parameters list
name = name:gsub("%d+", "#" ); -- replace digit(s) with # (last25 becomes last#) (mw.ustring because non-Western 'local' digits)
state = whitelist.limited_numbered_arguments[name];
if true == state then return true; end -- valid actively supported parameter
if false == state then
deprecated_parameter (name); -- parameter is deprecated but still supported
return true;
end
 
return false; -- not supported because not found or name is set to nil
end -- end limited parameter-set templates
else -- otherwise
state = whitelist.basic_arguments[name]; -- all other templates; all normal parameters allowed
if true == state then return true; end -- valid actively supported parameter
if false == state then
deprecated_parameter (name); -- parameter is deprecated but still supported
return true;
end
-- all enumerated parameters allowed
name = name:gsub("%d+", "#" ); -- replace digit(s) with # (last25 becomes last#) (mw.ustring because non-Western 'local' digits)
state = whitelist.numbered_arguments[name];
 
if true == state then return true; end -- valid actively supported parameter
if false == state then
deprecated_parameter (name); -- parameter is deprecated but still supported
return true;
end
return false; -- not supported because not found or name is set to nil
end
 
 
--[[--------------------------< M I S S I N G _ P I P E _ C H E C K >------------------------------------------
 
Look at the contents of a parameter. If the content has a string of characters and digits followed by an equal
sign, compare the alphanumeric string to the list of cs1|2 parameters.  If found, then the string is possibly a
parameter that is missing its pipe:
{{cite ... |title=Title access-date=2016-03-17}}
 
cs1|2 shares some parameter names with xml/html atributes: class=, title=, etc.  To prevent false positives xml/html
tags are removed before the search.
 
If a missing pipe is detected, this function adds the missing pipe maintenance category.
 
]]
 
local function missing_pipe_check (value)
local capture;
value = value:gsub ('%b<>', ''); -- remove xml/html tags because attributes: class=, title=, etc
 
capture = value:match ('%s+(%a[%a%d]+)%s*=') or value:match ('^(%a[%a%d]+)%s*='); -- find and categorize parameters with possible missing pipes
if capture and validate (capture) then -- if the capture is a valid parameter name
add_maint_cat ('missing_pipe');
end
end
 
 
--[[--------------------------< C S 1 . C I T A T I O N >------------------------------------------------------
 
This is used by templates such as {{cite book}} to create the actual citation text.
 
]]
 
function cs1.citation(frame)
Frame = frame; -- save a copy incase we need to display an error message in preview mode
local pframe = frame:getParent()
local validation, utilities, identifiers, metadata, styles;
if nil ~= string.find (frame:getTitle(), 'sandbox', 1, true) 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
cfg = mw.loadData ('Module:Citation/CS1/Configuration'); -- load live versions of support modules
whitelist = mw.loadData ('Module:Citation/CS1/Whitelist');
whitelist = mw.loadData ('Module:Citation/CS1/Whitelist');
Line 3,485: Line 3,509:
identifiers = require ('Module:Citation/CS1/Identifiers');
identifiers = require ('Module:Citation/CS1/Identifiers');
metadata = require ('Module:Citation/CS1/COinS');
metadata = require ('Module:Citation/CS1/COinS');
styles = 'Module:Citation/CS1/styles.css';
end
end


Line 3,535: Line 3,561:
if v ~= '' then
if v ~= '' then
if ('string' == type (k)) then
if ('string' == type (k)) then
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, config.CitationClass ) then
if not validate( k, config.CitationClass ) then
Line 3,545: Line 3,571:
end
end
elseif validate( k:lower(), config.CitationClass ) then  
elseif validate( k:lower(), config.CitationClass ) then  
error_text, error_state = set_error( 'parameter_ignored_suggest', {k, k:lower()}, true );
error_text, error_state = set_error( 'parameter_ignored_suggest', {k, k:lower()}, true ); -- suggest the lowercase version of the parameter
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
Line 3,557: Line 3,583:
capture = k:match (pattern); -- the whole match if no caputre in pattern else the capture if a match
capture = k:match (pattern); -- the whole match if no caputre in pattern else the capture if a match
if capture then -- if the pattern matches  
if capture then -- if the pattern matches  
param = substitute( param, capture ); -- add the capture to the suggested parameter (typically the enumerator)
param = substitute (param, capture); -- add the capture to the suggested parameter (typically the enumerator)
error_text, error_state = set_error( 'parameter_ignored_suggest', {k, param}, true ); -- set the error message
if validate (param, config.CitationClass) then -- validate the suggestion to make sure that the suggestion is supported by this template (necessary for limited parameter lists)
error_text, error_state = set_error ('parameter_ignored_suggest', {k, param}, true); -- set the suggestion error message
else
error_text, error_state = set_error( 'parameter_ignored', {param}, true ); -- suggested param not supported by this template
end
end
end
end
end
Line 3,587: Line 3,617:
end
end
end
end
return citation0( config, args)
return table.concat ({citation0( config, args), frame:extensionTag ('templatestyles', '', {src=styles})});
end
end


return cs1;
return cs1;
Cookies help us deliver our services. By using our services, you agree to our use of cookies.