Module:Citation/CS1

local z = { error_categories = {}; }

-- Formats a hidden comment for error trapping not intended to be visible to readers function hiddencomment( content ) return ' ' .. content .. ' '; end

-- This returns a string with HTML character entities for wikitext markup characters. function wikiescape(text) text = text:gsub( '[&\'%[%]{|}]', {               ['&'] = '&#38;',                ["'"] = '&#39;',                ['['] = '&#91;',                [']'] = '&#93;',                ['{'] = '&#123;',                ['|'] = '&#124;',	            ['}'] = '&#125;' } ); 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 .. ""   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, '["&\'<=>%[%]{|}]', {       ['"'] = '&#34;',        ['&'] = '&#38;',        ["'"] = '&#39;',        ['<'] = '&#60;',        ['='] = '&#61;',        ['>'] = '&#62;',        ['['] = '&#91;',        [']'] = '&#93;',        ['{'] = '&#123;',        ['|'] = '&#124;',        ['}'] = '&#125;',    } ) s = string.sub( string.gsub( '\n' .. s, '\n[#*:;]', { ["\n#"] = "\n&#35;", ["\n*"] = "\n&#42;", ["\n:"] = "\n&#58;", ["\n;"] = "\n&#59;", } ), 2 )   s = string.gsub( s, '://', '&#58;//' ) s = string.gsub( s, 'ISBN ', 'ISBN&#32;' ) s = string.gsub( s, 'RFC ', 'RFC&#32;' )

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.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.label .. "" .. sep .. "" .. 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 = "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 = ' Bad DOI (expected "10." prefix) in code number ' end return text .. inactive .. cat end

-- Escape sequences for content that will be used for URL descriptions function safeforurl( str ) return str:gsub( '[%[%]\n]', {           ['['] = '&#91;',	        [']'] = '&#93;',	        ['\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  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,  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 = " " .. str; end if str:sub(-1,-1) == "'" then str = str .. " "; 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 ) -- Is the input a simple number? local num = tonumber( str ); if num ~= nil and num > 0 and num < 2100 and num == math.abs(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; else -- Can't make sense of this input, return blank. 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}) .. ' Bad OL specified '; 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 lastauthoramp = control.lastauthoramp; 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("&mdash;",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 = "" .. one .. "" end end table.insert(text, one) end end local count = #text; if count > 1 and lastauthoramp ~= nil and lastauthoramp ~= "" and not etal then text[count-1] = text[count-1] .. " & " .. text[count]; text[count] = nil; end 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 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 or 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 or "." 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 LastAuthorAmp = args.lastauthoramp 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, 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, 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 ) 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

if (Periodical ~= nil and Periodical ~= "") and (Chapter == nil or Chapter == '') and (Title ~= nil and Title ~= "") then Chapter = Title ChapterLink = TitleLink TransChapter = TransTitle Title = nil TitleLink = nil TransTitle = nil end

-- 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 ";" 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, lastauthoramp = LastAuthorAmp } Authors = listpeople(control, a)    end local EditorCount if ( Editors == nil ) then local EditorNameSep = args["editor-name-separator"] or args["name-separator"] or "," EditorNameSep = EditorNameSep .. " "       local EditorSep = args["editor-separator"] or ";" EditorSep = EditorSep .. " "       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, lastauthoramp = LastAuthorAmp } 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 local OriginalURL = URL if ( ArchiveURL and "" < ArchiveURL ) then if ( DeadURL ~= "no" ) then URL = ArchiveURL end end if ( TransTitle and "" < TransTitle ) then TransTitle = " [" .. TransTitle .. "&#93;" else TransTitle = "" end if ( TransChapter and "" < TransChapter ) then TransChapter = " [" .. TransChapter .. "&#93;" else TransChapter = "" end if ( Chapter and "" < Chapter ) then if ( ChapterLink and "" < ChapterLink ) then Chapter = "" .. Chapter .. "" end if ( Periodical and "" < Periodical ) and (Title ~= nil and Title ~= "" ) 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 = "" .. 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 = " '''" .. Volume .. "'''"       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 = " &mdash; via " .. Via else Via = "" end if ( AccessDate ~= nil and AccessDate ~="" ) then local retrv_text = " retrieved " if (sepc == ".") then retrv_text = " Retrieved " end AccessDate = ' ' .. sepc .. retrv_text .. AccessDate .. ' '   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 .. " No  specified " 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 = " If you specify, you must also specify  " 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 OriginalURL ~= nil and OriginalURL ~= '' then Archived = sepc .. arch_text .. " from [" .. OriginalURL .. " the original] on" .. ArchiveDate else Archived = sepc .. arch_text .. " from If you specify " .. ", you must also specify 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 = sepc .. " [" .. 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, Conference, Periodical, TitleType, Series, Language, Edition, Publisher, Agency, Volume, Issue, Position}, sepc ); elseif ( config.CitationClass == "citation" ) or (config.CitationClass == "encyclopaedia" ) then tcommon = safejoin( {Title, TitleNote, Format, Conference, Periodical, TitleType, 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 }, sepc );

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 if ( config.CitationClass == "citation") then PostScript = "" end if PostScript ~= '' and PostScript ~= nil and PostScript ~= sepc then text = safejoin( {text, sepc}, sepc ); --Deals with italics, spaces, etc.        text = text:sub(1,-2); --Remove final seperator end text = safejoin( {text, PostScript}, sepc );

-- Now enclose the whole thing in a 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("/]*>.- ", ""):gsub("%b<>","")) <= 2 then table.insert( z.error_categories, 'Pages with empty citations' ); text = ' Citation is empty '; 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 .. '';       end end return text end

-- This is used by templates such as to create the actual citation text. function z.citation(frame) local pframe = frame:getParent local args = {}; for k, v in pairs( pframe.args ) do       if v ~= '' then args[k] = v;       elseif k == 'postscript' then args[k] = v;       end 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 &nbsp 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 + --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