Module:Citation/CS1: Difference between revisions

Synch from sandbox;
m>Shyamal
m (Reverted edits by Shyamal (talk) to last version by Trappist the monk)
m>Trappist the monk
(Synch from sandbox;)
Line 167: Line 167:
the URI scheme is valid or whether the URL is otherwise well formed.
the URI scheme is valid or whether the URL is otherwise well formed.


The scheme is checked http://tools.ietf.org/html/std66#section-3.1 which says:
Scheme names consist of a sequence of characters beginning with a
  letter and followed by any combination of letters, digits, plus
  ("+"), period ("."), or hyphen ("-").
First we test for space characters.  If any are found, return false.  Then test for the case where the url is
protocol relative (//example.com).  If the first two characters of the |url= value are //, return true.  Last
look for what appears to be a scheme according to the definition above.  If the characters preceding the colon
are in the allowed set, return true, else false
]]
]]


local function check_url( url_str )
local function check_url( url_str )
return url_str:sub(1,2) == "//" or url_str:match( "^[^/]*:" ) ~= nil; -- Protocol-relative or URL scheme
if nil == url_str:match ("^%S+$") then -- if there are any spaces in |url=value
return false;
end
return url_str:sub(1,2) == "//" or nil ~= url_str:match ("^%a[%a%d%+%.%-]*:") -- protocol relative or scheme part composed of legitimate characters
end
end


Line 334: Line 346:
is not added.  At this time there is no error message for this condition.
is not added.  At this time there is no error message for this condition.


At this writing, only |script-title= is supported.  It is anticipated that additional parameters will be created to use this function.
Supports |script-title= and |script-chapter=


TODO: error messages when prefix is invalid ISO639-1 code; when script_value has prefix but no script;
TODO: error messages when prefix is invalid ISO639-1 code; when script_value has prefix but no script;
Line 352: Line 364:
script_value = script_value:gsub ('^%l%l%s*:%s*', ''); -- strip prefix from script
script_value = script_value:gsub ('^%l%l%s*:%s*', ''); -- strip prefix from script
-- is prefix one of these language codes?
-- is prefix one of these language codes?
if in_array (lang, {'ar', 'bg', 'bs', 'dv', 'el', 'fa', 'hy', 'ja', 'ka', 'ko', 'ku', 'he', 'ps', 'ru', 'sd', 'sr', 'th', 'uk', 'ug', 'yi', 'zh'}) then
if in_array (lang, {'ar', 'bg', 'bs', 'dv', 'el', 'fa', 'he', 'hy', 'ja', 'ka', 'ko', 'ku', 'mk', 'ps', 'ru', 'sd', 'sr', 'th', 'uk', 'ug', 'yi', 'zh'}) then
add_prop_cat ('script_with_name', {name, lang})
add_prop_cat ('script_with_name', {name, lang})
else
else
Line 469: Line 481:
--[[--------------------------< F O R M A T _ C H A P T E R _ T I T L E >--------------------------------------
--[[--------------------------< F O R M A T _ C H A P T E R _ T I T L E >--------------------------------------


Format the three chapter parameters: |chapter=, |trans-chapter=, and |chapter-url= into a single Chapter meta-
Format the four chapter parameters: |script-chapter=, |chapter=, |trans-chapter=, and |chapter-url= into a single Chapter meta-
parameter (chapter_url_source used for error messages).
parameter (chapter_url_source used for error messages).


]]
]]


local function format_chapter_title (chapter, transchapter, chapterurl, chapter_url_source)
local function format_chapter_title (scriptchapter, chapter, transchapter, chapterurl, chapter_url_source)
local chapter_error = '';
local chapter_error = '';
if not is_set (chapter) then
if not is_set (chapter) then
chapter = ''; -- just to be safe for concatenation
chapter = ''; -- to be safe for concatenation
if is_set (transchapter) then
else
chapter = wrap_style ('trans-quoted-title', transchapter);
chapter_error = " " .. set_error ('trans_missing_chapter');
end
if is_set (chapterurl) then
chapter = external_link (chapterurl, chapter, chapter_url_source); -- adds bare_url_missing_title error if appropriate
end
return chapter .. chapter_error;
else -- here when chapter is set
chapter = kern_quotes (chapter); -- if necessary, separate chapter title's leading and trailing quote marks from Module provided quote marks
chapter = kern_quotes (chapter); -- if necessary, separate chapter title's leading and trailing quote marks from Module provided quote marks
chapter = wrap_style ('quoted-title', chapter);
chapter = wrap_style ('quoted-title', chapter);
if is_set (transchapter) then
end
transchapter = wrap_style ('trans-quoted-title', transchapter);
 
chapter = chapter .. ' ' .. transchapter;
chapter = script_concatenate (chapter, scriptchapter) -- <bdi> tags, lang atribute, categorization, etc; must be done after title is wrapped
end
 
if is_set (chapterurl) then
if is_set (transchapter) then
chapter = external_link (chapterurl, chapter); -- adds bare_url_missing_title error if appropriate
transchapter = wrap_style ('trans-quoted-title', transchapter);
if is_set (chapter) then
chapter = chapter .. ' ' .. transchapter;
else -- here when transchapter without chapter or script-chapter
chapter = transchapter; --
chapter_error = ' ' .. set_error ('trans_missing_title', {'chapter'});
end
end
end
end
return chapter;
 
if is_set (chapterurl) then
chapter = external_link (chapterurl, chapter, chapter_url_source); -- adds bare_url_missing_title error if appropriate
end
 
return chapter .. chapter_error;
end
end


--[[
--[[
Line 706: Line 721:
-- prefix=handler.prefix,id=id,separator=handler.separator, encode=handler.encode})
-- prefix=handler.prefix,id=id,separator=handler.separator, encode=handler.encode})
   
   
text="[[" .. handler.link .. "|" .. handler.label .. "]]:" .. handler.separator .. id; -- because no place to link to yet
text="[[" .. handler.link .. "|" .. handler.label .. "]]" .. handler.separator .. id; -- because no place to link to yet


if false == valid_ismn then
if false == valid_ismn then
Line 791: Line 806:
end
end
local handler = cfg.id_handlers['ASIN'];
local handler = cfg.id_handlers['ASIN'];
return external_link_id({link = handler.link,
return external_link_id({link=handler.link,
label=handler.label , prefix="//www.amazon."..domain.."/dp/",id=id,
label=handler.label, prefix=handler.prefix .. domain .. "/dp/",
encode=handler.encode, separator = handler.separator}) .. err_cat;
id=id, encode=handler.encode, separator = handler.separator}) .. err_cat;
end
end


Line 1,093: Line 1,108:
if ( code == "A" ) then
if ( code == "A" ) then
return external_link_id({link=handler.link, label=handler.label,
return external_link_id({link=handler.link, label=handler.label,
prefix="http://openlibrary.org/authors/OL",id=id, separator=handler.separator,
prefix=handler.prefix .. 'authors/OL',
encode = handler.encode})
id=id, separator=handler.separator, encode = handler.encode})
elseif ( code == "M" ) then
elseif ( code == "M" ) then
return external_link_id({link=handler.link, label=handler.label,
return external_link_id({link=handler.link, label=handler.label,
prefix="http://openlibrary.org/books/OL",id=id, separator=handler.separator,
prefix=handler.prefix .. 'books/OL',
encode = handler.encode})
id=id, separator=handler.separator, encode = handler.encode})
elseif ( code == "W" ) then
elseif ( code == "W" ) then
return external_link_id({link=handler.link, label=handler.label,
return external_link_id({link=handler.link, label=handler.label,
prefix= "http://openlibrary.org/works/OL",id=id, separator=handler.separator,
prefix=handler.prefix .. 'works/OL',
encode = handler.encode})
id=id, separator=handler.separator, encode = handler.encode})
else
else
return external_link_id({link=handler.link, label=handler.label,
return external_link_id({link=handler.link, label=handler.label,
prefix= "http://openlibrary.org/OL",id=id, separator=handler.separator,
prefix=handler.prefix .. 'OL',
encode = handler.encode}) ..  
id=id, separator=handler.separator, encode = handler.encode}) .. ' ' .. set_error( 'bad_ol' );
' ' .. set_error( 'bad_ol' );
end
end
end
end
Line 1,469: Line 1,483:
local result = table.concat(text) -- construct list
local result = table.concat(text) -- construct list
if etal and is_set (result) then -- etal may be set by |display-authors=etal but we might not have a last-first list
if etal and is_set (result) then -- etal may be set by |display-authors=etal but we might not have a last-first list
result = result .. ' ' .. cfg.messages['et al']; -- we've go a last-first list and etal so add et al.
result = result .. sep .. ' ' .. cfg.messages['et al']; -- we've go a last-first list and etal so add et al.
end
end
Line 1,492: Line 1,506:
--[[--------------------------< N A M E _ H A S _ E T A L >----------------------------------------------------
--[[--------------------------< N A M E _ H A S _ E T A L >----------------------------------------------------


Evaluates the content of author and editor name parameters for variations on the theme eof et al.  If found,
Evaluates the content of author and editor name parameters for variations on the theme of et al.  If found,
the et al. is removed, a flag is set to true and the function returns the modified name and the flag.
the et al. is removed, a flag is set to true and the function returns the modified name and the flag.


This function never sets the flag to false but returns it's previous state because it may have been set by
This function never sets the flag to false but returns it's previous state because it may have been set by
previous passes through this function or by the parameters |display-authors=etal or |displayeditors=etal
previous passes through this function or by the parameters |display-authors=etal or |display-editors=etal


]]
]]
Line 1,503: Line 1,517:


if is_set (name) then -- name can be nil in which case just return
if is_set (name) then -- name can be nil in which case just return
local pattern = "[;,]? *[\"']*%f[Ee][Ee][Tt] *[Aa][Ll][%.\"']*$" -- variations on the 'et al' theme
local etal_pattern = "[;,]? *[\"']*%f[Ee][Ee][Tt] *[Aa][Ll][%.\"']*$" -- variations on the 'et al' theme
local others_pattern = "[;,]? *%f[%a]and [Oo]thers"; -- and alternate to et al.
if name:match (pattern) then -- variants on et al.
if name:match (etal_pattern) then -- variants on et al.
name = name:gsub (pattern, ''); -- if found, remove
name = name:gsub (etal_pattern, ''); -- if found, remove
etal = true; -- set flag (may have been set previously here or by |display-authors=etal)
if not nocat then -- no categorization for |vauthors=
add_maint_cat ('etal'); -- and add a category if not already added
end
elseif name:match (others_pattern) then -- if not 'et al.', then 'and others'?
name = name:gsub (others_pattern, ''); -- if found, remove
etal = true; -- set flag (may have been set previously here or by |display-authors=etal)
etal = true; -- set flag (may have been set previously here or by |display-authors=etal)
if not nocat then -- no categorization for |vauthors=
if not nocat then -- no categorization for |vauthors=
Line 1,544: Line 1,565:


local err_msg_list_name = list_name:match ("(%w+)List") .. 's list'; -- modify AuthorList or EditorList for use in error messages if necessary
local err_msg_list_name = list_name:match ("(%w+)List") .. 's list'; -- modify AuthorList or EditorList for use in error messages if necessary
while true do
while true do
last = select_one( args, cfg.aliases[list_name .. '-Last'], 'redundant_parameters', i ); -- search through args for name components beginning at 1
last = select_one( args, cfg.aliases[list_name .. '-Last'], 'redundant_parameters', i ); -- search through args for name components beginning at 1
Line 1,650: Line 1,670:
    
    


-- COinS metadata (see <http://ocoins.info/>) allows automated tools to parse
--[[--------------------------< C O I N S >--------------------------------------------------------------------
-- the citation information.
 
COinS metadata (see <http://ocoins.info/>) allows automated tools to parse the citation information.
 
]]
 
local function COinS(data, class)
local function COinS(data, class)
if 'table' ~= type(data) or nil == next(data) then
if 'table' ~= type(data) or nil == next(data) then
Line 1,668: Line 1,692:
});
});
if is_set(data.Chapter) then
if in_array (class, {'citation', 'conference', 'interview', 'press release'}) and is_set(data.Periodical) then
OCinSoutput.rft_val_fmt = "info:ofi/fmt:kev:mtx:book";
OCinSoutput.rft_val_fmt = "info:ofi/fmt:kev:mtx:journal";
OCinSoutput["rft.genre"] = "bookitem";
OCinSoutput["rft.genre"] = "article";
OCinSoutput["rft.atitle"] = data.Chapter;
OCinSoutput["rft.jtitle"] = data.Periodical;
OCinSoutput["rft.btitle"] = data.Title;
OCinSoutput["rft.atitle"] = data.Title;
elseif is_set(data.Periodical) then
elseif in_array (class, {'arxiv', 'journal', 'news'}) then
OCinSoutput.rft_val_fmt = "info:ofi/fmt:kev:mtx:journal";
OCinSoutput.rft_val_fmt = "info:ofi/fmt:kev:mtx:journal";
if 'arxiv' == class then
if 'arxiv' == class then
Line 1,684: Line 1,708:
else
else
OCinSoutput.rft_val_fmt = "info:ofi/fmt:kev:mtx:book";
OCinSoutput.rft_val_fmt = "info:ofi/fmt:kev:mtx:book";
OCinSoutput["rft.genre"] = "book"
if is_set (data.Chapter) then
OCinSoutput["rft.genre"] = "bookitem";
OCinSoutput["rft.atitle"] = data.Chapter;
else
OCinSoutput["rft.genre"] = "book"
end
OCinSoutput["rft.btitle"] = data.Title;
OCinSoutput["rft.btitle"] = data.Title;
end
end
 
OCinSoutput["rft.place"] = data.PublicationPlace;
OCinSoutput["rft.place"] = data.PublicationPlace;
OCinSoutput["rft.date"] = data.Date;
OCinSoutput["rft.date"] = data.Date;
Line 1,710: Line 1,739:
for k, v in ipairs( data.Authors ) do
for k, v in ipairs( data.Authors ) do
last, first = v.last, v.first;
last, first = v.last, v.first;
if k == 1 then
if k == 1 then -- for the first author name only
if is_set(last) then
if is_set(last)  and is_set(first) then -- set these COinS values if |first= and |last= specify the first author name
OCinSoutput["rft.aulast"] = last;
OCinSoutput["rft.aulast"] = last;
OCinSoutput["rft.aufirst"] = first;
elseif is_set(last) then
OCinSoutput["rft.au"] = last; -- otherwise use this form for the first name
end
end
if is_set(first) then  
else -- for all other authors
OCinSoutput["rft.aufirst"] = first;
if is_set(last) and is_set(first) then
OCinSoutput["rft.au"] = table.concat{ last, ", ", first };
elseif is_set(last) then
OCinSoutput["rft.au"] = last;
end
end
end
if is_set(last) and is_set(first) then
OCinSoutput["rft.au"] = table.concat{ last, ", ", first };
elseif is_set(last) then
OCinSoutput["rft.au"] = last;
end
end
end
end
 
OCinSoutput.rft_id = data.URL;
OCinSoutput.rft_id = data.URL;
OCinSoutput.rfr_id = table.concat{ "info:sid/", mw.site.server:match( "[^/]*$" ), ":", data.RawPage };
OCinSoutput.rfr_id = table.concat{ "info:sid/", mw.site.server:match( "[^/]*$" ), ":", data.RawPage };
Line 1,901: Line 1,931:
sep, ps = set_cs1_style (ps);
sep, ps = set_cs1_style (ps);
else -- anything but cs1 or cs2
else -- anything but cs1 or cs2
if is_set (mode) then
table.insert( z.message_tail, { set_error( 'invalid_param_val', {'mode', mode}, true ) } ); -- add error message
end
sep, ps, ref = get_settings_from_cite_class (ps, ref, cite_class); -- get settings based on the template's CitationClass
sep, ps, ref = get_settings_from_cite_class (ps, ref, cite_class); -- get settings based on the template's CitationClass
end
end
Line 1,915: Line 1,942:
--[=[-------------------------< I S _ P D F >------------------------------------------------------------------
--[=[-------------------------< I S _ P D F >------------------------------------------------------------------


Determines if a url has the file extension is one of the pdf file extensions used by [[MediaWiki:Common.css]] when
Determines if a url has the file extension that is one of the pdf file extensions used by [[MediaWiki:Common.css]] when
applying the pdf icon to external links.
applying the pdf icon to external links.


Line 2,025: Line 2,052:
may sometimes be required and because such names will often fail the is_good_vanc_name() and other format compliance
may sometimes be required and because such names will often fail the is_good_vanc_name() and other format compliance
tests, are wrapped in doubled paranethese ((corporate name)) to suppress the format tests.
tests, are wrapped in doubled paranethese ((corporate name)) to suppress the format tests.
This function sets the vancouver error when a reqired comma is missing and when there is a space between an author's initials.


]]
]]
Line 2,051: Line 2,080:
    first = table.remove(lastfirstTable); -- removes and returns value of last element in table which should be author intials
    first = table.remove(lastfirstTable); -- removes and returns value of last element in table which should be author intials
    last  = table.concat(lastfirstTable, " ") -- returns a string that is the concatenation of all other names that are not initials
    last  = table.concat(lastfirstTable, " ") -- returns a string that is the concatenation of all other names that are not initials
    if mw.ustring.match (last, '%a+%s+%u+%s+%a+') or mw.ustring.match (v_name, ' %u %u$') then
add_vanc_error (); -- matches last II last; the case when a comma is missing or a space between two intiials
end
else
else
first = ''; -- set to empty string for concatenation and because it may have been set for previous author/editor
first = ''; -- set to empty string for concatenation and because it may have been set for previous author/editor
Line 2,108: Line 2,140:
if is_set (vxxxxors) then return 2 end;
if is_set (vxxxxors) then return 2 end;
if is_set (xxxxors) then return 3 end;
if is_set (xxxxors) then return 3 end;
return 0; -- no authors so return 0
return 1; -- no authors so return 1; this allows missing author name test to run in case there is a first without last
end
end
--[[--------------------------< I S _ V A L I D _ P A R A M E T E R _ V A L U E >------------------------------
This function is used to validate a parameter's assigned value for those parameters that have only a limited number
of allowable values (yes, y, true, no, etc).  When the parameter value has not been assigned a value (missing or empty
in the source template) the function refurns true.  If the parameter value is one of the list of allowed values returns
true; else, emits an error message and returns false.
]]
local function is_valid_parameter_value (value, name, possible)
if not is_set (value) then
return true; -- an empty parameter is ok
elseif in_array(value:lower(), possible) then
return true;
else
table.insert( z.message_tail, { set_error( 'invalid_param_val', {name, value}, true ) } ); -- not an allowed value so add error message
return false
end
end
--[[--------------------------< I S _ P A R A M E T E R _ E X T _ W I K I L I N K >----------------------------
Return true if a parameter value has a string that begins and ends with square brackets [ and ] and the first
characters following the opening bracket obey the rules of a uri scheme (see check_url()).  The test will also find
external wikilinks that use protocol relative urls.
]]
local function is_parameter_ext_wikilink (value)
if value:match ("%[%a[%a%d%+%.%-]*:.*%]") or value:match ("%[//.*%]") then -- does the param value contain an external wikilink?
return true;
else
return false;
end
end
--[[-------------------------< C H E C K _ F O R _ U R L >-----------------------------------------------------
loop through a list of parameters and their values.  Look at the value and if it has an external link, emit an error message.
]]
local function check_for_url (parameter_list)
local error_message = '';
for k, v in pairs (parameter_list) do -- for each parameter in the list
if is_parameter_ext_wikilink (v) then -- look at the value; if there is a url add an error message
if is_set(error_message) then -- once we've added the first portion of the error message ...
error_message=error_message .. ", "; -- ... add a comma space separator
end
error_message=error_message .. "&#124;" .. k .. "="; -- add the failed parameter
end
end
if is_set (error_message) then -- done looping, if there is an error message, display it
table.insert( z.message_tail, { set_error( 'param_has_ext_link', {error_message}, true ) } );
end
end


--[[--------------------------< C I T A T I O N 0 >------------------------------------------------------------
--[[--------------------------< C I T A T I O N 0 >------------------------------------------------------------
Line 2,128: Line 2,221:
local PPPrefix = A['PPPrefix']
local PPPrefix = A['PPPrefix']
local NoPP = A['NoPP']  
local NoPP = A['NoPP']  
if in_array(NoPP:lower(), {'yes', 'true', 'y'}) then
if is_valid_parameter_value (NoPP, 'nopp', cfg.keywords ['yes_true_y']) then
PPPrefix = ''; -- unset these, prefix if used is in |page= or |pages=
PPPrefix = ''; -- unset these, prefix if used is in |page= or |pages=
PPrefix = '';
PPrefix = '';
Line 2,134: Line 2,227:
NoPP = nil; -- unset, used as a flag later
NoPP = nil; -- unset, used as a flag later
end
end
 
-- Pick out the relevant fields from the arguments.  Different citation templates
-- Pick out the relevant fields from the arguments.  Different citation templates
-- define different field names for the same underlying things.
-- define different field names for the same underlying things.
Line 2,140: Line 2,233:
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 NameListFormat = A['NameListFormat']; -- replaces |author-format= and |editor-format=
local NameListFormat = A['NameListFormat'];


do -- to limit scope of selected
do -- to limit scope of selected
Line 2,173: Line 2,266:
end
end


if is_set (NameListFormat) and ('vanc' ~= NameListFormat) then -- only accepted value for this parameter is 'vanc'
local t = {}; -- translators list from |translator-lastn= / translator-firstn= pairs
table.insert( z.message_tail, { set_error( 'invalid_param_val', {'name-list-format', NameListFormat}, true ) } ); -- not vanc so add error message
local Translators; -- assembled trnaslators name list
NameListFormat = ''; -- set to empty string
t = extract_names (args, 'TranslatorList'); -- fetch translator list from |translatorn= / |translator-lastn=, -firstn=, -linkn=, -maskn=
if not is_valid_parameter_value (NameListFormat, 'name-list-format', cfg.keywords['name-list-format']) then -- only accepted value for this parameter is 'vanc'
NameListFormat = ''; -- anything else, set to empty string
end
end


Line 2,192: Line 2,288:
local TitleLink = A['TitleLink'];
local TitleLink = A['TitleLink'];
local Chapter = A['Chapter'];
local Chapter = A['Chapter'];
local ChapterLink = A['ChapterLink']; -- deprecated but used internally by cite episode
local ScriptChapter = A['ScriptChapter'];
local ChapterLink -- = A['ChapterLink']; -- deprecated as a parameter but still used internally by cite episode
local TransChapter = A['TransChapter'];
local TransChapter = A['TransChapter'];
local TitleType = A['TitleType'];
local TitleType = A['TitleType'];
Line 2,222: Line 2,319:
local PublisherName = A['PublisherName'];
local PublisherName = A['PublisherName'];
local RegistrationRequired = A['RegistrationRequired'];
local RegistrationRequired = A['RegistrationRequired'];
if not is_valid_parameter_value (RegistrationRequired, 'registration', cfg.keywords ['yes_true_y']) then
registration=nil;
end
local SubscriptionRequired = A['SubscriptionRequired'];
local SubscriptionRequired = A['SubscriptionRequired'];
if not is_valid_parameter_value (SubscriptionRequired, 'subscription', cfg.keywords ['yes_true_y']) then
subscription=nil;
end
local Via = A['Via'];
local Via = A['Via'];
local AccessDate = A['AccessDate'];
local AccessDate = A['AccessDate'];
Line 2,228: Line 2,332:
local Agency = A['Agency'];
local Agency = A['Agency'];
local DeadURL = A['DeadURL']
local DeadURL = A['DeadURL']
if not is_valid_parameter_value (DeadURL, 'dead-url', cfg.keywords ['deadurl']) then -- set in config.defaults to 'yes'
DeadURL = ''; -- anything else, set to empty string
end
local Language = A['Language'];
local Language = A['Language'];
local Format = A['Format'];
local Format = A['Format'];
Line 2,235: Line 2,343:
local ASINTLD = A['ASINTLD'];
local ASINTLD = A['ASINTLD'];
local IgnoreISBN = A['IgnoreISBN'];
local IgnoreISBN = A['IgnoreISBN'];
if not is_valid_parameter_value (IgnoreISBN, 'ignore-isbn-error', cfg.keywords ['yes_true_y']) then
IgnoreISBN = nil; -- anything else, set to empty string
end
local Embargo = A['Embargo'];
local Embargo = A['Embargo'];
local Class = A['Class']; -- arxiv class identifier
local Class = A['Class']; -- arxiv class identifier
Line 2,251: Line 2,362:


local LastAuthorAmp = A['LastAuthorAmp'];
local LastAuthorAmp = A['LastAuthorAmp'];
if not is_valid_parameter_value (LastAuthorAmp, 'last-author-amp', cfg.keywords ['yes_true_y']) then
LastAuthorAmp = nil; -- set to empty string
end
local no_tracking_cats = A['NoTracking'];
local no_tracking_cats = A['NoTracking'];
if not is_valid_parameter_value (no_tracking_cats, 'no-tracking', cfg.keywords ['yes_true_y']) then
no_tracking_cats = nil; -- set to empty string
end


--these are used by cite interview
--these are used by cite interview
Line 2,265: Line 2,382:


-- set default parameter values defined by |mode= parameter.  If |mode= is empty or omitted, use CitationClass to set these values
-- set default parameter values defined by |mode= parameter.  If |mode= is empty or omitted, use CitationClass to set these values
local Mode = A['Mode'];
if not is_valid_parameter_value (Mode, 'mode', cfg.keywords['mode']) then
Mode = '';
end
local sepc; -- separator between citation elements for CS1 a period, for CS2, a comma
local sepc; -- separator between citation elements for CS1 a period, for CS2, a comma
local PostScript;
local PostScript;
local Ref;
local Ref;
sepc, PostScript, Ref = set_style (A['Mode']:lower(), A['PostScript'], A['Ref'], config.CitationClass);
sepc, PostScript, Ref = set_style (Mode:lower(), A['PostScript'], A['Ref'], config.CitationClass);
use_lowercase = ( sepc == ',' ); -- used to control capitalization for certain static text
use_lowercase = ( sepc == ',' ); -- used to control capitalization for certain static text


Line 2,318: Line 2,439:


All other combinations of |encyclopedia, |title, and |article are not modified
All other combinations of |encyclopedia, |title, and |article are not modified
TODO: script-title to script-chapter if and when we support script-chapter
 
]]
]]


Line 2,324: Line 2,445:


if ( config.CitationClass == "encyclopaedia" ) or ( config.CitationClass == "citation" and is_set (Encyclopedia)) then -- test code for citation
if ( config.CitationClass == "encyclopaedia" ) or ( config.CitationClass == "citation" and is_set (Encyclopedia)) then -- test code for citation
if is_set(Periodical) then -- Periodical is set when |encyclopedia is set
if is_set(Periodical) then -- Periodical is set when |encyclopedia is set
if is_set(Title) then
if is_set(Title) or is_set (ScriptTitle) then
if not is_set(Chapter) then
if not 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;
TransChapter = TransTitle;
TransChapter = TransTitle;
ChapterURL = URL;
ChapterURL = URL;
Line 2,335: Line 2,457:
Title = Periodical;
Title = Periodical;
ChapterFormat = Format;
ChapterFormat = Format;
Periodical = ''; -- redundant so unset
Periodical = ''; -- redundant so unset
TransTitle = ''; -- redundant so unset
TransTitle = '';
URL = ''; -- redundant so unset
URL = '';
Format = ''; -- redundant so unset
Format = '';
TitleLink = ''; -- redundant so unset
TitleLink = '';
ScriptTitle = '';
end
end
else -- |title not set
else -- |title not set
Title = Periodical; -- |encyclopedia set and |article set or not set so map |encyclopedia to |title
Title = Periodical; -- |encyclopedia set and |article set or not set so map |encyclopedia to |title
Periodical = ''; -- redundant so unset
Periodical = ''; -- redundant so unset
end
end
end
end
Line 2,442: Line 2,565:
if 'episode' == config.CitationClass or 'serial' == config.CitationClass then
if 'episode' == config.CitationClass or 'serial' == config.CitationClass then
local AirDate = A['AirDate'];
local AirDate = A['AirDate'];
local Began = A['Began']; -- these two are deprecated because the module understands date ranges
local Ended = A['Ended'];
local SeriesLink = A['SeriesLink'];
local SeriesLink = A['SeriesLink'];
local Network = A['Network'];
local Network = A['Network'];
Line 2,457: Line 2,578:
if is_set (AirDate) then
if is_set (AirDate) then
Date = AirDate;
Date = AirDate;
elseif is_set (Began) then -- deprecated
if Began:match('%s') or Ended:match('%s') then -- so we don't create errors: if either has spaces then
Date = Began .. ' – ' .. Ended; -- use spaced ndash as separator
else
Date = Began .. '–' .. Ended; -- elsewise no spaces
end
end
end
end
end
Line 2,481: Line 2,596:
Chapter = Title; -- promote title parameters to chapter
Chapter = Title; -- promote title parameters to chapter
ScriptChapter = ScriptTitle;
ChapterLink = TitleLink; -- alias episodelink
ChapterLink = TitleLink; -- alias episodelink
TransChapter = TransTitle;
TransChapter = TransTitle;
Line 2,496: Line 2,612:
end
end
URL = ''; -- unset
URL = ''; -- unset
TransTitle = ''; -- unset
TransTitle = '';
ScriptTitle = '';
else -- now oddities that are cite serial
else -- now oddities that are cite serial
Issue = ''; -- unset because this parameter no longer supported by the citation/core version of cite serial
Issue = ''; -- unset because this parameter no longer supported by the citation/core version of cite serial
Chapter = A['Episode']; -- TODO: make |episode= available to cite episode someday?
Chapter = A['Episode']; -- TODO: make |episode= available to cite episode someday?
if is_set (Series) and is_set (SeriesLink) then
if is_set (Series) and is_set (SeriesLink) then
Line 2,550: Line 2,667:
-- legacy: promote concatenation of |month=, and |year= to Date if Date not set; or, promote PublicationDate to Date if neither Date nor Year are set.
-- legacy: promote concatenation of |month=, and |year= to Date if Date not set; or, promote PublicationDate to Date if neither Date nor Year are set.
if not is_set (Date) then
if not is_set (Date) then
Date = Year; -- promote Year to Date
Date = Year; -- promote Year to Date
Year = nil; -- make nil so Year as empty string isn't used for CITEREF
Year = nil; -- make nil so Year as empty string isn't used for CITEREF
if is_set(Date) then
if not is_set (Date) and is_set(PublicationDate) then -- use PublicationDate when |date= and |year= are not set
local Month = A['Month'];
Date = PublicationDate; -- promote PublicationDate to Date
if is_set(Month) then
PublicationDate = ''; -- unset, no longer needed
Date = Month .. " " .. Date;
end
elseif is_set(PublicationDate) then -- use PublicationDate when |date= and |year= are not set
Date = PublicationDate; -- promote PublicationDate to Date
PublicationDate = ''; -- unset, no longer needed
end
end
end
end
Line 2,574: Line 2,686:
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
anchor_year, COinS_date, error_message = dates({['accessdate']=AccessDate, ['archivedate']=ArchiveDate, ['date']=Date, ['doi_brokendate']=DoiBroken,
anchor_year, COinS_date, error_message = dates({['access-date']=AccessDate, ['archive-date']=ArchiveDate, ['date']=Date, ['doi-broken-date']=DoiBroken,
['embargo']=Embargo, ['laydate']=LayDate, ['publicationdate']=PublicationDate, ['year']=Year});
['embargo']=Embargo, ['lay-date']=LayDate, ['publication-date']=PublicationDate, ['year']=Year});


if is_set (Year) and is_set (Date) then -- both |date= and |year= not normally needed;  
if is_set (Year) and is_set (Date) then -- both |date= and |year= not normally needed;  
Line 2,610: Line 2,722:
not is_set(TransTitle) and
not is_set(TransTitle) and
not is_set(ScriptTitle) then
not is_set(ScriptTitle) then
table.insert( z.message_tail, { set_error( 'citation_missing_title', {}, true ) } );
if 'episode' == config.CitationClass then -- special case for cite episode; is there a better way to do this?
table.insert( z.message_tail, { set_error( 'citation_missing_title', {'series'}, true ) } );
else
table.insert( z.message_tail, { set_error( 'citation_missing_title', {'title'}, true ) } );
end
end
end
Line 2,617: Line 2,733:
add_maint_cat ('untitled');
add_maint_cat ('untitled');
end
end
check_for_url ({['title']=Title, ['chapter']=Chapter, ['work']=Periodical}); -- adds error message when any of these parameters contain a URL


-- COinS metadata (see <http://ocoins.info/>) for automated parsing of citation information.
-- COinS metadata (see <http://ocoins.info/>) for automated parsing of citation information.
Line 2,635: Line 2,753:
local OCinSoutput = COinS({
local OCinSoutput = COinS({
['Periodical'] = Periodical,
['Periodical'] = Periodical,
['Chapter'] = strip_apostrophe_markup (coins_chapter), -- Chapter stripped of bold / italic wikimarkup
['Chapter'] = make_coins_title (coins_chapter, ScriptChapter), -- Chapter and ScriptChapter stripped of bold / italic wikimarkup
['Title'] = make_coins_title (coins_title, ScriptTitle), -- Title and ScriptTitle stripped of bold / italic wikimarkup
['Title'] = make_coins_title (coins_title, ScriptTitle), -- Title and ScriptTitle stripped of bold / italic wikimarkup
['PublicationPlace'] = PublicationPlace,
['PublicationPlace'] = PublicationPlace,
Line 2,668: Line 2,786:
-- We also add leading spaces and surrounding markup and punctuation to the
-- We also add leading spaces and surrounding markup and punctuation to the
-- various parts of the citation, but only when they are non-nil.
-- various parts of the citation, but only when they are non-nil.
local EditorCount; -- used only for choosing {ed.) or (eds.) annotation at end of editor name-list
do
local last_first_list;
local maximum;
local control = {
format = NameListFormat, -- empty string or 'vanc'
maximum = nil, -- as if display-authors or display-editors not set
lastauthoramp = LastAuthorAmp,
page_name = this_page.text -- get current page name so that we don't wikilink to it via editorlinkn
};
do -- do editor name list first because coauthors can modify control table
maximum , editor_etal = get_display_authors_editors (A['DisplayEditors'], #e, 'editors', editor_etal);
-- Preserve old-style implicit et al.
if not is_set(maximum) and #e == 4 then
maximum = 3;
table.insert( z.message_tail, { set_error('implict_etal_editor', {}, true) } );
end
control.maximum = maximum;
last_first_list, EditorCount = list_people(control, e, editor_etal);
if is_set (Editors) then
if editor_etal then
Editors = Editors .. ' ' .. cfg.messages['et al']; -- add et al. to editors parameter beause |display-editors=etal
EditorCount = 2; -- with et al., |editors= is multiple names; spoof to display (eds.) annotation
else
EditorCount = 2; -- we don't know but assume |editors= is multiple names; spoof to display (eds.) annotation
end
else
Editors = last_first_list; -- either an author name list or an empty string
end
if 1 == EditorCount and (true == editor_etal or 1 < #e) then -- only one editor displayed but includes etal then
EditorCount = 2; -- spoof to display (eds.) annotation
end
end
do -- now do translators
control.maximum = #t; -- number of translators
Translators = list_people(control, t, false); -- et al not currently supported
end
do -- now do authors
control.maximum , author_etal = get_display_authors_editors (A['DisplayAuthors'], #a, 'authors', author_etal);
if is_set(Coauthors) then -- if the coauthor field is also used, prevent ampersand and et al. formatting.
control.lastauthoramp = nil;
control.maximum = #a + 1;
end
last_first_list = list_people(control, a, author_etal);
if is_set (Authors) then
Authors, author_etal = name_has_etal (Authors, author_etal, false); -- find and remove variations on et al.
if author_etal then
Authors = Authors .. ' ' .. cfg.messages['et al']; -- add et al. to authors parameter
end
else
Authors = last_first_list; -- either an author name list or an empty string
end
end -- end of do
if not is_set(Authors) and is_set(Coauthors) then -- coauthors aren't displayed if one of authors=, authorn=, or lastn= isn't specified
table.insert( z.message_tail, { set_error('coauthors_missing_author', {}, true) } ); -- emit error message
end
end
--[[
do -- do-block to limit scope of last_first_list
do -- do-block to limit scope of last_first_list
local last_first_list;
local last_first_list;
Line 2,739: Line 2,928:
end
end
end
end
 
]]


-- apply |[xx-]format= styling; at the end, these parameters hold correctly styled format annotation,
-- apply |[xx-]format= styling; at the end, these parameters hold correctly styled format annotation,
Line 2,791: Line 2,980:
if in_array(config.CitationClass, {"web","news","journal","pressrelease","podcast", "newsgroup", 'arxiv'}) or
if in_array(config.CitationClass, {"web","news","journal","pressrelease","podcast", "newsgroup", 'arxiv'}) or
('citation' == config.CitationClass and is_set (Periodical) and not is_set (Encyclopedia)) then
('citation' == config.CitationClass and is_set (Periodical) and not is_set (Encyclopedia)) then
if is_set (Chapter) or is_set (TransChapter) or is_set (ChapterURL)then -- chapter parameters not supported for these citation types
if is_set (Chapter) or is_set (TransChapter) or is_set (ChapterURL) or is_set (ScriptChapter) then -- chapter parameters not supported for these citation types
table.insert( z.message_tail, { set_error( 'chapter_ignored', {}, true ) } ); -- add error message
table.insert( z.message_tail, { set_error( 'chapter_ignored', {A:ORIGIN ('Chapter')}, true ) } ); -- add error message
Chapter = ''; -- set to empty string to be safe with concatenation
Chapter = ''; -- set them to empty string to be safe with concatenation
TransChapter = '';
TransChapter = '';
ChapterURL = '';
ChapterURL = '';
ScriptChapter = '';
end
end
else -- otherwise, format chapter / article title
else -- otherwise, format chapter / article title
Chapter = format_chapter_title (Chapter, TransChapter, ChapterURL, ChapterURLorigin);
Chapter = format_chapter_title (ScriptChapter, Chapter, TransChapter, ChapterURL, ChapterURLorigin);
if is_set (Chapter) then
if is_set (Chapter) then
if 'map' == config.CitationClass and is_set (TitleType) then
if 'map' == config.CitationClass and is_set (TitleType) then
Line 2,834: Line 3,024:
TransTitle = " " .. TransTitle;
TransTitle = " " .. TransTitle;
else
else
TransError = " " .. set_error( 'trans_missing_title' );
TransError = " " .. set_error( 'trans_missing_title', {'title'} );
end
end
end
end
Line 2,963: Line 3,153:


Others = is_set(Others) and (sepc .. " " .. Others) or "";
Others = is_set(Others) and (sepc .. " " .. Others) or "";
if is_set (Translators) then
Others = sepc .. ' Translated by ' .. Translators .. Others;
end


TitleNote = is_set(TitleNote) and (sepc .. " " .. TitleNote) or "";
TitleNote = is_set(TitleNote) and (sepc .. " " .. TitleNote) or "";
if is_set (Edition) then
if is_set (Edition) then
if Edition:match ('[Ee]d%.?$') or Edition:match ('[Ee]dition$') then
if Edition:match ('%f[%a][Ee]d%.?$') or Edition:match ('%f[%a][Ee]dition$') then
add_maint_cat ('extra_text', 'edition');
add_maint_cat ('extra_text', 'edition');
end
end
Line 2,995: Line 3,189:


]]
]]
if in_array(SubscriptionRequired:lower(), {'yes', 'true', 'y'}) then
if is_set (SubscriptionRequired) then
SubscriptionRequired = sepc .. " " .. cfg.messages['subscription']; -- subscription required message
SubscriptionRequired = sepc .. " " .. cfg.messages['subscription']; -- subscription required message
elseif in_array(RegistrationRequired:lower(), {'yes', 'true', 'y'}) then
elseif is_set (RegistrationRequired) then
SubscriptionRequired = sepc .. " " .. cfg.messages['registration']; -- registration required message
SubscriptionRequired = sepc .. " " .. cfg.messages['registration']; -- registration required message
else
else
Line 3,048: Line 3,242:
Archived = Archived .. " " .. set_error('archive_missing_url');    
Archived = Archived .. " " .. set_error('archive_missing_url');    
end
end
elseif is_set(OriginalURL) then
elseif is_set(OriginalURL) then -- DeadURL is empty, 'yes', 'true', 'y', 'unfit', 'usurped'
local arch_text = cfg.messages['archived-dead'];
local arch_text = cfg.messages['archived-dead'];
if sepc ~= "." then arch_text = arch_text:lower() end
if sepc ~= "." then arch_text = arch_text:lower() end
Archived = sepc .. " " .. substitute( arch_text,
-- if 'usurped' == DeadURL then -- when original has unsuitable content do not link
{ external_link( OriginalURL, cfg.messages['original'] ) .. OriginalFormat, ArchiveDate } ); -- format already styled
if in_array (DeadURL, {'unfit', 'usurped'}) then
Archived = sepc .. " " .. 'Archived from the original on ' .. ArchiveDate; -- format already styled
else -- DeadURL is empty, 'yes', 'true', or 'y'
Archived = sepc .. " " .. substitute( arch_text,
{ external_link( OriginalURL, cfg.messages['original'] ) .. OriginalFormat, ArchiveDate } ); -- format already styled
end
else
else
local arch_text = cfg.messages['archived-missing'];
local arch_text = cfg.messages['archived-missing'];
Line 3,267: Line 3,466:
text = safe_join( {text, PostScript}, sepc );
text = safe_join( {text, PostScript}, sepc );


-- Now enclose the whole thing in a <span/> element
-- Now enclose the whole thing in a <cite/> element
local options = {};
local options = {};
if is_set(config.CitationClass) and config.CitationClass ~= "citation" then
if is_set(config.CitationClass) and config.CitationClass ~= "citation" then
options.class = "citation " .. config.CitationClass;
options.class = config.CitationClass;
options.class = "citation " .. config.CitationClass; -- class=citation required for blue highlight when used with |ref=
else
else
options.class = "citation";
options.class = "citation";
Line 3,304: Line 3,504:
if is_set(options.id) then  
if is_set(options.id) then  
text = '<span id="' .. mw.uri.anchorEncode(options.id) ..'" class="' .. mw.text.nowiki(options.class) .. '">' .. text .. "</span>";
text = '<cite id="' .. mw.uri.anchorEncode(options.id) ..'" class="' .. mw.text.nowiki(options.class) .. '">' .. text .. "</cite>";
else
else
text = '<span class="' .. mw.text.nowiki(options.class) .. '">' .. text .. "</span>";
text = '<cite class="' .. mw.text.nowiki(options.class) .. '">' .. text .. "</cite>";
end
end


Line 3,381: Line 3,581:
end
end


local capture; -- the single supported capture when matching unknown parameters using patterns
for k, v in pairs( pframe.args ) do
for k, v in pairs( pframe.args ) do
if v ~= '' then
if v ~= '' then
Line 3,393: Line 3,594:
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 );
else
else
if #suggestions == 0 then
if nil == suggestions.suggestions then -- if this table is nil then we need to load it
suggestions = mw.loadData( 'Module:Citation/CS1/Suggestions' );
if nil ~= string.find (frame:getTitle(), 'sandbox', 1, true) 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
for pattern, param in pairs (suggestions.patterns) do -- loop through the patterns to see if we can suggest a proper parameter
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
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
end
end
end
if suggestions[ k:lower() ] ~= nil then
if not is_set (error_text) then -- couldn't match with a pattern, is there an expicit suggestion?
error_text, error_state = set_error( 'parameter_ignored_suggest', {k, suggestions[ k:lower() ]}, true );
if suggestions.suggestions[ k:lower() ] ~= nil then
else
error_text, error_state = set_error( 'parameter_ignored_suggest', {k, suggestions.suggestions[ k:lower() ]}, true );
error_text, error_state = set_error( 'parameter_ignored', {k}, true );
else
error_text, error_state = set_error( 'parameter_ignored', {k}, true );
end
end
end
-- if #suggestions == 0 then
-- suggestions = mw.loadData( 'Module:Citation/CS1/Suggestions' );
-- end
-- if suggestions[ k:lower() ] ~= nil then
-- error_text, error_state = set_error( 'parameter_ignored_suggest', {k, suggestions[ k:lower() ]}, true );
-- else
-- error_text, error_state = set_error( 'parameter_ignored', {k}, true );
-- end
end    
end    
if error_text ~= '' then
if error_text ~= '' then
Anonymous user