Module:Citation/CS1: Difference between revisions

Sync from sandbox; Bug fixes; streamlined deprecated parameter detection; Year and PublicationDate promotion to Date consolidation; Change pmc/url handling; Modify parameter handling for cite encyclopedia;
m>Trappist the monk
(Fix sandbox oversight;)
m>Trappist the monk
(Sync from sandbox; Bug fixes; streamlined deprecated parameter detection; Year and PublicationDate promotion to Date consolidation; Change pmc/url handling; Modify parameter handling for cite encyclopedia;)
Line 1: Line 1:
--[[
History of changes since last sync 2013-11-09
2013-11-13: Fix Script Error bug that occured when |doi_brokendate= did not contain a year value;
2013-11-13: Fix doi() so that dois with invalid doi_brokendate categorize to "Pages with inactive DOIs" and not to "Pages with DOIs inactive since";
2013-11-14: Change deprecated_parameter() to emit a single error message;
2013-11-15: Fix bug in checkisbn() that stripped-out non-isbn character before validation; declared good as long as the stripped version of the isbn passed the remaining tests;
2013-11-21: Year and PublicationDate promotion to Date consolidation;
2013-11-22: Change validate() and the whitelist to recognize deprecated parameters;
2013-11-30: Change pmc/url handling;
2013-12-05: Modify |encyclopedia, |title and |article parameter handling for cite encyclopedia;
]]
local z = {
local z = {
     error_categories = {};
     error_categories = {};
Line 39: Line 52:
end
end


-- Add this page to the deprecated parameter tracking category
--[[
Categorize and emit an error message when the citation contains one or more deprecated parameters.  Because deprecated parameters (currently |day=, |month=,
|coauthor=, and |coauthors=) aren't related to each other and because these parameters may be concatenated into the variables used by |date= and |author#= (and aliases)
details of which parameter caused the error message are not provided.  Only one error message is emitted regarless of the number of deprecated parameters in the citation.
]]
function deprecated_parameter()
function deprecated_parameter()
if true ~= Page_in_deprecated_cat then -- if we haven't been here before then set a  
if true ~= Page_in_deprecated_cat then -- if we haven't been here before then set a  
Page_in_deprecated_cat=true; -- sticky flag so that if there are more than one deprecated parameter the category is added only once
Page_in_deprecated_cat=true; -- sticky flag so that if there are more than one deprecated parameter the category is added only once
table.insert( z.error_categories, "Pages containing cite templates with deprecated parameters" ); -- add page to category
table.insert( z.message_tail, { seterror( 'deprecated_params', {error_message}, true ) } ); -- add error message
end
end
end
end
Line 113: Line 130:
end
end


-- Checks that parameter name is valid using the whitelist
--[[
Looks for a parameter's name in the whitelist.
 
Parameters in the whitelist can have three valuse:
true - active, supported parameters
false - deprecated, supported parameters
nil - unsupported parameters
]]
function validate( name )
function validate( name )
    name = tostring( name );
local name = tostring( name );
   
local state = whitelist.basic_arguments[ name ];
    -- Normal arguments
    if whitelist.basic_arguments[ name ] then
-- Normal arguments
        return true;
if true == state then return true; end -- valid actively supported parameter
    end
if false == state then
   
deprecated_parameter (); -- parameter is deprecated but still supported
    -- Arguments with numbers in them
return true;
    name = name:gsub( "%d+", "#" );
end
    if whitelist.numbered_arguments[ name ] then
        return true;
-- Arguments with numbers in them
    end
name = name:gsub( "%d+", "#" ); -- replace digit(s) with # (last25 becomes last#
   
state = whitelist.numbered_arguments[ name ];
    -- Not found, argument not supported.
if true == state then return true; end -- valid actively supported parameter
    return false
if false == state then
deprecated_parameter (); -- parameter is deprecated but still supported
return true;
end
return false; -- Not supported because not found or name is set to nil
end
end


Line 227: Line 256:


--[[
--[[
Formats a PMC and checks for embargoed articles. The embargo parameter takes a date for a value. If the embargo date is in the futue
Determines if a PMC identifier's online version is embargoed. Compares the date in |embargo= against today's date. If embargo date is
the PMC identifier will not be linked to the article.  If the embargo specifies a date in the past, or if it is empty or omitted, then
in the future, returns true; otherwse, returns false because the embargo has expired or |embargo= not set in this cite.
the PMC identifier is linked to the article through the link at cfg.id_handlers['PMC'].link.
 
The {{citation/core}} version of {{cite journal}} links the citation title (if url parameter is empty) when embargo date is in the past
or when embargo parameter is missing or empty. That behavior is inconsistent with the behavior of other identifiers used in CS1 and is
not supported here.
]]
]]
function pmc(id, embargo)
function is_embargoed(embargo)
local handler = cfg.id_handlers['PMC'];
   
local text;
if is_set(embargo) then
if is_set(embargo) then
local lang = mw.getContentLanguage();
local lang = mw.getContentLanguage();
Line 245: Line 265:
good1, embargo_date = pcall( lang.formatDate, lang, 'U', embargo );
good1, embargo_date = pcall( lang.formatDate, lang, 'U', embargo );
good2, todays_date = pcall( lang.formatDate, lang, 'U' );
good2, todays_date = pcall( lang.formatDate, lang, 'U' );
if good1 and good2 and tonumber( embargo_date ) >= tonumber( todays_date ) then --is embargo date is in the future?
return true; -- still embargoed
end
end
return false; -- embargo expired or |embargo= not set
end


if good1 and good2 and tonumber( embargo_date ) < tonumber( todays_date ) then --if embargo date is in the past then
--[[
text = externallinkid({link = handler.link, label = handler.label, --ok to link to article
Formats a PMC and checks for embargoed articles.  The embargo parameter takes a date for a value. If the embargo date is in the future
prefix=handler.prefix,id=id,separator=handler.separator, encode=handler.encode})
the PMC identifier will not be linked to the article.  If the embargo specifies a date in the past, or if it is empty or omitted, then
else
the PMC identifier is linked to the article through the link at cfg.id_handlers['PMC'].prefix.
text="[[" .. handler.link .. "|" .. handler.label .. "]]:" .. handler.separator .. id; --still embargoed so no external link
]]
end
function pmc(id, embargo)
local handler = cfg.id_handlers['PMC'];
   
local text;
 
if is_embargoed(embargo) then
text="[[" .. handler.link .. "|" .. handler.label .. "]]:" .. handler.separator .. id; --still embargoed so no external link
else
else
text = externallinkid({link = handler.link, label = handler.label, --no embargo date, ok to link to article
text = externallinkid({link = handler.link, label = handler.label, --no embargo date, ok to link to article
prefix=handler.prefix,id=id,separator=handler.separator, encode=handler.encode})
prefix=handler.prefix,id=id,separator=handler.separator, encode=handler.encode})
end
end
return text
return text;
end
end


Line 265: Line 298:
      
      
     local text;
     local text;
    if is_set(inactive) then
if is_set(inactive) then
        text = "[[" .. handler.link .. "|" .. handler.label .. "]]:" .. id;
local inactive_year = inactive:match("%d%d%d%d") or ''; -- try to get the year portion from the inactive date
        table.insert( z.error_categories, "Pages with DOIs inactive since " .. selectyear(inactive) );      
text = "[[" .. handler.link .. "|" .. handler.label .. "]]:" .. id;
        inactive = " (" .. cfg.messages['inactive'] .. " " .. inactive .. ")"  
if is_set(inactive_year) then
    else  
table.insert( z.error_categories, "Pages with DOIs inactive since " .. inactive_year );
        text = externallinkid({link = handler.link, label = handler.label,
else
            prefix=handler.prefix,id=id,separator=handler.separator, encode=handler.encode})
table.insert( z.error_categories, "Pages with inactive DOIs" ); -- when inactive doesn't contain a recognizable year
        inactive = ""  
end
    end
inactive = " (" .. cfg.messages['inactive'] .. " " .. inactive .. ")"  
    if ( string.sub(id,1,3) ~= "10." ) then       
else  
        cat = seterror( 'bad_doi' );
text = externallinkid({link = handler.link, label = handler.label,
    end
prefix=handler.prefix,id=id,separator=handler.separator, encode=handler.encode})
    return text .. inactive .. cat  
inactive = ""  
end
if ( string.sub(id,1,3) ~= "10." ) then       
cat = seterror( 'bad_doi' );
end
return text .. inactive .. cat  
end
end


Line 344: Line 382:
end
end


-- returns a number according to the month in a date 1 for January, etc.  If not a valid month, returns 0
--[[
function get_month_number (month)
This function sets default title types (equivalent to the citation including |type=<default value>) for those citations that have defaults.
local long_months = {['january']=1, ['february']=2, ['march']=3, ['april']=4, ['may']=5, ['june']=6, ['july']=7, ['august']=8, ['september']=9, ['october']=10, ['november']=11, ['december']=12};
Also handles the special case where it is desireable to omit the title type from the rendered citation (|type=none).
local short_months = {['jan']=1, ['feb']=2, ['mar']=3, ['apr']=4, ['may']=5, ['jun']=6, ['jul']=7, ['aug']=8, ['sep']=9, ['oct']=10, ['nov']=11, ['dec']=12};
]]
function set_titletype(cite_class, title_type)
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
 
if "pressrelease" == cite_class then -- if this citation is cite press release
return "Press release"; -- display press release annotation
 
elseif "speech" == cite_class then -- if this citation is cite speech
return "Speech"; -- display speech annotation
elseif "techreport" == cite_class then -- if this citation is cite techreport
return "Technical report"; -- display techreport annotation
elseif "thesis" == cite_class then -- if this citation is cite thesis (degree option handled after this function returns)
return "Thesis"; -- display simple thesis annotation (without |degree= modification)
end
end
 
-- returns a number according to the month in a date: 1 for January, etc.  If not a valid month, returns 0
function get_month_number (month)
local long_months = {['january']=1, ['february']=2, ['march']=3, ['april']=4, ['may']=5, ['june']=6, ['july']=7, ['august']=8, ['september']=9, ['october']=10, ['november']=11, ['december']=12};
local short_months = {['jan']=1, ['feb']=2, ['mar']=3, ['apr']=4, ['may']=5, ['jun']=6, ['jul']=7, ['aug']=8, ['sep']=9, ['oct']=10, ['nov']=11, ['dec']=12};
local temp;
local temp;
temp=long_months[month:lower()];
temp=long_months[month:lower()];
if temp then return temp; end -- if month is the long-form name
if temp then return temp; end -- if month is the long-form name
temp=short_months[month:lower()];
temp=short_months[month:lower()];
if temp then return temp; end -- if month is the short-form name
if temp then return temp; end -- if month is the short-form name
return 0; -- misspelled or not a month name
return 0; -- misspelled or not a month name
end
end


Line 373: Line 437:
local days_in_month = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
local days_in_month = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
local month_length;
local month_length;
if (2==month) then -- if February
if (2==month) then -- if February
month_length = 28; -- then 28 days unless
month_length = 28; -- then 28 days unless
if 1582 > tonumber(year) then -- Julian calendar
if 1582 > tonumber(year) then -- Julian calendar
if 0==(year%4) then
if 0==(year%4) then
month_length = 29;
month_length = 29;
end
end
else -- Gregorian calendar
else -- Gregorian calendar
if (0==(year%4) and (0~=(year%100) or 0==(year%400))) then -- date specifies a leap year
if (0==(year%4) and (0~=(year%100) or 0==(year%400))) then -- is a leap year?
month_length = 29; -- if leap year then 29 days in February
month_length = 29; -- if leap year then 29 days in February
end
end
end
end
Line 395: Line 459:


--Check a pair of months or seasons to see if both are valid members of a month or season pair.
--Check a pair of months or seasons to see if both are valid members of a month or season pair.
--TODO: Check order to make sure that the left month/season properly precedes the right month/season


function is_valid_month_season_range(range_start, range_end)
function is_valid_month_season_range(range_start, range_end)
Line 408: Line 473:
return true;
return true;
end
end


--[[
--[[
Line 425: Line 489:
true, anchor_year, COinS_date
true, anchor_year, COinS_date
anchor_year can be used in CITEREF anchors
anchor_year can be used in CITEREF anchors
COinS_date is date_string without anchor_year disambiguators if any
COinS_date is date_string without anchor_year disambiguator if any
]]
]]
function check_date (date_string)
function check_date (date_string)
Line 463: Line 527:
end
end
elseif date_string:match("^%a+%s*%d%d%d%d%a?$") then -- month/season year
elseif date_string:match("^%a+%s*%d%d%d%d%a?$") then -- month/season year
coins_date = date_string:match("%a+%s*%d%d%d%d");
coins_date = date_string:match("%a+%s*%d%d%d%d");
month, anchor_year, year=string.match(date_string, "(%a+)%s*((%d%d%d%d)%a?)");
month, anchor_year, year=string.match(date_string, "(%a+)%s*((%d%d%d%d)%a?)");
Line 510: Line 574:
for k, v in pairs(date_parameters_list) do -- for each date-holding parameter in the list
for k, v in pairs(date_parameters_list) do -- for each date-holding parameter in the list
if is_set(v) then -- if the parameter has a value
if is_set(v) then -- if the parameter has a value
if v:match("^c%.%s%d%d%d%d?%a?$") then -- special case for c. year or with or without CITEREF disambiguator - only |date= and |year=
if v:match("^c%.%s%d%d%d%d?%a?$") then -- special case for c. year or with or without CITEREF disambiguator - only |date= and |year=
if 'date'==k then
if 'date'==k then
good_date, anchor_year, COinS_date = true, v:match("((c%.%s%d%d%d%d?)%a?)"); -- anchor year and COinS_date only from |date= parameter
good_date, anchor_year, COinS_date = true, v:match("((c%.%s%d%d%d%d?)%a?)"); -- anchor year and COinS_date only from |date= parameter
Line 520: Line 584:
good_date =  true;
good_date =  true;
end
end
elseif 'date'==k then -- if the parameter is |date=
elseif 'date'==k then -- if the parameter is |date=
if v:match("n%.d%.%a?") then -- if |date=n.d. with or without a CITEREF disambiguator
if v:match("n%.d%.%a?") then -- if |date=n.d. with or without a CITEREF disambiguator
good_date, anchor_year, COinS_date = true, v:match("((n%.d%.)%a?)"); --"n.d."; -- no error when date parameter is set to no date
good_date, anchor_year, COinS_date = true, v:match("((n%.d%.)%a?)"); --"n.d."; no error when date parameter is set to no date
elseif v:match("nd%a?$") then -- if |date=nd with or without a CITEREF disambiguator
elseif v:match("nd%a?$") then -- if |date=nd with or without a CITEREF disambiguator
good_date, anchor_year, COinS_date = true, v:match("((nd)%a?)"); --"nd"; -- no error when date parameter is set to no date
good_date, anchor_year, COinS_date = true, v:match("((nd)%a?)"); --"nd"; no error when date parameter is set to no date
else
else
good_date, anchor_year, COinS_date = check_date (v); -- go test the date
good_date, anchor_year, COinS_date = check_date (v); -- go test the date
Line 531: Line 595:
good_date = check_date (v); -- go test the date
good_date = check_date (v); -- go test the date
end
end
if false==good_date then -- assemble one error message so we don't add the tracking category multiple times
if false==good_date then -- assemble one error message so we don't add the tracking category multiple times
if is_set(error_message) then -- once we've added the first portion of the 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
error_message=error_message .. ", "; -- ... add a comma space separator
Line 547: Line 611:


--[[
--[[
Determines whether an URL string is valid
Determines whether a URL string is valid


At present the only check is whether the string appears to  
At present the only check is whether the string appears to  
Line 566: Line 630:


--[[
--[[
ISBN-10 and ISSN validator code calculates checksum across all isbn/issn digits including the check digit. If the number is valid the result will be 0.
ISBN-10 and ISSN validator code calculates checksum across all isbn/issn digits including the check digit. ISBN-13 is checked in checkisbn().
Before calling this function, issbn/issn must be checked for length and stripped of dashes, spaces and other non-isxn characters.
If the number is valid the result will be 0. Before calling this function, issbn/issn must be checked for length and stripped of dashes,
spaces and other non-isxn characters.
]]
]]
function is_valid_isxn (isxn_str, len)
function is_valid_isxn (isxn_str, len)
Line 573: Line 638:
isxn_str = { isxn_str:byte(1, len) }; -- make a table of bytes
isxn_str = { isxn_str:byte(1, len) }; -- make a table of bytes
len = len+1; -- adjust to be a loop counter
len = len+1; -- adjust to be a loop counter
for i, v in ipairs( isxn_str ) do -- loop through all of the byte an calculate the checksum
for i, v in ipairs( isxn_str ) do -- loop through all of the bytes and calculate the checksum
if v == string.byte( "X" ) then -- if checkdigit is X
if v == string.byte( "X" ) then -- if checkdigit is X
temp = temp + 10*( len - i ); -- it represents 10 decimal
temp = temp + 10*( len - i ); -- it represents 10 decimal
Line 585: Line 650:
-- Determines whether an ISBN string is valid
-- Determines whether an ISBN string is valid
function checkisbn( isbn_str )
function checkisbn( isbn_str )
    isbn_str = cleanisbn( isbn_str ):gsub( "-", "" );
if nil ~= isbn_str:match("[^%s-0-9X]") then return false; end -- fail if isbn_str contains anything but digits, hyphens, or the uppercase X
    local len = isbn_str:len();
isbn_str = isbn_str:gsub( "-", "" ):gsub( " ", "" ); -- remove hyphens and spaces
local len = isbn_str:len();
   
   
    if len ~= 10 and len ~= 13 then
if len ~= 10 and len ~= 13 then
        return false;
return false;
    end
end
 
    if len == 10 then
if len == 10 then
        if isbn_str:match( "^%d*X?$" ) == nil then return false; end
if isbn_str:match( "^%d*X?$" ) == nil then return false; end
return is_valid_isxn(isbn_str, 10);
return is_valid_isxn(isbn_str, 10);
    else
else
    local temp = 0;
local temp = 0;
        if isbn_str:match( "^97[89]%d*$" ) == nil then return false; end -- isbn13 begins with 978 or 979
if isbn_str:match( "^97[89]%d*$" ) == nil then return false; end -- isbn13 begins with 978 or 979
        isbn_str = { isbn_str:byte(1, len) };
isbn_str = { isbn_str:byte(1, len) };
        for i, v in ipairs( isbn_str ) do
for i, v in ipairs( isbn_str ) do
            temp = temp + (3 - 2*(i % 2)) * tonumber( string.char(v) );
temp = temp + (3 - 2*(i % 2)) * tonumber( string.char(v) );
        end
end
        return temp % 10 == 0;
return temp % 10 == 0;
    end
end
end
end


Line 724: Line 790:
end   
end   


--[[
-- Attempts to convert names to initials.
Return the year portion of a date string, if possible. 
function reducetoinitials(first)
Returns empty string if the argument can not be interpreted
     local initials = {}
as a year.
 
BUG: If editors set |date=n.d or |date=n.da then selectyear() returns the current year for use in CITEREF.  These "dates" are caught by dates().
]]
function selectyear( str )
-- Is the input a simple number?
local num = tonumber( str );
if num ~= nil and num > 0 and num < 2100 and num == math.floor(num) then
return str;
else
-- Use formatDate to interpret more complicated formats
local lang = mw.getContentLanguage();
local good, result;
good, result = pcall( lang.formatDate, lang, 'Y', str );
if good then return result; end -- if good
end
end
 
-- Attempts to convert names to initials.
function reducetoinitials(first)
     local initials = {}
     for word in string.gmatch(first, "%S+") do
     for word in string.gmatch(first, "%S+") do
         table.insert(initials, string.sub(word,1,1)) -- Vancouver format does not include full stops.
         table.insert(initials, string.sub(word,1,1)) -- Vancouver format does not include full stops.
Line 893: Line 938:
     end
     end
      
      
     function comp( a, b )
     function comp( a, b ) -- used in following table.sort()
         return a[1] < b[1];
         return a[1] < b[1];
     end
     end
Line 1,043: Line 1,088:


--[[
--[[
This is the main function foing the majority of the citation
This is the main function doing the majority of the citation
formatting.
formatting.
]]
]]
Line 1,095: Line 1,140:
     local ConferenceURLorigin = A:ORIGIN('ConferenceURL');
     local ConferenceURLorigin = A:ORIGIN('ConferenceURL');
     local Periodical = A['Periodical'];
     local Periodical = A['Periodical'];
   
    if ( config.CitationClass == "encyclopaedia" ) then
        if not is_set(Chapter) then
            if not is_set(Title) then
                Title = Periodical;
                Periodical = '';
            else
                Chapter = Title
                TransChapter = TransTitle
                Title = '';
                TransTitle = '';
            end
        end
    end


    local Series = A['Series'];
--[[
Parameter remapping for cite encyclopedia:
When the citation has these parameters:
|encyclopedia and |title then map |title to |article and |encyclopedia to |title
|encyclopedia and |article then map |encyclopedia to |title
|encyclopedia then map |encyclopedia to |title
 
|trans_title maps to |trans_chapter when |title is re-mapped
 
All other combinations of |encyclopedia, |title, and |article are not modified
]]
if ( config.CitationClass == "encyclopaedia" ) then
if is_set(Periodical) then -- Periodical is set when |encyclopedia is set
if is_set(Title) then
if not is_set(Chapter) then
Chapter = Title; -- |encyclopedia and |title are set so map |title to |article and |encyclopedia to |title
TransChapter = TransTitle;
Title = Periodical;
Periodical = ''; -- redundant so unset
TransTitle = ''; -- redundant so unset
end
else -- |title not set
Title = Periodical; -- |encyclopedia set and |article set or not set so map |encyclopedia to |title
Periodical = ''; -- redundant so unset
end
end
end
 
local Series = A['Series'];
     local Volume = A['Volume'];
     local Volume = A['Volume'];
     local Issue = A['Issue'];
     local Issue = A['Issue'];
Line 1,160: Line 1,219:
local ID = A['ID'];
local ID = A['ID'];
if (config.CitationClass == "techreport") then -- special case for cite techreport
if (config.CitationClass == "techreport") then -- special case for cite techreport
if is_set(Issue) then -- cite techreport uses 'number', which everything else aliases to 'issue'
if is_set(Issue) then -- cite techreport uses 'number', which other citations aliase to 'issue'
if not is_set(ID) then -- can we use ID for the "number"?
if not is_set(ID) then -- can we use ID for the "number"?
ID = Issue; -- yes, use it
ID = Issue; -- yes, use it
Line 1,201: Line 1,260:
local anchor_year; -- used in the CITEREF identifier
local anchor_year; -- used in the CITEREF identifier
local COinS_date; -- used in the COinS metadata
local COinS_date; -- used in the COinS metadata
-- legacy: promote concatenation of |day=, |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
Date = Year; -- promote Year to Date
Year = nil; -- make nil so Year as empty string isn't used for CITEREF
if is_set(Date) then
local Month = A['Month'];
if is_set(Month) then
Date = Month .. " " .. Date;
local Day = A['Day']
if is_set(Day) then Date = Day .. " " .. Date end
end
elseif is_set(PublicationDate) then -- use PublicationDate when |date= and |year= are not set
Date = PublicationDate; -- promonte PublicationDate to Date
PublicationDate = ''; -- unset, no longer needed
end
end
if PublicationDate == Date then PublicationDate = ''; end -- if PublicationDate is same as Date, don't display in rendered citation


-- Go test all of the date-holding parameters for valid MOS:DATE format and make sure that dates are real dates.
-- Go test all of the date-holding parameters for valid MOS:DATE format and make sure that dates are real dates.
Line 1,207: Line 1,285:
['embargo']=Embargo, ['laydate']=LayDate, ['publicationdate']=PublicationDate, ['year']=Year});
['embargo']=Embargo, ['laydate']=LayDate, ['publicationdate']=PublicationDate, ['year']=Year});


if not is_set(Year) then -- prevent Year from being set from DateIn  TODO: eliminate the need for this?
-- At this point fields may be nil if they weren't specified in the template use.  We can use that fact.
if is_set(anchor_year) then
 
Year = anchor_year;
--Account for the oddity that is {{cite journal}} with |pmc= set and |url= not set
if config.CitationClass == "journal" and not is_set(URL) and is_set(ID_list['PMC']) then
if not is_embargoed(Embargo) then
URL=cfg.id_handlers['PMC'].prefix .. ID_list['PMC']; -- set url to be the same as the PMC external link if not embargoed
end
end
end
end


-- At this point fields may be nil if they weren't specified in the template use.  We can use that fact.
   
     -- Account for the oddity that is {{cite conference}}, before generation of COinS data.
     -- Account for the oddity that is {{cite conference}}, before generation of COinS data.
     if is_set(BookTitle) then
     if is_set(BookTitle) then
Line 1,260: Line 1,339:
         ['Title'] = Title,
         ['Title'] = Title,
         ['PublicationPlace'] = PublicationPlace,
         ['PublicationPlace'] = PublicationPlace,
         ['Date'] = first_set(COinS_date, Date, Year, PublicationDate),
         ['Date'] = first_set(COinS_date, Date), -- COinS_date has correctly formatted date if Date is valid; any reason to keep Date here?  Should we be including invalid dates in metadata?
         ['Series'] = Series,
         ['Series'] = Series,
         ['Volume'] = Volume,
         ['Volume'] = Volume,
Line 1,308: Line 1,387:
             control.lastauthoramp = nil;
             control.lastauthoramp = nil;
             control.maximum = #a + 1;
             control.maximum = #a + 1;
            deprecated_parameter(); -- |coauthor= and |coathors= are deprecated; add this page to deprecated parameter category
         end
         end
          
          
Line 1,316: Line 1,394:
if not is_set(Authors) and is_set(Coauthors) then -- coauthors aren't displayed if one of authors=, authorn=, or lastn= isn't specified
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, { seterror('coauthors_missing_author', {}, true) } ); -- emit error message
table.insert( z.message_tail, { seterror('coauthors_missing_author', {}, true) } ); -- emit error message
deprecated_parameter(); -- |coauthor= and |coathors= are deprecated; add this page to deprecated parameter category
end
end


Line 1,359: Line 1,436:
         end         
         end         
     end
     end
   
    if not is_set(Date) then
        Date = Year;
        if is_set(Date) then
            local Month = A['Month'];
            if is_set(Month) then
            deprecated_parameter(); -- |month= (and also |day=) is deprecated; add this page to deprecated parameter category
                Date = Month .. " " .. Date;
                local Day = A['Day']
                if is_set(Day) then Date = Day .. " " .. Date end
            end
        end
    end
   
    if inArray(PublicationDate, {Date, Year}) then PublicationDate = ''; end
    if not is_set(Date) and is_set(PublicationDate) then
        Date = PublicationDate;
        PublicationDate = '';
    end
    -- Captures the value for Date prior to adding parens or other textual transformations
    local DateIn = Date;
      
      
     if  not is_set(URL) and
     if  not is_set(URL) and
Line 1,599: Line 1,654:
]]
]]
if is_set (Language) then
if is_set (Language) then
local name = cfg.iso639_1[Language:lower()]; -- get the language name if Language parameter has a valid iso 639-1 code
local name = cfg.iso639_1[Language:lower()]; -- get the language name if Language parameter has a valid iso 639-1 code
if nil == name then
if nil == name then
Language=" " .. wrap( 'language', Language ); -- no match, use parameter's value
Language=" " .. wrap( 'language', Language ); -- no match, use parameter's value
else
else
if 0 == this_page.namespace and 'en' ~= Language:lower() then --found a match; is this page main / article space and English not the language?
if 0 == this_page.namespace and 'en' ~= Language:lower() then --found a match; is this page main / article space and English not the language?
Language=" " .. wrap( 'language', name .. '[[Category:Articles with ' .. name .. '-language external links]]' ); -- in main space and not English: categorize
Language=" " .. wrap( 'language', name .. '[[Category:Articles with ' .. name .. '-language external links]]' ); -- in main space and not English: categorize
else
else
Language=" " .. wrap( 'language', name ); --not in mainspace or language is English so don't categorize
Language=" " .. wrap( 'language', name ); --not in mainspace or language is English so don't categorize
end
end
end
else
Language=""; -- language not specified so make sure this is an empty string;
end
 
Others = is_set(Others) and (sepc .. " " .. Others) or "";
 
-- handle type parameter for those CS1 citations that have default values
 
if inArray(config.CitationClass, {"pressrelease","techreport","thesis", "speech"}) then
TitleType = set_titletype (config.CitationClass, TitleType);
if is_set(Degree) and "Thesis" == TitleType then -- special case for cite thesis
TitleType = Degree .. " thesis";
end
end
else
Language=""; -- language not specified so make sure this is an empty string;
end
end


Others = is_set(Others) and (sepc .. " " .. Others) or "";
-- handle type parameter for those CS1 citations that have default values
if "pressrelease" == config.CitationClass then -- if this citation is cite press release
if not is_set (TitleType) then
TitleType = "Press release"; -- if type not specified, display the press release annotation
else
if "none" == TitleType then TitleType = ""; end -- if |type=none then type parameter not displayed
end
elseif "techreport" == config.CitationClass then -- if this citation is cite techreport
if not is_set (TitleType) then
TitleType = "Technical report"; -- if type not specified, display the techreport annotation
else
if "none" == TitleType then TitleType = ""; end -- if |type=none then type parameter not displayed; |number=, if set, will be displayed
end
elseif "thesis" == config.CitationClass then -- if this citation is cite thesis
if not is_set (TitleType) then
if is_set(Degree) then -- if type not specified, display one of the thesis annotations
TitleType = Degree .. " thesis"; -- if a degree (masters, PhD, ...) is specified include it in the display
else
TitleType = "Thesis"; -- otherwise display the simple thesis annotation
end
else
if "none" == TitleType then TitleType = ""; end -- if |type=none then type parameter not displayed
end
end
if is_set(TitleType) then -- if type parameter is specified
if is_set(TitleType) then -- if type parameter is specified
TitleType = " (" .. TitleType .. ")"; -- display it in parentheses
TitleType = " (" .. TitleType .. ")"; -- display it in parentheses
Line 1,903: Line 1,940:


     -- Now enclose the whole thing in a <span/> element
     -- Now enclose the whole thing in a <span/> element
    if not is_set(Year) then
        if is_set(DateIn) then
            Year = selectyear( DateIn );
        elseif is_set(PublicationDate) then
            Year = selectyear( PublicationDate );
        end
    end
   
     local options = {};
     local options = {};
      
      
Anonymous user