Module:Citation/CS1
<section begin=header />
Warning | This Lua module is used on 3,000,000+ pages. To avoid large-scale disruption and unnecessary server load, any changes to this module should first be tested in its /sandbox or /testcases subpages. The tested changes can then be added to this page in a single edit. Please consider discussing any changes on the talk page before implementing them. |
This module is subject to page protection. It is a highly visible module in use by a very large number of pages, or is substituted very frequently. Because vandalism or mistakes would affect many pages, and even trivial editing might cause substantial load on the servers, it is protected from editing. |
<section end=header />
This module and associated sub-modules support the Citation Style 1 and Citation Style 2 citation templates. In general, it is not intended to be called directly, but is called by one of the core CS1 and CS2 templates. <section begin=module_components_table /> These files comprise the module support for cs1|2 citation templates:
<section end=module_components_table />
Other documentation:
local z = {
error_categories = {};
}
-- Formats a hidden comment for error trapping not intended to be visible to readers
function hiddencomment( content )
return '<span style="display: none;" class="citation-comment">' .. content .. '</span>';
end
-- This returns a string with HTML character entities for wikitext markup characters.
function wikiescape(text)
text = text:gsub( '[&\'%[%]{|}]', {
['&'] = '&',
["'"] = ''',
['['] = '[',
[']'] = ']',
['{'] = '{',
['|'] = '|',
['}'] = '}' } );
return text;
end
-- Create an HTML tag
function createTag(t, frame)
local name = t.name or "!-- --"
local content = t.contents or ""
local attrs = {}
for n,v in pairs(t.params) do
if (v) then
table.insert(attrs, n .. "=\"" .. wikiescape(v) .. "\"")
else
table.insert(attrs, n)
end
end
if ("" == content) then
return "<" .. name .. " " .. table.concat(attrs, " ") .. "/>"
else
return "<" .. name .. " " .. table.concat(attrs, " ") .. ">" .. content .. "</" .. name .. ">"
end
end
--[[
This is a clone of mw.text.nowiki. When the mw.text library is installed,
this can be replaced by a call to that library.
]]
function nowiki( s )
-- string.gsub is safe here, because we're only caring about ASCII chars
s = string.gsub( s, '["&\'<=>%[%]{|}]', {
['"'] = '"',
['&'] = '&',
["'"] = ''',
['<'] = '<',
['='] = '=',
['>'] = '>',
['['] = '[',
[']'] = ']',
['{'] = '{',
['|'] = '|',
['}'] = '}',
} )
s = string.sub( string.gsub( '\n' .. s, '\n[#*:;]', {
["\n#"] = "\n#",
["\n*"] = "\n*",
["\n:"] = "\n:",
["\n;"] = "\n;",
} ), 2 )
s = string.gsub( s, '://', '://' )
s = string.gsub( s, 'ISBN ', 'ISBN ' )
s = string.gsub( s, 'RFC ', 'RFC ' )
return s
end
-- Formats a wiki style external link
function externallinkid(args)
local sep = args.separator or " "
args.suffix = args.suffix or ""
local url_string = args.id
if args.encode == true or args.encode == nil then
url_string = mw.uri.encode( url_string );
end
return "[[" .. args.link .. "|" .. args.label .. "]]" .. sep .. "[" .. args.prefix .. url_string .. args.suffix .. " " .. nowiki(args.id) .. "]"
end
-- Formats a wiki style internal link
function internallinkid(args)
local sep = args.separator or " "
args.suffix = args.suffix or ""
return "[[" .. args.link .. "|" .. args.label .. "]]" .. sep .. "[[" .. args.prefix .. args.id .. args.suffix .. "|" .. nowiki(args.id) .. "]]"
end
-- Formats a link to Amazon
function amazon(id, domain)
if ( nil == domain ) then
domain = "com"
elseif ( "jp" == domain or "uk" == domain ) then
domain = "co." .. domain
end
return externallinkid({link="Amazon Standard Identification Number",label="ASIN",prefix="//www.amazon."..domain.."/dp/",id=id,encode=false})
end
-- Formats a DOI and checks for DOI errors.
function doi(id, inactive)
local cat = ""
local text;
if ( inactive ~= nil ) then
text = "[[Digital object identifier|doi]]:" .. id;
table.insert( z.error_categories, "Pages with DOIs inactive since " .. selectyear(inactive) );
inactive = " (inactive " .. inactive .. ")"
else
text = externallinkid({link="Digital object identifier",label="doi",prefix="http://dx.doi.org/",id=id,separator=":"})
inactive = ""
end
if ( string.sub(id,1,3) ~= "10." ) then
table.insert( z.error_categories, "Pages with DOI errors" );
cat = ' <span class="error">Bad DOI (expected "10." prefix) in code number</span>'
end
return text .. inactive .. cat
end
-- Escape sequences for content that will be used for URL descriptions
function safeforurl( str )
return str:gsub( '[%[%]\n]', {
['['] = '[',
[']'] = ']',
['\n'] = ' ' } );
end
-- Converts a hyphen to a dash
function hyphentodash( str )
if str == nil then
return nil;
end
return str:gsub( '-', '–' );
end
-- Protects a string that will be wrapped in wiki italic markup '' ... ''
function safeforitalics( str )
--[[ Note: We can not use <i> for italics, as the expected behavior for
italics specified by ''...'' in the title is that they will be inverted
(i.e. unitalicized) in the resulting references. In addition, <i> and ''
tend to interact poorly under Mediawiki's HTML tidy. ]]
if str == nil or str == '' then
return str;
else
if str:sub(1,1) == "'" then str = "<span />" .. str; end
if str:sub(-1,-1) == "'" then str = str .. "<span />"; end
return str;
end
end
--[[
Joins a sequence of string together while checking for duplicate separation
characters.
]]
function safejoin( tbl, duplicate_char )
--[[
Note: we use string functions here, rather than ustring functions.
This has considerably faster performance and should work correctly as
long as the duplicate_char is strict ASCII. The strings
in tbl may be ASCII or UTF8.
]]
local str = '';
local comp = '';
local end_chr = '';
for _, value in ipairs( tbl ) do
if value == nil then value = ''; end
if str == '' then
str = value;
elseif value ~= '' then
if value:sub(1,1) == '<' then
-- Special case of values enclosed in spans and other markup.
comp = value:gsub( "%b<>", "" );
else
comp = value;
end
if comp:sub(1,1) == duplicate_char then
end_chr = str:sub(-1,-1);
if end_chr == duplicate_char then
str = str:sub(1,-2) .. value;
elseif end_chr == "'" then
if str:sub(-3,-1) == duplicate_char .. "''" then
str = str:sub(1, -4) .. "''" .. value;
else
str = str .. value;
end
elseif end_chr == " " then
if str:sub(-2,-1) == duplicate_char .. " " then
str = str:sub(1,-3) .. value;
else
str = str .. value;
end
else
str = str .. value;
end
else
str = str .. value;
end
end
end
return str;
end
--[[
Return the year portion of a date string, if possible.
Returns empty string if the argument can not be interpreted
as a year.
]]
function selectyear( str )
local lang = mw.getContentLanguage();
local good, result;
good, result = pcall( lang.formatDate, lang, 'Y', str )
if good then
return result;
else
--[[
FormatDate fails on years that are less than 4 digits. If the input
is a positive integer, assume it is a valid year even if it has less
than four digits.
]]
local num = tonumber( str );
if num ~= nil and num > 0 and num < 2100 and num == math.abs(num) then
return str;
else
return '';
end
end
end
-- Formats an OpenLibrary link, and checks for associated errors.
function openlibrary(id)
local code = id:sub(-1,-1)
if ( code == "A" ) then
return externallinkid({link="Open Library",label="OL",prefix="http://openlibrary.org/authors/OL",id=id})
elseif ( code == "M" ) then
return externallinkid({link="Open Library",label="OL",prefix="http://openlibrary.org/books/OL",id=id})
elseif ( code == "W" ) then
return externallinkid({link="Open Library",label="OL",prefix= "http://openlibrary.org/works/OL",id=id})
else
table.insert( z.error_categories, "Pages with OL errors" );
return externallinkid({link="Open Library",label="OL",prefix= "http://openlibrary.org/OL",id=id}) ..
' <span class="error">Bad OL specified</span>';
end
end
-- Attempts to convert names to initials.
function reducetoinitials(first)
local initials = {}
for word in string.gmatch(first, "%S+") do
table.insert(initials, string.sub(word,1,1)) -- Vancouver format does not include full stops.
end
return table.concat(initials) -- Vancouver format does not include spaces.
end
-- Formats a list of people (e.g. authors / editors)
function listpeople(control, people)
local sep = control.sep;
if sep:sub(-1,-1) ~= " " then sep = sep .. " " end
local namesep = control.namesep
local format = control.format
local maximum = control.maximum
local text = {}
local etal = false;
for i,person in ipairs(people) do
if (person.last ~= nil or person.last ~= "") then
local mask = person.mask
local one
if ( maximum ~= nil and i == maximum + 1 ) then
etal = true;
break;
elseif (mask ~= nil) then
local n = tonumber(mask)
if (n ~= nil) then
one = string.rep("—",n)
else
one = mask
end
else
one = person.last
local first = person.first
if (first ~= nil and first ~= '') then
if ( "vanc" == format ) then first = reducetoinitials(first) end
one = one .. namesep .. first
end
if (person.link ~= nil and person.link ~= "") then one = "[[" .. person.link .. "|" .. one .. "]]" end
end
table.insert(text, one)
end
end
local count = #text;
local result = table.concat(text, sep) -- construct list
if etal then
local etal_text = "et al."
if (sepc == ".") then etal_text = "et al" end
result = result .. " " .. etal_text;
end
if ( "scap" == format ) then result= createTag({name="span", contents=result, params={class="smallcaps", style="font-variant:small-caps;"}}) end -- if necessary wrap result in <span> tag to format in Small Caps
return result, count
end
-- Generates a CITEREF anchor ID.
function anchorid(args)
local P1 = args[1] or ""
local P2 = args[2] or ""
local P3 = args[3] or ""
local P4 = args[4] or ""
local P5 = args[5] or ""
return "CITEREF" .. P1 .. P2 .. P3 .. P4 .. P5
end
-- Gets author list from the input arguments
function extractauthors(args)
local authors = {};
local i = 1;
local last;
while true do
last = args["author" .. i .. "-last"] or args["author-last" .. i] or args["last" .. i] or args["surname" .. i] or args["Author" .. i] or args["author" .. i]
if ( last and "" < last ) then -- just in case someone passed in an empty parameter
authors[i] = {
last = last,
first = args["author" .. i .. "-first"] or args["author-first" .. i] or args["first" .. i] or args["given" .. i],
link = args["author" .. i .. "-link"] or args["author-link" .. i] or args["author" .. i .. "link"] or args["authorlink" .. i],
mask = args["author" .. i .. "-mask"] or args["author-mask" .. i] or args["author" .. i .. "mask"] or args["authormask" .. i]
}
else
break;
end
i = i + 1;
end
return authors;
end
-- Gets editor list from the input arguments
function extracteditors(args)
local editors = {};
local i = 1;
local last;
while true do
last = args["editor" .. i .. "-last"] or args["editor-last" .. i] or args["EditorSurname" .. i] or args["Editor" .. i] or args["editor" .. i]
if ( last and "" < last ) then -- just in case someone passed in an empty parameter
editors[i] = {
last = last,
first = args["editor" .. i .. "-first"] or args["editor-first" .. i] or args["EditorGiven" .. i],
link = args["editor" .. i .. "-link"] or args["editor-link" .. i] or args["editor" .. i .. "link"] or args["editorlink" .. i],
mask = args["editor" .. i .. "-mask"] or args["editor-mask" .. i] or args["editor" .. i .. "mask"] or args["editormask" .. i]
}
else
break;
end
i = i + 1;
end
return editors;
end
--[[
This is the main function foing the majority of the citation
formatting.
]]
function citation0( config, args)
-- Load Input Parameters
local PPrefix = config.PPrefix or "p. "
local PPPrefix = config.PPPrefix or "pp. "
if ( nil ~= args.nopp ) then PPPrefix = "" PPrefix = "" end
-- Transfer unnumbered arguments to numbered arguments if necessary.
args["author1"] = args.author1 or args.author or args.authors
args["author1-last"] = args["author1-last"] or args["author-last"] or args["last"]
args["author1-first"] = args["author1-first"] or args["author-first"]
or args.first or args.first1 or args.given or args.given1
args["author1-link"] = args["author1-link"] or args["author-link"]
args["author1-mask"] = args["author1-mask"] or args["author-mask"]
args["author1link"] = args["author1link"] or args["authorlink"]
args["editor1"] = args["editor1"] or args["editor"]
args["editor1-last"] = args["editor1-last"] or args["editor-last"]
args["editor1-first"] = args["editor1-first"] or args["editor-first"]
args["editor1-link"] = args["editor1-link"] or args["editor-link"]
args["editor1-mask"] = args["editor1-mask"] or args["editor-mask"]
args["editor1link"] = args["editor1link"] or args["editorlink"]
-- Pick out the relevant fields from the arguments. Different citation templates define different field names for the same underlying things.
local Authors = args.authors
local i
local a = extractauthors( args );
local Coauthors = args.coauthors or args.coauthor
local Others = args.others
local EditorMask = args.editormask or args["editor-mask"]
local EditorFormat = args["editor-format"] or args.editorformat
local Editors = args.editors
local e = extracteditors( args );
local Year = args.year
local PublicationDate = args.publicationdate or args["publication-date"]
local OrigYear = args.origyear
local Date = args.date
local LayDate = args.laydate
------------------------------------------------- Get title data
local Title = args.title or args.encyclopaedia or args.encyclopedia or args.dictionary
local BookTitle = args.booktitle
local Conference = args.conference
local TransTitle = args.trans_title
local TitleNote = args.department
local TitleLink = args.titlelink or args.episodelink
local Chapter = args.chapter or args.contribution or args.entry
local ChapterLink = args.chapterlink
local TransChapter = args["trans-chapter"] or args.trans_chapter
local TitleType = args.type
local ArchiveURL = args["archive-url"] or args.archiveurl
local URL = args.url
local ChapterURL = args["chapter-url"] or args.chapterurl
local ConferenceURL = args["conference-url"] or args.conferenceurl
local Periodical = args.journal or args.newspaper or args.magazine or args.work or args.periodical or args.encyclopedia or args.encyclopaedia
if ( config.CitationClass == "encyclopaedia" ) then
if ( args.article and args.article ~= "") then
if ( Title and Title ~= "") then Periodical = Title end
Chapter = args.article
TransChapter = TransTitle
Title = ""
elseif ( Chapter == nil or Chapter == '' ) then
if Title ~= args.encyclopedia then
Chapter = Title
TransChapter = TransTitle
Title = ""
end
end
if ( Periodical and Periodical ~= "") then
if Periodical == Title or Periodical == Chapter then Periodical = '' end
end
end
local Series = args.series or args.version
local Volume = args.volume
local Issue = args.issue or args.number
local Position = nil
local Page = args.p or args.page
local Pages = hyphentodash( args.pp or args.pages )
local At = args.at
local page_error = false;
if Page ~= nil and Page ~= '' then
if (Pages ~= nil and Pages ~= '') or (At ~= nil and At ~= '') then
Pages = nil;
At = nil;
page_error = true;
end
elseif Pages ~= nil and Pages ~= '' then
if At ~= nil and At ~= '' then
At = nil;
page_error = true;
end
end
local Edition = args.edition
local PublicationPlace = args["publication-place"] or args.publicationplace or args.place or args.location
local Location = PublicationPlace
local PublisherName = args.publisher
local SubscriptionRequired = args.subscription
local Via = args.via
local AccessDate = args["access-date"] or args.accessdate
local ArchiveDate = args["archive-date"] or args.archivedate
local Agency = args.agency
local DeadURL = args.deadurl or "yes" -- Only used is ArchiveURL is present.
local Language = args.language or args["in"]
local Format = args.format
local Ref = args.ref or args.Ref
local ARXIV = args.arxiv or args.ARXIV
local ASIN = args.asin or args.ASIN
local ASINTLD = args["ASIN-TLD"] or args["asin-tld"]
local BIBCODE = args.bibcode or args.BIBCODE
local DOI = args.doi or args.DOI
local DoiBroken = args.doi_inactivedate or args.doi_brokendate or args.DoiBroken
local ID = args.id or args.ID
local ISBN = args.isbn13 or args.isbn or args.ISBN
local ISSN = args.issn or args.ISSN
local JFM = args.jfm or args.JFM
local JSTOR = args.jstor or args.JSTOR
local LCCN = args.lccn or args.LCCN
local MR = args.mr or args.MR
local OCLC = args.oclc or args.OCLC
local OL = args.ol or args.OL
local OSTI = args.osti or args.OSTI
local PMC = args.pmc or args.PMC
local PMID = args.pmid or args.PMID
local RFC = args.rfc or args.RFC
local SSRN = args.ssrn or args.SSRN
local ZBL = args.zbl or args.ZBL
local Quote = args.quote or args.quotation
local PostScript = args.postscript
local LaySummary = args.laysummary
local LaySource = args.laysource
local Transcript = args.transcript
local TranscriptURL = args["transcript-url"] or args.transcripturl
local sepc = args.separator or "."
local no_tracking_cats = args["template doc demo"] or args.nocat or args.notracking or args["no-tracking"] or "";
if ( config.CitationClass == "journal" ) then
if (URL == nil or URL == "") then
if (PMC ~= nil and PMC ~="")
then URL="http://www.ncbi.nlm.nih.gov/pmc/articles/PMC" .. PMC
else URL=""
end
end
elseif ( config.CitationClass == "citation" ) then
sepc = ","
if ( Ref == nil ) then Ref = "harv" 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.
if ( BookTitle ) then
Chapter = Title
ChapterLink = TitleLink
TransChapter = TransTitle
Title = BookTitle
TitleLink = nil
TransTitle = nil
end
-- Account for the oddity that is {{cite episode}}, before generation of COinS data.
if config.CitationClass == "episode" then
local AirDate = args.airdate
local SeriesLink = args.serieslink
local Season = args.season
local SeriesNumber = args.seriesnumber or args.seriesno
local Network = args.network
local Station = args.station
local s = {}
if Issue ~= nil then table.insert(s, "episode " .. Issue) Issue = nil end
if Season ~= nil then table.insert(s, "season " .. Season) end
if SeriesNumber ~= nil then table.insert(s, "series " .. SeriesNumber) end
local n = {}
if Network ~= nil then table.insert(n, Network) end
if Station ~= nil then table.insert(n, Station) end
Date = Date or AirDate
Chapter = Title
ChapterLink = TitleLink
TransChapter = TransTitle
Title = Series
TitleLink = SeriesLink
TransTitle = nil
local Sep = args["series-separator"] or args["separator"] or ". "
Series = table.concat(s, Sep)
ID = table.concat(n, Sep)
end
-- These data form a COinS tag (see <http://ocoins.info/>) which allows automated tools to parse the citation information.
local OCinSdata = {} -- COinS metadata excluding id, bibcode, doi, etc.
local ctx_ver = "Z39.88-2004"
OCinSdata.rft_val_fmt = "info:ofi/fmt:kev:mtx:book"
if ( nil ~= Periodical ) then
OCinSdata.rft_val_fmt = "info:ofi/fmt:kev:mtx:journal"
OCinSdata["rft.genre"] = "article"
OCinSdata["rft.jtitle"] = Periodical
if ( nil ~= Title ) then OCinSdata["rft.atitle"] = Title end
end
if ( nil ~= Chapter and "" ~= Chapter) then
OCinSdata.rft_val_fmt = "info:ofi/fmt:kev:mtx:book"
OCinSdata["rft.genre"] = "bookitem"
OCinSdata["rft.btitle"] = Chapter
if ( nil ~= Title ) then OCinSdata["rft.atitle"] = Title end
else
OCinSdata["rft.genre"] = "book"
if ( nil ~= Title ) then OCinSdata["rft.btitle"] = Title end
end
OCinSdata["rft.place"] = PublicationPlace
OCinSdata["rft.date"] = Date or Year or PublicationDate
OCinSdata["rft.series"] = Series
OCinSdata["rft.volume"] = Volume
OCinSdata["rft.issue"] = Issue
OCinSdata["rft.pages"] = Page or Pages or At
OCinSdata["rft.edition"] = Edition
OCinSdata["rft.pub"] = PublisherName
OCinSdata["rft.isbn"] = ISBN
OCinSdata["rft.issn"] = ISSN
OCinSdata["rft.jfm"] = JFM
OCinSdata["rft.jstor"] = JSTOR
OCinSdata["rft.lccn"] = LCCN
OCinSdata["rft.mr"] = MR
OCinSdata.rft_id = URL or ChapterURL
if ( nil ~= a[1] and nil ~= a[1].last) then
local last = a[1].last
local first = a[1].first
OCinSdata["rft.aulast"] = last
if ( nil ~= first ) then
OCinSdata["rft.aufirst"] = first
OCinSdata["rft.au"] = last .. (args.NameSep or ", ") .. first
else
OCinSdata["rft.au"] = last
end
end
local OCinSids = {} -- COinS data only for id, bibcode, doi, pmid, etc.
OCinSids["info:arxiv"] = ARXIV
OCinSids["info:asin"] = ASIN
OCinSids["info:bibcode"] = BIBCODE
OCinSids["info:doi"] = DOI
OCinSids["info:oclcnum"] = OCLC
OCinSids["info:olnum"] = OL
OCinSids["info:osti"] = OSTI
OCinSids["info:pmc"] = PMC
OCinSids["info:pmid"] = PMID
OCinSids["info:rfc"] = RFC
OCinSids["info:ssrn"] = SSRN
OCinSids["info:zbl"] = ZBL
local OCinStitle = "ctx_ver=" .. ctx_ver -- such as "Z39.88-2004"
for name,value in pairs(OCinSids) do
OCinStitle = OCinStitle .. "&rft_id=" .. mw.uri.encode(name .. "/" .. value)
end
for name,value in pairs(OCinSdata) do
OCinStitle = OCinStitle .. "&" .. name .. "=" .. mw.uri.encode(value)
end
local this_page = mw.title.getCurrentTitle();
OCinStitle = OCinStitle .. "&rfr_id=info:sid/en.wikipedia.org:"
.. this_page.prefixedText -- end COinS data by page's non-encoded pagename
-- Now perform various field substitutions.
-- We also add leading spaces and surrounding markup and punctuation to the various parts of the citation, but only when they are non-nil.
if ( Authors == nil ) then
local AuthorNameSep = args["author-name-separator"] or args["name-separator"] or ","
AuthorNameSep = AuthorNameSep .. " "
local AuthorSep = args["author-separator"] or args["separator"] or ";"
AuthorSep = AuthorSep .. " "
local AuthorFormat = args["author-format"] or args.authorformat
local AuthorMaximum = tonumber(args["display-authors"] or args.displayauthors) or 8
local control = { sep = AuthorSep, namesep = AuthorNameSep, format = AuthorFormat, maximum = AuthorMaximum }
Authors = listpeople(control, a)
end
local EditorCount
if ( Editors == nil ) then
local EditorNameSep = args["editor-name-separator"] or args["name-separator"] or ", "
local EditorSep = args["editor-separator"] or args["separator"] or "; "
local EditorFormat = args["editor-format"] or args.editorformat
local EditorMaximum = tonumber(args["display-editors"] or args.displayeditors) or 3
local control = { sep = EditorSep, namesep = EditorNameSep, format = EditorFormat, maximum = EditorMaximum }
Editors, EditorCount = listpeople(control, e)
else
EditorCount = 1;
end
if ( Date == nil or Date == "") then
-- there's something hinky with how this adds dashes to perfectly-good free-standing years
--[[ Date = Year
if ( Date ~= nil ) then
local Month = args.month
if ( Month == nil ) then
local Began = args.began
local Ended = args.ended
if Began ~= nil and Ended ~= nil then
Month = Began .. "–" .. Ended
else
Month = "–"
end
end
Date = Month .. " " .. Date
local Day = args.day
if ( Day ~= nil ) then Date = Day .. " " .. Date end
end
]] -- so let's use the original version for now
Date = Year
if ( Date ~= nil and Date ~="") then
local Month = args.month
if ( Month ~= nil and Month ~= "") then
Date = Month .. " " .. Date
local Day = args.day
if ( Day ~= nil ) then Date = Day .. " " .. Date end
else Month = ""
end
else Date = ""
end
end
if ( PublicationDate == Date or PublicationDate == Year ) then PublicationDate = nil end
if( (Date == nil or Date == "") and PublicationDate ~= nil ) then
Date = PublicationDate;
PublicationDate = nil;
end
-- Captures the value for Date prior to adding parens or other textual transformations
local DateIn = Date
-- Test is cite web is called without giving a URL
if ( config.CitationClass == "web" ) then
if ( URL == nil or URL == '' ) and
( ChapterURL == nil or ChapterURL == '' ) and
( ArchiveURL == nil or ArchiveURL == '' ) and
( ConferenceURL == nil or ConferenceURL == '' ) and
( TranscriptURL == nil or TranscriptURL == '' ) then
table.insert( z.error_categories, 'Pages using web citations with no URL' );
if Title == nil or Title == "" then
Authors = Authors .. hiddencomment("No URL on cite web here");
else
Title = Title .. hiddencomment("No URL on cite web here");
end
end
end
-- Test if citation has no title
if ( Chapter == nil or Chapter == "" ) and
( Title == nil or Title == "" ) and
( Periodical == nil or Periodical == "" ) and
( Conference == nil or Conference == "" ) then
table.insert( z.error_categories, 'Pages with citations lacking titles' );
Authors = Authors .. hiddencomment("No citation title here");
end
if ( Format ~= nil and Format ~="" ) then
Format = " (" .. Format .. ")" else Format = "" end
if ( ArchiveURL and "" < ArchiveURL ) then
if ( DeadURL ~= "no" ) then
local temp = URL
URL = ArchiveURL
end
end
if ( TransTitle and "" < TransTitle ) then TransTitle = " [" .. TransTitle .. "]" else TransTitle = "" end
if ( TransChapter and "" < TransChapter ) then TransChapter = " [" .. TransChapter .. "]" else TransChapter = "" end
if ( Chapter and "" < Chapter ) then
if ( ChapterLink and "" < ChapterLink ) then Chapter = "[[" .. ChapterLink .. "|" .. Chapter .. "]]" end
if ( Periodical and "" < Periodical
and config.CitationClass ~= "encyclopaedia"
) then
Chapter = "''" .. safeforitalics(Chapter) .. "''"
else
Chapter = "\"" .. Chapter .. "\""
end
Chapter = Chapter .. TransChapter
if ( ChapterLink == nil ) then
if ( ChapterURL and "" < ChapterURL ) then
Chapter = "[" .. ChapterURL .. " " .. safeforurl( Chapter ) .. "]"
elseif ( URL and "" < URL ) then
Chapter = "[" .. URL .. " " .. safeforurl( Chapter ) .. "]" .. Format
URL = nil
Format = ""
end
end
Chapter = Chapter .. sepc .. " " -- with end-space
else
Chapter = ""
end
if ( Title and "" < Title ) then
if ( TitleLink and "" < TitleLink ) then
Title = "[[" .. TitleLink .. "|" .. Title .. "]]" end
if ( Periodical and "" < Periodical ) then
Title = "\"" .. Title .. "\""
elseif ( config.CitationClass == "web"
or config.CitationClass == "news" ) then
Title = "\"" .. Title .. "\""
else
Title = "''" .. safeforitalics(Title) .. "''"
end
Title = Title .. TransTitle
if ( TitleLink == nil and URL and "" < URL ) then
Title = "[" .. URL .. " " .. safeforurl( Title ) .. "]" .. Format
URL = nil
Format = ''
end
else
Title = ""
end
if ( Conference ~= nil and Conference ~="" ) then
if ( ConferenceURL ~= nil ) then
Conference = "[" .. ConferenceURL .. " " .. safeforurl( Conference ) .. "]"
end
Conference = " " .. Conference
else
Conference = ""
end
if ( nil ~= Position or nil ~= Page or nil ~= Pages ) then At = nil end
if ( nil == Position and "" ~= Position ) then
local Minutes = args.minutes
if ( nil ~= Minutes ) then
Position = " " .. Minutes .. " minutes in"
else
local Time = args.time
if ( nil ~= Time ) then
local TimeCaption = args.timecaption or "Event occurs at"
Position = " " .. TimeCaption .. " " .. Time
else
Position = ""
end
end
else
Position = " " .. Position
end
if ( nil == Page or "" == Page ) then
Page = ""
if ( nil == Pages or "" == Pages) then
Pages = ""
elseif ( Periodical ~= nil and Periodical ~= "" and
config.CitationClass ~= "encyclopaedia" and
config.CitationClass ~= "web" and
config.CitationClass ~= "book" and
config.CitationClass ~= "news") then
Pages = ": " .. Pages
else
if ( tonumber(Pages) ~= nil ) then
Pages = sepc .." " .. PPrefix .. Pages
else Pages = sepc .." " .. PPPrefix .. Pages
end
end
else
Pages = ""
if ( Periodical ~= nil and Periodical ~= "" and
config.CitationClass ~= "encyclopaedia" and
config.CitationClass ~= "web" and
config.CitationClass ~= "book" and
config.CitationClass ~= "news") then
Page = ": " .. Page
else
Page = sepc .." " .. PPrefix .. Page
end
end
if ( At ~= nil and At ~="") then At = sepc .. " " .. At
else At = "" end
if ( Coauthors == nil ) then Coauthors = "" end
if ( Others ~= nil and Others ~="" ) then
Others = sepc .. " " .. Others else Others = "" end
if ( TitleType ~= nil and TitleType ~="" ) then
TitleType = " (" .. TitleType .. ")" else TitleType = "" end
if ( TitleNote ~= nil and TitleNote ~="" ) then
TitleNote = sepc .. " " .. TitleNote else TitleNote = "" end
if ( PublicationPlace ~= nil and PublicationPlace ~="" ) then
PublicationPlace = PublicationPlace .. ": "
else PublicationPlace = "" end
if ( Language ~= nil and Language ~="" ) then
Language = " (in " .. Language .. ")" else Language = "" end
if ( Edition ~= nil and Edition ~="" ) then
Edition = " (" .. Edition .. " ed.)" else Edition = "" end
if ( Volume ~= nil and Volume ~="" )
then
if ( string.len(Volume) > 4 )
then Volume = sepc .." " .. Volume
else Volume = " <b>" .. Volume .. "</b>"
end
else Volume = "" end
if ( Issue ~= nil and Issue ~="" ) then
Issue = " (" .. Issue .. ")" else Issue = "" end
if ( Series ~= nil and Series ~="" ) then
Series = sepc .. " " .. Series else Series = "" end
if ( OrigYear ~= nil and OrigYear ~="" ) then
OrigYear = " [" .. OrigYear .. "]" else OrigYear = "" end
if ( Agency ~= nil and Agency ~="" ) then
Agency = sepc .. " " .. Agency else Agency = "" end
------------------------------------ totally unrelated data
if ( Date ~= nil ) then Date = Date else Date = "" end
if ( Via ~= nil and Via ~="" ) then
Via = " — via " .. Via else Via = "" end
if ( AccessDate ~= nil and AccessDate ~="" )
then local retrv_text = " retrieved "
if (sepc == ".") then retrv_text = " Retrieved " end
AccessDate = '<span class="reference-accessdate">'
.. sepc .. retrv_text .. AccessDate .. '</span>'
else AccessDate = "" end
if ( SubscriptionRequired ~= nil and
SubscriptionRequired ~= "" ) then
SubscriptionRequired = sepc .. " " .. createTag({name="span", contents="(subscription required)", params={style="font-size:0.95em; font-size: 90%; color: #555"}})
else
SubscriptionRequired = ""
end
if ( ARXIV ~= nil and ARXIV ~= "" ) then
ARXIV = sepc .. " " .. externallinkid({label="arXiv",link="arXiv",prefix="http://arxiv.org/abs/",id=ARXIV,separator=":",encode=false}) else ARXIV = "" end
if ( ASIN ~= nil and ASIN ~= "" ) then
ASIN = sepc .. " " .. amazon(ASIN, ASINTLD) else ASIN = "" end
if ( BIBCODE ~= nil and BIBCODE ~= "" ) then
BIBCODE = sepc .. " " .. externallinkid({label="Bibcode",link="Bibcode",prefix="http://adsabs.harvard.edu/abs/",id=BIBCODE,separator=":"}) else BIBCODE = "" end
if ( DOI ~= nil and DOI ~= "" ) then
DOI = sepc .. " " .. doi(DOI, DoiBroken) else DOI = "" end
if ( ID ~= nil and ID ~="") then ID = sepc .." ".. ID else ID="" end
if ( ISBN ~= nil and ISBN ~= "") then
ISBN = sepc .. " " .. internallinkid({label="ISBN",link="International Standard Book Number",prefix="Special:BookSources/",id=ISBN}) else ISBN = "" end
if ( ISSN ~= nil and ISSN ~="" ) then
ISSN = sepc .. " " .. externallinkid({label="ISSN",link="International Standard Serial Number",prefix="//www.worldcat.org/issn/",id=ISSN,encode=false}) else ISSN = "" end
if ( JFM ~= nil and JFM ~="" ) then
JFM = sepc .." " .. externallinkid({label="JFM",link="Jahrbuch über die Fortschritte der Mathematik",prefix="http://www.zentralblatt-math.org/zmath/en/search/?format=complete&q=an:",id=JFM}) else JFM = "" end
if ( JSTOR ~= nil and JSTOR ~="") then
JSTOR = sepc .." " .. externallinkid({label="JSTOR",link="JSTOR",prefix="http://www.jstor.org/stable/",id=JSTOR}) else JSTOR = "" end
if ( LCCN ~= nil and LCCN ~="" ) then
LCCN = sepc .." " .. externallinkid({label="LCCN",link="Library of Congress Control Number",prefix="http://lccn.loc.gov/",id=LCCN,encode=false}) else LCCN = "" end
if ( MR ~= nil and MR ~="" ) then
MR = sepc .." " .. externallinkid({label="MR",link="Mathematical Reviews",prefix="http://www.ams.org/mathscinet-getitem?mr=",id=MR}) else MR = "" end
if ( OCLC ~= nil and OCLC ~="") then
OCLC = sepc .." " .. externallinkid({label="OCLC",link="OCLC",prefix="//www.worldcat.org/oclc/",id=OCLC}) else OCLC = "" end
if ( OL ~= nil and OL ~="") then
OL = sepc .. " " .. openlibrary(OL) else OL = "" end
if ( OSTI ~= nil and OSTI ~="") then
OSTI = sepc .." " .. externallinkid({label="OSTI",link="Office of Scientific and Technical Information",prefix="http://www.osti.gov/energycitations/product.biblio.jsp?osti_id=",id=OSTI}) else OSTI = "" end
if ( PMC ~= nil and PMC ~="") then
PMC = sepc .." " .. externallinkid({label="PMC",link="PubMed Central",prefix="//www.ncbi.nlm.nih.gov/pmc/articles/PMC",suffix=" ",id=PMC}) else PMC = "" end
if ( PMID ~= nil and PMID ~="") then
PMID = sepc .." " .. externallinkid({label="PMID",link="PubMed Identifier",prefix="//www.ncbi.nlm.nih.gov/pubmed/",id=PMID,encode=false}) else PMID = "" end
if ( RFC ~= nil and RFC ~="") then
RFC = sepc .." " .. externallinkid({label="RFC",link="Request for Comments",prefix="//tools.ietf.org/html/rfc",id=RFC,encode=false}) else RFC = "" end
if ( SSRN ~= nil and SSRN ~="") then
SSRN = sepc .." " .. externallinkid({label="SSRN",link="Social Science Research Network",prefix="http://ssrn.com/abstract=",id=SSRN}) else SSRN = "" end
if ( URL ~= nil and URL ~="") then
URL = " " .. "[" .. URL .. " " .. nowiki(URL) .. "]";
table.insert( z.error_categories, "Pages with citations having bare URLs" );
if config.CitationClass == "web" then
URL = URL .. " <span class='error'>No <code>title=</code> specified</span>"
else
URL = URL .. hiddencomment("Bare URL here");
end
else
URL = ""
end
if ( ZBL ~= nil and ZBL ~="") then
ZBL = sepc .." " .. externallinkid({label="Zbl",link="Zentralblatt MATH",prefix="http://www.zentralblatt-math.org/zmath/en/search/?format=complete&q=an:",id=ZBL}) else ZBL = "" end
if ( Quote and Quote ~="" ) then
if Quote:sub(1,1) == '"' and Quote:sub(-1,-1) == '"' then
Quote = Quote:sub(2,-2);
end
Quote = sepc .." \"" .. Quote .. "\""
PostScript = ""
else
if ( PostScript == nil) then PostScript = "" end
Quote = ""
end
local Archived
if ( nil ~= ArchiveURL and "" ~= ArchiveURL ) then
if ( ArchiveDate ~= nil and ArchiveDate ~="" ) then
ArchiveDate = " " .. ArchiveDate
else
ArchiveDate = " <span class='error'>If you specify <code>archiveurl=</code>, you must also specify <code>archivedate=</code></span> "
table.insert( z.error_categories, 'Pages with archiveurl citation errors' );
end
local arch_text = " archived"
if (sepc == ".") then arch_text = " Archived" end
if ( "no" == DeadURL ) then
Archived = sepc .. " [" .. ArchiveURL .. arch_text .. "] from the original on" .. ArchiveDate
else
if args.url ~= nil and args.url ~= '' then
Archived = sepc .. arch_text .. " from [" .. args.url .. " the original] on" .. ArchiveDate
else
Archived = sepc .. arch_text .. " from <span class='error'>If you specify <code>archiveurl=</code>" ..
", you must also specify <code>url=</code></span> on" .. ArchiveDate
table.insert( z.error_categories, 'Pages with archiveurl citation errors' );
end
end
else
Archived = ""
end
local Lay
if ( nil ~= LaySummary and "" ~= LaySummary ) then
if ( LayDate ~= nil ) then LayDate = " (" .. LayDate .. ")" else LayDate = "" end
if ( LaySource ~= nil ) then
LaySource = " – ''" .. safeforitalics(LaySource) .. "''"
else
LaySource = ""
end
Lay = " [" .. LaySummary .. " lay summary]" .. LaySource .. LayDate
else
Lay = ""
end
if ( nil ~= Transcript and "" ~= Transcript ) then
if ( TranscriptURL ~= nil ) then Transcript = "[" .. TranscriptURL .. Transcript .. "]" end
else
Transcript = ""
end
local Publisher = ""
if ( Periodical and Periodical ~= "" and
config.CitationClass ~= "encyclopaedia" and
config.CitationClass ~= "web" ) then
if ( PublicationDate and PublicationDate ~="" )
then PublicationDate = " " .. PublicationDate
else PublicationDate = "" end
if ( PublisherName and PublisherName ~="" ) then
Publisher = " (" .. PublicationPlace .. PublisherName .. PublicationDate .. ")"
else
if (Location ~= nil and Location ~= '') then Publisher= " (" .. Location .. ")"
else Publisher = "" end
end
else
if ( PublicationDate and PublicationDate ~="" ) then
PublicationDate = " (published " .. PublicationDate .. ")"
else PublicationDate = "" end
if ( PublisherName and PublisherName ~="" ) then
Publisher = sepc .. " " .. PublicationPlace .. PublisherName .. PublicationDate
else
if (Location ~= nil and Location ~= '') then Publisher= sepc .. " " .. Location
else Publisher = "" end
end
end
-- Several of the above rely upon detecting this as nil, so do it last.
if ( Periodical ~= nil and Periodical ~="" ) then
if ( Title and Title ~= "") then
Periodical = sepc .. " ''" .. safeforitalics(Periodical) .. "''"
else
Periodical = "''" .. safeforitalics(Periodical) .. "''"
end
else Periodical = "" end
-- Piece all bits together at last. Here, all should be non-nil.
-- We build things this way because it is more efficient in LUA
-- not to keep reassigning to the same string variable over and over.
local tcommon
if ( config.CitationClass == "journal" and
Periodical ~= "" ) then
if (Others ~= "") then Others = Others .. sepc .. " " end
tcommon = safejoin( {Others, Title, TitleNote, Format, TitleType, Conference, Periodical, Series, Language, Edition, Publisher, Agency, Volume, Issue, Position}, sepc );
elseif ( config.CitationClass == "citation" ) or (config.CitationClass == "encyclopaedia" ) then
tcommon = safejoin( {Title, TitleNote, Format, TitleType, Conference, Periodical, Series, Language, Volume, Issue, Edition, Publisher, Agency, Others, Position}, sepc );
else
tcommon = safejoin( {Title, TitleNote, Series, Format, TitleType, Conference, Periodical, Language, Volume, Issue, Others, Edition, Publisher, Agency, Position}, sepc );
end
local idcommon = safejoin( { ARXIV, ASIN, BIBCODE, DOI, ISBN, ISSN, JFM, JSTOR, LCCN, MR, OCLC, OL, OSTI, PMC, PMID, RFC, SSRN, URL, ZBL, ID, Archived, AccessDate, Via, SubscriptionRequired, Lay, Quote, PostScript }, sepc );
local enddot = "."
if (Quote ~= "") then enddot = "" end
if (args.postscript == "") then enddot = "" end
if ( config.CitationClass == "citation") then enddot = "" end
idcommon = safejoin( { idcommon, enddot }, sepc )
if ( config.CitationClass == "encyclopaedia" ) then
Chapter = Chapter
end
local text
local pgtext = Page .. Pages .. At
if page_error then
table.insert( z.error_categories, 'Pages with citations using conflicting page specifications' );
pgtext = pgtext .. hiddencomment('Bad page specification here');
end
if ( "" ~= Authors ) then
if (Coauthors ~= "")
then Authors = Authors .. "; " .. Coauthors
end
if ( "" ~= Date )
then Date = " ("..Date..")" .. OrigYear .. sepc .. " "
else
if ( string.sub(Authors,-1,-1) == sepc) --check end character
then Authors = Authors .. " "
else Authors = Authors .. sepc .. " "
end
end
if ( "" ~= Editors) then
local in_text = " in "
if (sepc == '.') then in_text = " In " end
if (string.sub(Editors,-1,-1) == sepc)
then Editors = in_text .. Editors .. " "
else Editors = in_text .. Editors .. sepc .. " "
end
end
text = safejoin( {Authors, Date, Chapter, Editors, tcommon }, sepc );
text = safejoin( {text, pgtext, idcommon}, sepc );
elseif ( "" ~= Editors) then
if ( "" ~= Date ) then
if EditorCount <= 1 then
Editors = Editors .. ", ed."
else
Editors = Editors .. ", eds."
end
Date = " (" .. Date ..")" .. OrigYear .. sepc .. " "
else
if EditorCount <= 1 then
Editors = Editors .. " (ed.)" .. sepc .. " "
else
Editors = Editors .. " (eds.)" .. sepc .. " "
end
end
text = safejoin( {Editors, Date, Chapter, tcommon}, sepc );
text = safejoin( {text, pgtext, idcommon}, sepc );
else
if ( "" ~= Date ) then
if ( string.sub(tcommon,-1,-1) ~= sepc )
then Date = sepc .." " .. Date
else Date = " " .. Date
end
end -- endif ""~=Date
if ( config.CitationClass=="journal" and Periodical ) then
text = safejoin( {Chapter, tcommon}, sepc );
text = safejoin( {text, pgtext, Date, idcommon}, sepc );
else
text = safejoin( {Chapter, tcommon, Date}, sepc );
text = safejoin( {text, pgtext, idcommon}, sepc );
end
end
-- Now enclose the whole thing in a <span/> element
if ( Year == nil ) then
if ( DateIn ~= nil and DateIn ~= "" ) then
Year = selectyear( DateIn )
elseif( PublicationDate ~= nil and PublicationDate ~= "" ) then
Year = selectyear( PublicationDate )
else
Year = ""
end
end
local classname = "citation"
if ( config.CitationClass ~= "citation" )
then classname = "citation " .. (config.CitationClass or "") end
local args = { class=classname }
if ( Ref ~= nil ) then
local id = Ref
if ( "harv" == Ref ) then
local names = {} --table of last names & year
if ( "" ~= Authors ) then
for i,v in ipairs(a) do names[i] = v.last end
elseif ( "" ~= Editors ) then
for i,v in ipairs(e) do names[i] = v.last end
end
if ( names[1] == nil ) then
names[1] = Year
elseif ( names[2] == nil ) then
names[2] = Year
elseif ( names[3] == nil ) then
names[3] = Year
elseif ( names[4] == nil ) then
names[4] = Year
else
names[5] = Year
end
id = anchorid(names)
end
args.id = id;
end
if string.len(text:gsub("<span[^>/]*>.-</span>", ""):gsub("%b<>","")) <= 2 then
table.insert( z.error_categories, 'Pages with empty citations' );
text = '<span class="error">Citation is empty</span>';
end
text = createTag({name="span", contents=text, params=args})
local empty_span = createTag( {name="span", contents=" ", params={style="display: none;"}} );
-- Note: Using display: none on then COinS span breaks some clients.
local OCinS = createTag({name="span", contents=empty_span, params={class="Z3988",title=OCinStitle }})
text = text .. OCinS;
if no_tracking_cats == '' then
for _, v in ipairs( z.error_categories ) do
text = text .. '[[Category:' .. v ..']]';
end
end
return text
end
-- This is used by templates such as {{cite book}} to create the actual citation text.
function z.citation(frame)
local pframe = frame:getParent()
local args = {};
for k, v in pairs( pframe.args ) do
args[k] = v;
end
local config = {};
for k, v in pairs( frame.args ) do
config[k] = v;
end
return citation0( config, args)
end
return z
---------------------------------------------------------------------
--NOTES
--
-- NOTE A1: This Lua module was originally designed to handle a mix
-- of citation styles, crossing Vancouver style with Wikipedia's
-- local Citation Style 1 (CS1) from {Template:Citation/core}.
-- However, the conflicting positions of parameters, scattered
-- in twisted locations across this module, led to a separate
-- variation just to untangle the CS1 format of citations.
--
-- NOTE D2: The placement of dots and other separators between the
-- displayed parameters has been a continual headache, to keep
-- coordinated with the data in parentheses "(data)". There
-- has been a need to pre-check for the existence of related
-- options, to keep from putting double-dots ".." in some cases.
-- In particular, the omission of the "title=" parameter has led
-- to several cases of a spurious dot ". ." because the original
-- design had treated the title as a mandatory parameter.
--
------------------------------------------------------------------------
--HISTORY:
--18Oct2012 Fixed lead-space in Chapter by omitting " ".
--18Oct2012 Fixed lead-space in Chapter/Title as end " " of Authors/Date/...
--19Oct2012 Put HISTORY comments to log major changes (not typos).
--19Oct2012 Fixed extra dot ".." in Title by omitting at end of "tcommon=...".
--19Oct2012 For pages, put   in "p. " etc.
--19Oct2012 Enhanced "pages=" to detect lone page as "p." else "pp." prefix.
--19Oct2012 Fixed to show "." after Periodical name (work, newspaper...).
--19Oct2012 Fixed web-link to have spaces "[... Archived] from the original".
--19Oct2012 Fixed to show ";" between authors & coauthors.
--19Oct2012 Fixed to omit extra "." after coauthors.
--20Oct2012 Fixed COinS data to not urlencode all, as "ctx_ver=Z39.88-2004"
--20Oct2012 Fixed COinS to not end as "&" but use lead "&rft...=" form.
--20Oct2012 Fixed COinS to not url.encode page's "rfr_id=..." pagename.
--20Oct2012 Fixed COinS data when "web" to default to rft.genre "book".
--05Nov2012 Add a span wrapper even when there is no Ref parameter
--15Feb2013 Added Agency for "agency=xx".
--19Feb2013 Put NOTES comments to explain module operation.
--19Feb2013 Copied as Module:Citation/CS1 to alter to match wp:CS1 form.
--19Feb2013 Changed OrigYear to use [__] for CS1 style.
--19Feb2013 Fixed to not show duplicate Publisher/Agency.
--19Feb2013 Moved page-number parameters to after final date.
--19Feb2013 Fixed to not put double-dots after title again.
--20Feb2013 Changed to omit dot "." if already ends with dot.
--20Feb2013 If class "journal" shows Publisher after Periodical/Series.
--20Feb2013 Shifted Format to after Language, and Others after Volume.
--20Feb2013 Set AccessDate + <span class="reference-accessdate">
--20Feb2013 Fixed url when deadurl=no.
--20Feb2013 Added sepc for separator character between parameters.
--20Feb2013 Put "OCLC" for "Online Computer Library Center".
--20Feb2013 Fix empty "authorlink=" as person.link ~= "".
--20Feb2013 Added space after AuthorSep & AuthorNameSep.
--21Feb2013 Added args.contributor (was missing parameter).
--21Feb2013 Fixed EditorSep (was misspelled "EdithorSep").
--21Feb2013 Set OCinSdata.rft_val_fmt = "info:ofi/fmt:kev:mtx:book"
--21Feb2013 Checked to omit blank codes (asin= | doi= etc.).
--21Feb2013 Set enddot to end line if not config.CitationClass "citation".
--21Feb2013 Fixed to show "issn=x" as the ISSN code.
--21Feb2013 Fixed to show "id=x" after Zbl code.
--21Feb2013 Changed to omit double-dot before date when already dot.
--21Feb2013 Order config.CitationClass "citation": Volume, Issue, Publisher.
--21Feb2013 Put warning "Bad DOI (expected "10."..)" in DOI result.
--21Feb2013 Automatically unbolded volume+comma when > 4 long.
--21Feb2013 Changed to allow lowercase "asin-tld".
--22Feb2013 Fixed ref=harv to extract Year from Date.
--22Feb2013 Set Harvard refer. span id if config.CitationClass "citation".
--22Feb2013 Fixed config.CitationClass "citation" as span class="citation".
--22Feb2013 Capitalized "Archived/Retrieved" only when sepc is dot ".".
--23Feb2013 Fixed author editor for "in" or "In" and put space after sepc.
--23Feb2013 Changed to omit dot in "et al." when sepc is "." separator.
--23Feb2013 Fixed "author1-first" to also get args.given or args.given1.
--23Feb2013 Fixed args.article to set Title, after Periodical is Title.
--23Feb2013 Fixed to allow blank Title (such as "contribution=mytitle").
--23Feb2013 Fixed double-dot ".." at end of Editors list
--26Feb2013 Moved "issue=" data to show before "page=".
--26Feb2013 Moved "type=" data to show after "format=".
--26Feb2013 For "pmc=" link, omitted suffix "/?tool=pmcentrez".
--27Feb2013 For coauthors, omitted extra separator after authors.
--27Feb2013 For date, allowed empty date to use month/day/year.
--27Feb2013 Fixed double-dot ".." at end of authors/coauthors list.
--27Feb2013 Reset editor suffix as ", ed." when date exists.
--27Feb2013 Removed duplicate display of "others=" data.
--27Feb2013 Removed parentheses "( )" around "department" TitleNote.
--05Mar2013 Moved Language to follow Periodical or Series.
--05Mar2013 Fixed Edition to follow Series or Volume.
--05Mar2013 Fixed class encyclopaedia to show article as quoted Chapter.
--05Mar2013 Fixed class encyclopaedia to show page as "pp." or "p.".
--07Mar2013 Changed class encyclopaedia to omit "( )" around publisher.
--07Mar2013 Fixed end double-dot by string.sub(idcommon,-1,-1) was "-1,1".
--13Mar2013 Removed enddot "." after "quote=" parameter.
--13Mar2013 Changed config.CitationClass "news" to use "p." page format.
--13Mar2013 Fixed missing "location=" when "web" or "encyclopaedia".
--14Mar2013 Fixed end double-dot after book/work title.
--14Mar2013 Fixed double-dot before "p." or "pp." page number.
--14Mar2013 Fixed config.CitationClass "book" to use p./pp. page.
--18Mar2013 Fixed "page=" to override "pages=" as in markup-based cites.
--19Mar2013 Fixed date of class=journal Periodical to show after page.
--19Mar2013 Changed null "postscript=" to suppress end-dot of citation.
--20Mar2013 If CitationClass is journal, show "others=" before title.
--20Mar2013 If CitationClass is book, show "others=" before edition.
--20Mar2013 If CitationClass is journal, adjust "others=" to have sepc.
--20Mar2013 For class "journal", use book format unless Periodical set.
--
--End