Module:Citation/CS1

    From Nonbinary Wiki
    Revision as of 17:51, 19 February 2013 by m>Wikid77 (moved Publisher / Agency before pages)

    Documentation for this module may be created at Module:Citation/CS1/doc

    ---------------------------------------------------------------------
    -- Module:Citation/CS1 - Lua module for Citation Style 1 templates
    ---------------------------------------------------------------------
    --                               (see NOTES at bottom)
    --require "mw.text"
    
    local z = {
        wikitext = require("Module:Wikitext"),
        mw = require("Module:Mw")
    }
    
    function hideinprint(content)
        return content
    end
    
    function onlyinprint(content)
        return ""
    end
    
    function nowiki(frame, content)
        return z.mw.text.tag({name="nowiki",contents=content,params={}}, frame)
    end
    
    function externallinkid(frame, args)
        local sep = args.separator or " "
        args.suffix = args.suffix or ""
        local t0 = onlyinprint(args.label .. sep .. args.id)
        local t1 = hideinprint("[[" .. args.link .. "|" .. args.label .. "]]" .. sep .. "[" .. args.prefix .. z.mw.url.encode(args.id) .. args.suffix .. " " .. nowiki(frame, args.id) .. "]")
        return t0 .. t1
    end
    
    function internallinkid(frame, args)
        local sep = args.separator or " "
        args.suffix = args.suffix or ""
        local t0 = onlyinprint(args.label .. sep .. args.id)
        local t1 = hideinprint("[[" .. args.link .. "|" .. args.label .. "]]" .. sep .. "[[" .. args.prefix .. args.id .. args.suffix .. "|" .. nowiki(frame, args.id) .. "]]")
        return t0 .. t1
    end
    
    function amazon(frame, id, domain)
        if ( nil == domain ) then 
            domain = "com"
        elseif ( "jp" == domain or "uk" == domain ) then
            domain = "co." .. domain
        end
        return externallinkid(frame, {link="Amazon Standard Identification Number",label="ASIN",prefix="//www.amazon."..domain.."/dp/",id=id})
    end
    
    function doi(frame, id, broken, inactive, nocat)
        local text = externallinkid(frame, {link="Digital object identifier",label="doi",prefix="http://dx.doi.org/",id=id,separator=":"})
        local cat = ""
        if ( inactive ~= nil ) then 
            inactive = " (inactive " .. inactive .. ")" 
            cat = cat .. "[[Category:Pages with DOIs inactive since " .. z.wikitext.canonicalcleanuptime(inactive) .. "]]"
        else 
            inactive = "" 
        end
        if ( string.sub(id,1,3) ~= "10." ) then
            cat = cat .. "[[Category:Pages with DOI errors]]"
        end
        if ( nocat and nocat ~= "" ) then cat = "" end
        return text .. inactive .. cat    
     end
    
    function url(frame, id)
        local t0 = onlyinprint(id)
        local t1 = hideinprint("[" .. id .. " " .. nowiki(frame, id) .. "]")
        return t0 .. t1
    end
    
    function openlibrary(frame, id)
        local cat = ""
        local prefix = ""
        local code = id:sub(-1,-1)
        if ( code == "A" ) then
            prefix = "http://openlibrary.org/authors/OL"
        elseif ( code == "M" ) then
            prefix = "http://openlibrary.org/books/OL"
        elseif ( code == "W" ) then
            prefix = "http://openlibrary.org/works/OL"
        else
            prefix = "http://openlibrary.org/OL"
            cat = cat .. "[[Category:Pages with OL errors]]"
        end
        local text = externallinkid(frame, {link="Open Library",label="OL",prefix=prefix,id=id})
        return text .. cat
    end
    
    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
    
    function listpeople(control, people)
        local sep = control.sep
        local namesep = control.namesep
        local format = control.format
        local maximum = control.maximum
        local text = {}
        for i,person in ipairs(people) do
            if (person.last ~= nil) then
                local mask = person.mask
                local one
                if ( maximum ~= nil and i == maximum + 1 ) then
                    one = "et al."
                elseif ( maximum ~= nil and i > maximum + 1 ) then
                    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) then 
                        if ( "vanc" == format ) then first = reducetoinitials(first) end
                        one = one .. namesep .. first 
                    end
                    if (person.link ~= nil) then one = "[[" .. person.link .. "|" .. one .. "]]" end
                end
                table.insert(text, one)
            end
        end
        local result = table.concat(text, sep) -- construct list
        if ( "scap" == format ) then result= z.mw.text.tag({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
    end
    
    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
    
    function refid(args)
        local p = args.p or ""
        local pp = args.pp or ""
        local loc = args.loc or ""
        return anchorid(args) .. p .. pp .. loc    
    end
    
    function name(args)
        local P1 = args[1] or ""
        if ( args[5] ~= nil) then
            return P1 .. " et al."
        else
            local P2 = args[2] or ""
            local P3 = args[3] or "" 
            local P4 = args[4] or ""
            if ( args[4] ~= nil ) then
                P4 = " " .. P4
                P3 = ", & " .. P3
                P2 = ", " .. P2
            elseif ( args[3] ~= nil ) then
                P3 = " " .. P3
                P2 = " & " .. P2
            elseif ( args[2] ~= nil ) then
                P2 = " " .. P2            
            end
            return P1 .. P2 .. P3 .. P4
        end 
    end
    
    function crossref(frame, args)
        local config = frame.args -- the arguments passed BY the template, in the wikitext of the template itself
        local LB = config.BracketLeft or ""
        local RB = config.BracketRight or ""
        local anchor = args.ref or args.Ref or anchorid(args)
        local text = name(args)
        local loc = args.loc
        local page = args.p or args.page
        local pages = args.pp or args.pages
        if nil == loc then loc = "" else loc = " " .. loc end
        if ( page ~= nil ) then
            local pagesep = config.PageSep or ", p. "
            loc = loc .. pagesep .. page
        end
        if ( pages ~= nil ) then
            local pagessep = config.PagesSep or ", pp. "
            loc = loc .. pagessep .. pages
        end        
        local pagename = args.pagename or ""
        local ps = args.Postscript or ""
        return LB .. "[[" .. pagename .. "#" .. anchor .. "|" .. text .. "]]" .. loc .. RB .. ps
    end
    
    function extractauthor(args, i)
        local 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
            return {
                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
            return nil
        end
    end
    
    function extracteditor(args, i)
        local 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
            return {
                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
            return nil
        end
    end
    
    function citation0(frame, args)
        local config = frame.args -- the arguments passed BY the template, in the wikitext of the template itself
        
        local PPrefix = config.PPrefix or "p.&nbsp;"
        local PPPrefix = config.PPPrefix or "pp.&nbsp;"
        if ( nil ~= args.nopp ) then PPPrefix = "" PPrefix = "" end
        
        -- Transfer unnumbered arguments to numbered arguments if necessary.
        args["author1"] = args["author1"] or args["author"]
        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"]
        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 = {}
        i = 1
        while true do
            a[i] = extractauthor(args, i)
            if ( nil == a[i]) then break end
            i = i + 1
        end
        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 = {} 
        i = 1
        while true do
            e[i] = extracteditor(args, i)
            if ( nil == e[i]) then break end
            i = i + 1
        end
        local Year = args.year 
        local PublicationDate = args.publicationdate
        local OrigYear = args.origyear
        local Date = args.date
        local LayDate = args.laydate
        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.article 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
        local Series = args.series or args.version
        local Volume = args.volume
        local Issue = args.issue or args.number
        local Position = nil
        local Page = args.page
        local Pages = args.pages
        local PP = args.pp
        local At = args.at
        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
        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"]
        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
    
        -- 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:"
        if ( nil ~= Periodical ) then
            OCinSdata["rft.genre"] = "article"
            OCinSdata["rft.jtitle"] = Periodical
    	    if ( nil ~= Title ) then OCinSdata["rft.atitle"] = Title end
        end
        if ( nil ~= Chapter ) then
            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=" .. z.mw.url.encode(name .. "/" .. value)
        end
        for name,value in pairs(OCinSdata) do
            OCinStitle = OCinStitle .. "&" .. name .. "=" .. z.mw.url.encode(value)
        end
        OCinStitle = OCinStitle .. "&rfr_id=info:sid/en.wikipedia.org:"
           .. config.fullpagename  -- 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 "&#44; "
            local AuthorSep = args["author-separator"] or args["separator"] or "&#59; "
            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
        if ( Editors == nil ) then 
            local EditorNameSep = args["editor-name-separator"] or args["name-separator"] or "&#44; "
            local EditorSep = args["editor-separator"] or args["separator"] or "&#59; "
            local EditorFormat = args["editor-format"] or args.editorformat
            local EditorMaximum = tonumber(args["display-editors"] or args.displayeditors) or 3
            local control = { sep = EdithorSep, namesep = EditorNameSep, format = EditorFormat, maximum = EditorMaximum }
            Editors = listpeople(control, e) 
        end
        if ( Date == nil ) 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 .. "&ndash;" .. Ended
                    else
                        Month = "&ndash;"
                    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 ) then
                local Month = args.month
                if ( Month ~= nil ) then 
                    Date = Month .. " " .. Date 
                    local Day = args.day
                    if ( Day ~= nil ) then Date = Day .. " " .. Date end
                end
            end
        end
        if ( PublicationDate == Date or PublicationDate == Year ) then PublicationDate = nil end
        if ( ArchiveURL and "" < ArchiveURL ) then
            local temp = URL
            URL = ArchiveURL
        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 ) then
                Chapter = "<i>" .. Chapter .. "</i>"
            else
                Chapter = "\"" .. Chapter .. "\""
            end
            Chapter = Chapter .. TransChapter
            if ( ChapterLink == nil ) then
                if ( ChapterURL and "" < ChapterURL ) then
                    Chapter = "[" .. ChapterURL .. " " .. Chapter .. "]"
                elseif ( URL and "" < URL ) then 
                    Chapter = "[" .. URL .. " " .. Chapter .. "]"
                    URL = nil
                end
            end
            Chapter = Chapter .. ". " -- 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 = "<i>" .. Title .. "</i>"
            end
            Title = Title .. TransTitle
            if ( TitleLink == nil and URL and "" < URL ) then 
                Title = "[" .. URL .. " " .. Title .. "]"
                URL = nil
            end
            Title = Title .. "." -- with end-dot
        else 
            Title = "" 
        end
        if ( Conference ~= nil ) then
            if ( ConferenceURL ~= nil ) then
                Conference = "[" .. ConferenceURL .. " " .. Conference .. "]"
            end
            Conference = " " .. Conference
        else 
            Conference = "" 
        end
        if ( nil ~= Position or nil ~= Page or nil ~= Pages ) then At = nil end
        if ( nil == 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 ) then 
            Page = "" 
        elseif ( Periodical ~= nil ) then
            Page = ": " .. Page .. "."
        else
            Page = " " .. PPrefix .. Page .. "."
        end
        if ( nil == Pages ) then 
            Pages = "" 
        elseif ( Periodical ~= nil ) then
            Pages = ": " .. Pages .. "."
        else
            if ( tonumber(Pages) ~= nil ) then
              Pages = " " .. PPrefix .. Pages .. "."
            else Pages = " " .. PPPrefix .. Pages .. "."
            end
        end
        if ( At ~= nil ) then At = " " .. At .. "."
        else At = "" end
        if ( Coauthors ~= nil ) then
          if ( Authors ~= nil ) then Coauthors = "; " .. Coauthors end
          if ( Date == nil ) then Coauthors = Coauthors .. "." end
        else Coauthors = "" end
        if ( Others ~= nil ) then Others = " " .. Others .. "." else Others = "" end
        if ( TitleType ~= nil ) then TitleType = " (" .. TitleType .. ")." else TitleType = "" end
        if ( TitleNote ~= nil ) then TitleNote = " (" .. TitleNote .. ")." else TitleNote = "" end
        if ( PublicationPlace ~= nil ) then PublicationPlace = PublicationPlace .. ": " else PublicationPlace = "" end
        if ( Language ~= nil ) then Language = " (in " .. Language .. ")" else Language = "" end
        if ( Edition ~= nil ) then Edition = " (" .. Edition .. " edition)" else Edition = "" end
        if ( Volume ~= nil ) then Volume = " <b>" .. Volume .. "</b>" else Volume = "" end
        if ( Issue ~= nil ) then Issue = " (" .. Issue .. ")" else Issue = "" end
        if ( Series ~= nil ) then Series = " " .. Series .. "." else Series = "" end
        if ( Format ~= nil ) then Format = " (" .. Format .. ")" else Format = "" end
        if ( OrigYear ~= nil ) then OrigYear = " [" .. OrigYear .. "]" else OrigYear = "" end
        if ( Agency ~= nil ) then Agency = " " .. Agency .. "." else Agency = "" end
        if ( Date ~= nil ) then Date = Date else Date = "" end
        if ( Via ~= nil ) then Via = " &mdash; via " .. Via else Via = "" end
        if ( AccessDate ~= nil ) then AccessDate = " Retrieved " .. AccessDate .. "." else AccessDate = "" end
        if ( SubscriptionRequired ~= nil ) then
            SubscriptionRequired = " " .. z.mw.text.tag({name="span", contents="(subscription required)", params={style="font-size:0.95em; font-size: 90%; color: #555"}})
        else
            SubscriptionRequired = ""
        end
        if ( ARXIV ~= nil ) then ARXIV = " " .. externallinkid(frame, {label="arXiv",link="arXiv",prefix="http://arxiv.org/abs/",id=ARXIV,separator=":"}) else ARXIV = "" end
        if ( ASIN ~= nil ) then ASIN = " " .. amazon(frame, ASIN, ASINTLD) else ASIN = "" end
        if ( BIBCODE ~= nil ) then BIBCODE = " " .. externallinkid(frame, {label="Bibcode",link="Bibcode",prefix="http://adsabs.harvard.edu/abs/",id=BIBCODE,separator=":"}) else BIBCODE = "" end
        if ( DOI ~= nil ) then DOI = " " .. doi(frame, DOI, DoiBroken) else DOI = "" end
        if ( ID ~= nil ) then ID = " " .. ID else ID = "" end
        if ( ISBN ~= nil ) then ISBN = " " .. internallinkid(frame, {label="ISBN",link="International Standard Book Number",prefix="Special:BookSources/",id=ISBN}) else ISBN = "" end
        if ( ISSN ~= nil ) then ISSN = " " .. externallinkid(frame, {label="ISSN",link="International Standard Serial Number",prefix="//www.worldcat.org/issn/",id=ISSN}) else ISSN = "" end
        if ( JFM ~= nil ) then JFM = " " .. externallinkid(frame, {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 ) then JSTOR = " " .. externallinkid(frame, {label="JSTOR",link="JSTOR",prefix="http://www.jstor.org/stable/",id=JSTOR}) else JSTOR = "" end
        if ( LCCN ~= nil ) then LCCN = " " .. externallinkid(frame, {label="LCCN",link="Library of Congress Control Number",prefix="http://lccn.loc.gov/",id=LCCN}) else LCCN = "" end
        if ( MR ~= nil ) then MR = " " .. externallinkid(frame, {label="MR",link="Mathematical Reviews",prefix="http://www.ams.org/mathscinet-getitem?mr=",id=MR}) else MR = "" end
        if ( OCLC ~= nil ) then OCLC = " " .. externallinkid(frame, {label="OCLC",link="Online Computer Library Center",prefix="//www.worldcat.org/oclc/",id=OCLC}) else OCLC = "" end
        if ( OL ~= nil ) then OL = " " .. openlibrary(frame, OL) else OL = "" end
        if ( OSTI ~= nil ) then OSTI = " " .. externallinkid(frame, {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 ) then PMC = " " .. externallinkid(frame, {label="PMC",link="PubMed Central",prefix="//www.ncbi.nlm.nih.gov/pmc/articles/PMC",suffix="/?tool=pmcentrez",id=PMC}) else PMC = "" end
        if ( PMID ~= nil ) then PMID = " " .. externallinkid(frame, {label="PMID",link="PubMed Identifier",prefix="//www.ncbi.nlm.nih.gov/pubmed/",id=PMID}) else PMID = "" end
        if ( RFC ~= nil ) then RFC = " " .. externallinkid(frame, {label="RFC",link="Request for Comments",prefix="//tools.ietf.org/html/rfc",id=RFC}) else RFC = "" end
        if ( SSRN ~= nil ) then SSRN = " " .. externallinkid(frame, {label="SSRN",link="Social Science Research Network",prefix="http://ssrn.com/abstract=",id=SSRN}) else SSRN = "" end
        if ( URL ~= nil ) then URL = " " .. url(frame, URL) else URL = "" end
        if ( ZBL ~= nil ) then ZBL = " " .. externallinkid(frame, {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 ~= nil ) then 
            Quote = " \"" .. Quote .. "\"" 
            PostScript = ""
        else 
            if ( PostScript ~= nil ) then PostScript = " " .. PostScript else PostScript = "" end
            Quote = "" 
        end
        local Archived
        if ( nil ~= ArchiveURL ) then
            if ( ArchiveDate ~= nil ) then ArchiveDate = " " .. ArchiveDate
            else ArchiveDate = "" end
            if ( "no" == DeadURL ) then
                Archived = " [" .. ArchiveURL .. "  Archived] from the original on" .. ArchiveDate .. "."
            else
                Archived = " Archived from [" .. args.url .. " the original] on" .. ArchiveDate .. "."
            end
        else
            Archived = ""
        end
        local Lay
        if ( nil ~= LaySummary ) then
            if ( LayDate ~= nil ) then LayDate = " (" .. LayDate .. ")" else LayDate = "" end
            if ( LaySource ~= nil ) then LaySource = " &ndash; <i>" .. LaySource .. "</i>" else LaySource = "" end
            Lay = " [" .. LaySummary .. " lay summary]" .. LaySource .. LayDate
        else
            Lay = ""
        end
        if ( nil ~= Transcript ) then
            if ( TranscriptURL ~= nil ) then Transcript = "[" .. TranscriptURL .. Transcript .. "]" end
        else
            Transcript = ""
        end
        local Publisher
        if ( Periodical ~= nil ) then
            if ( PublicationDate ~= nil ) then PublicationDate = " " .. PublicationDate else PublicationDate = "" end
            if ( PublisherName ~= nil ) then
                Publisher = " (" .. PublicationPlace .. PublisherName .. PublicationDate .. ")."
            else
                if (Location ~=nil) then Publisher= " (" .. Location .. ")."
                else Publisher = "" end
            end
            Edition = ""
        else
            if ( PublicationDate ~= nil ) then PublicationDate = " (published " .. PublicationDate .. ")" else PublicationDate = "" end
            if ( PublisherName ~= nil ) then Publisher = " " .. PublicationPlace .. PublisherName .. PublicationDate .. "." else Publisher = "" end
        end
        -- Several of the above rely upon detecting this as nil, so do it last.
        if ( Periodical ~= nil ) then Periodical = " <i>" .. Periodical .. "</i>."
        else Periodical = "" end
        
        -- Piece all bits together at last.  At this point, 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 idcommon = ARXIV .. ASIN .. BIBCODE .. DOI .. ID .. ISBN .. JFM .. JSTOR .. LCCN .. MR .. OCLC .. OL .. OSTI .. PMC .. PMID .. RFC .. SSRN .. URL .. ZBL .. Archived .. AccessDate .. Via .. SubscriptionRequired .. Lay .. Quote .. PostScript
        local tcommon = Title .. TitleType .. TitleNote .. Format .. Edition .. Language .. Conference .. Periodical .. Series .. Volume .. Issue .. Publisher .. Agency .. Position .. Page .. Pages .. At
        -- DEBUG: tcommon = "/Title="..Title .. "/TitleType="..TitleType .. "/TitleNote="..TitleNote .. "/Format="..Format .. "/Edition="..Edition .. "/Language="..Language .. "/Conference="..Conference .. "/Periodical="..Periodical .. "/Series="..Series .. "/Volume="..Volume .. "/Issue="..Issue .. "/Position="..Position .. Page .. Pages .. At
    
        local text
        if ( "" ~= Authors ) then
            if ( "" ~= Date ) then Date = " ("..Date..")" .. OrigYear .. ". "
            else Authors = Authors .. ". " end
            if ( "" ~= Editors ) then Editors = " in " .. Editors .. "." end
            text = Authors .. Coauthors .. " "..Date .. Chapter .. Others .. Editors .. tcommon .. idcommon
        elseif ( "" ~= Editors) then
            Editors = Editors .. " (eds.)"
            if ( "" ~= Date ) then Date = " (" .. Date ..")" .. OrigYear .. ". "
            else Editors = Editors .. ". " end
            text = Editors .. Date .. Chapter .. tcommon .. Publisher .. Agency .. idcommon
        else
            if ( "" ~= Date ) then Date = " " .. Date .. "." end
            text = Chapter .. tcommon .. Publisher .. Agency .. Date .. idcommon
        end
        
        -- Now enclose the whole thing in a <span/> element
        if ( Year == nil ) then Year = "" end
        local args = { class="citation " .. (config.CitationClass or "") }
        if ( Ref ~= nil ) then 
            local id = Ref
            if ( "harv" == Ref ) then
                local names = {}
                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
        text = z.mw.text.tag({name="span", contents=text, params=args})
    
        local OCinS = z.mw.text.tag({name="span", contents="&nbsp;", params={class="Z3988",title=OCinStitle,style="display: none;"}}) 
            
        return text .. OCinS
    end
    
    function r0(frame, name, group, page)
        if ( name == nil ) then return "" end
        if ( group == nil ) then group = "" end
        local p = ""
        if ( page ~= nil ) then 
            local contents = ":" .. page
            p = z.mw.text.tag({name="sup",contents=contents,params={class="reference",style="white-space:nowrap;"}}) 
        end
        return z.mw.text.tag({name="ref",contents="",params={name=name,group=group}}, frame) .. p
    end
    
    function reflist0(frame, config, args)
        local contents = args.refs or ""
        local liststyle = args.liststyle
        local count = args[1]
        local width = args.colwidth
        local group = args.group or config.default_group
        if ( nil == tonumber(count) and nil == width ) then 
            width = count
            count = nil
        end
        if ( nil == liststyle ) then
            if ( "upper-alpha" == group or "lower-alpha" == group or "upper-roman" == group or "lower-roman" == group or "upper-greek" == group or "lower-greek" == group ) then
                liststyle = group
            else
                liststyle = config.default_liststyle
            end
        end
        local params = {}
        params.class = "reflist"    
        params.style = z.wikitext.liststyle(liststyle)
        if ( nil ~= count ) then        
            params.class = params.class .. " references-column-count references-column-count-" .. count
            params.style = params.style .. " " .. z.wikitext.columncountstyle(count)
        end    
        if ( nil ~= width ) then
            params.class = params.class .. " references-column-width"
            params.style = params.style .. " " .. z.wikitext.columnwidthstyle(width)
        end
        local references = z.mw.text.tag({name="references",contents=contents,params={group=group}}, frame)
        return z.mw.text.tag({name="div",contents=references,params=params})
    end
    
    function refbegin0(frame, config, args)
        local liststyle = args.liststyle
        local indent = args.indent
        local indentsize = args.indentsize
        local count = args[1]
        local width = args.colwidth
        if ( nil == tonumber(count) and nil == width ) then 
            width = count
            count = nil
        end
        if ( nil == liststyle ) then
            if ( "upper-alpha" == group or "lower-alpha" == group or "upper-roman" == group or "lower-roman" == group or "upper-greek" == group or "lower-greek" == group ) then
                liststyle = group
            else
                liststyle = config.default_liststyle
            end
        end
        local params = {}
        params.class = "refbegin"
        params.style = z.wikitext.liststyle(liststyle)
        if ( nil ~= count ) then        
            params.class = params.class .. " references-column-count references-column-count-" .. count
            params.style = params.style .. " " .. z.wikitext.columncountstyle(count)
        end    
        if ( nil ~= width ) then
            params.class = params.class .. " references-column-width"
            params.style = params.style .. " " .. z.wikitext.columnwidthstyle(width)
        end
        local dlopen
        if ( nil ~= indent ) then
            dlopen = z.wikitext.OpenHTMLTag({name="dl",params={style="text-indent: -" .. (indentsize or "3.2") .. "em;"}})
        else
            dlopen = ""
        end
        return z.wikitext.OpenHTMLTag({name="div",params=params}) .. dlopen
    end
    
    function refend0(frame, config, args)
        local indent = args.indent
        local dlclose
        if ( nil ~= indent ) then
            dlclose = "</dl>"
        else
            dlclose = ""
        end
        return dlclose .. "</div>"
    end
    
    -- This is used by {{doi}} to create DOI links in the style used in citations.
    function z.doi(frame)
        local pframe = frame:getParent()
        local id = pframe.args.id or pframe.args[1] or ""
        return doi(frame, id)
    end
    
    -- This is used by {{ISSN}} to create ISSN links in the style used in citations.
    function z.ISSN(frame)
        local pframe = frame:getParent()
        local Name = pframe.args[1] or ""
        return hideinprint(frame, "[[International Standard Serial Number|ISSN]]&nbsp;[http://www.worldcat.org/search?fq=x0:jrnl&q=n2:" .. Name .. " " .. Name .. "]")
    end
    
    -- This is used by templates such as {{SfnRef}} to create the (encoded) anchor name for a Harvard cross-reference hyperlink.
    function z.SFNID(frame)
        local pframe = frame:getParent()
        return anchorid(pframe.args)
    end
    
    -- This is used by templates such as {{Harvard citation}} to create the Harvard cross-reference text.
    function z.Harvard(frame)
        local pframe = frame:getParent()
        return crossref(frame, pframe.args)
    end
    
    -- This is used by templates such as {{cite book}} to create the actual citation text.
    function z.citation(frame)
        local pframe = frame:getParent()
        return citation0(frame, pframe.args)
    end
    
    -- This is used by templates such as {{sfn}} to create the entire cross-reference.
    function z.sfn(frame)
        local pframe = frame:getParent()
        local content = crossref(frame, pframe.args)
        local args = { name = refid(pframe.args) }
        return z.mw.text.tag({name = "ref", contents = content, params = args}, frame)
    end
    
    -- This is used by template {{r}}.
    function z.r(frame)
        local pframe = frame:getParent()
        local config = frame.args -- the arguments passed BY the template, in the wikitext of the template itself
        local args = pframe.args -- the arguments passed TO the template, in the wikitext that instantiates the template
        args.page1 = args.page1 or args.page
        local text = ""
        -- This would be shorter using ipairs(), but that doesn't work on an arguments table supplied to a template.
        local index = 1
        while args[index] ~= nil do
            local arg = args[index]
            local t = r0(frame, arg, args.group, args["page" .. index])
            text = text .. t
            index = index + 1
        end
        return text
    end
    
    -- This is used by template {{ref label}}.
    function z.reflabel(frame)
        local pframe = frame:getParent()
        local config = frame.args -- the arguments passed BY the template, in the wikitext of the template itself
        local args = pframe.args -- the arguments passed TO the template, in the wikitext that instantiates the template
        local P1 = args[1] or ""
        local P2 = args[2] or ""
        local P3 = args[3] or ""
        local id = nil
        local contents = "[[#endnote_" .. P1 .. P3 .. "|&#91;" .. P2 .. "&#93;]]"
        local params = {}
        params.class="reference"
        if ( args.noid == nil or args.noid == "" ) then params.id = "ref_" .. P1 .. P3 end
        return z.mw.text.tag({name="sup",contents=contents,params=params})
    end
    
    -- This is used by template {{note label}}.
    function z.notelabel(frame)
        local pframe = frame:getParent()
        local config = frame.args -- the arguments passed BY the template, in the wikitext of the template itself
        local args = pframe.args -- the arguments passed TO the template, in the wikitext that instantiates the template
        local id = args[1] or ""
        local arrow = args[3] or ""
        local postscript = args[4] or ""
        local contents 
        if arrow ~= "" then
            local sup_arrow = z.mw.text.tag({name="sup",contents=arrow,params={}})
            contents = "[[#ref_" .. id .. arrow .. "|<b>" .. sup_arrow .. "</b>]]" .. postscript
            if "none" == arrow then arrow = "^" end -- Change this AFTER using it in the ID parameter and the contents.
        else
            contents = (args[2] or "") .. postscript
        end
        local params = { class="citation wikicite" }
        if id ~= "" and ( args.noid == nil or args.noid == "" ) then 
            params.id = z.mw.url.encodeAnchor("endnote_" .. id .. arrow)
        end
        return z.mw.text.tag({name="span",contents=contents,params=params})
    end
    
    -- This is used by templates {{reflist}} and {{notelist}}.
    function z.reflist(frame)
        local pframe = frame:getParent()
        local config = frame.args -- the arguments passed BY the template, in the wikitext of the template itself
        local args = pframe.args -- the arguments passed TO the template, in the wikitext that instantiates the template
        return reflist0(frame, config, args)
    end
    
    -- This is used by template {{refbegin}}.
    function z.refbegin(frame)
        local pframe = frame:getParent()
        local config = frame.args -- the arguments passed BY the template, in the wikitext of the template itself
        local args = pframe.args -- the arguments passed TO the template, in the wikitext that instantiates the template
        return refbegin0(frame, config, args)
    end
    
    -- This is used by template {{refend}}.
    function z.refend(frame)
        local pframe = frame:getParent()
        local config = frame.args -- the arguments passed BY the template, in the wikitext of the template itself
        local args = pframe.args -- the arguments passed TO the template, in the wikitext that instantiates the template
        return refend0(frame, config, args)
    end
    
    -- This is used by template {{efn}}.
    function z.efn(frame)
        local pframe = frame:getParent()
        local config = frame.args -- the arguments passed BY the template, in the wikitext of the template itself
        local args = pframe.args -- the arguments passed TO the template, in the wikitext that instantiates the template
        return z.mw.text.tag({name="ref",contents=(args[1] or ""),params={name=args.name,group=config.default_group}}, frame)
    end
    
    return z
    ------------------------------------------------------------------------
    --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.&nbsp;" etc.
    --19Oct2012 Enhanced "pages=" to detect lone page as "p." else "pp." prefix.
    --19Oct2012 Fixed to show "." after Periodical name (work, newspaper, etc.).
    --19Oct2012 Fixed web-link to have spaces "[...  Archived] from the original".
    --19Oct2012 Fixed to show ";" between authors & coauthors.
    --19Oct2012 Fixed to omit "." 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 Copied as Module:Citation/CS1 to alter to match wp:CS1 form.
    --19Feb2013 Changed OrigYear to use [__] for CS1 style.
    --
    --End