--require "mw.text"

local z = {
    wikitext = require "Module:Wikitext"
}

function hideinprint(frame, content)
    return content
end

function onlyinprint(frame, content)
    return ""
end

function nowiki(frame, content)
    return z.wikitext.tag(frame, {name="nowiki",contents=content,params={)))
end

function externallinkid(frame, args)
    local sep = args.separator or " "
    args.suffix = args.suffix or ""
    local t0 = onlyinprint(frame, args.label .. sep .. args.id)
    local t1 = hideinprint(frame, "[[" .. args.link .. "|" .. args.label .. "]]" .. sep .. "[" .. args.prefix .. z.wikitext.urlencode(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(frame, args.label .. sep .. args.id)
    local t1 = hideinprint(frame, "[[" .. 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
    local text = externallinkid(frame, {link="Amazon Standard Identification Number",label="ASIN",prefix="//www.amazon."..domain.."/dp/",id=id})
    if ( string.sub(id,1,3) ~= "10." ) then
        text = text .. "[[Category:Pages with DOI errors]]"
    end
    return text
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 ~= nil and nocal ~= "" ) then cat = "" end
    return text .. inactive .. cat    
 end

function url(frame, id)
    local t0 = onlyinprint(frame, id)
    local t1 = hideinprint(frame, "[" .. id .. " " .. nowiki(frame, id) .. "]")
    return t0 .. t1
end

function openlibrary(frame, id)
    local cat = ""
    local prefix = ""
    local code = string.sub(id,string.length(id),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 listpeople(config, people)
    local text = ""
    local sep = config.AuthorSep or "&#59;"
    for i,person in ipairs(people) do
        if (person.last ~= nil) then
            local one = person.last
            if (person.first ~= nil) then one = one .. ", " .. person.first end
            if (person.link ~= nil) then one = "[[" .. person.link .. "|" .. one .. "]]" end
            text = text .. one
            if ( people[i + 1] ~= nil ) then text = text .. sep .. " " end
        end
    end
    return text
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 or ""
    local page = args.p or args.page
    local pages = args.pp or args.pages
    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 ps = args.Postscript or ""
    return LB .. "[[#" .. anchor .. "|" .. text .. "]]" .. loc .. RB .. ps
end

function citation0(frame, args)
    local config = frame.args -- the arguments passed BY the template, in the wikitext of the template itself
    
    -- Pick out the relevant fields from the arguments.  Different citation templates define different field names for the same underlying things.
    local AuthorMask = args.authormask or args.authormask
    local Authors = args.authors 
    local a = {}
    for i=1,9,1 do
        local last = args["last" .. i] or args["surname" .. i] or args["author" .. i]
        if ( last ~= nil ) then
            a[i] = {}
            a[i].last = last
            a[i].first = args["first" .. i] or args["given" .. i]
            a[i].link = args["author" .. i .. "link"] or args["authorlink" .. i]
        end
    end
    if ( a[1] == nil ) then
        local i = ""
        local last = args["last" .. i] or args["surname" .. i] or args["author" .. i]
        if ( last ~= nil ) then
            a[1] = {}
            a[1].last = last
            a[1].first = args["first" .. i] or args["given" .. i]
            a[1].link = args["author" .. i .. "link"] or args["authorlink" .. i]
        end
    end
    local Coauthors = args.coauthor or args.coauthors 
    local Editors = args.editors 
    local e = {}    
    for i=1,9,1 do
        local last = args["editor" .. i .. "-last"] or args["editor-last" .. i] or args["EditorSurname" .. i] or args["Editor" .. i]
        if ( last ~= nil ) then
            e[i] = {}
            e[i].last = last
            e[i].first = args["editor" .. i .. "-first"] or args["editor-first" .. i] or args["EditorGiven" .. i]
            e[i].link = args["editor" .. i .. "link"] or args["editorlink" .. i]
        end
    end
    if ( e[1] == nil ) then
        local i = ""
        local last = args["editor" .. i .. "-last"] or args["editor-last" .. i] or args["EditorSurname" .. i] or args["Editor" .. i]
        if ( last ~= nil ) then
            e[1] = {}
            e[1].last = last
            e[1].first = args["editor" .. i .. "-first"] or args["editor-first" .. i] or args["EditorGiven" .. i]
            e[1].link = args["editor" .. i .. "link"] or args["editorlink" .. i]
        end
    end
    local Year = args.year or args.publicationdate
    local Date = args.date
    local Title = args.title or args.encyclopaedia or args.encyclopedia
    local Chapter = args.chapter or args.article
    local URL = args.archiveurl or args.url
    local ChapterURL = args.chapterurl
    local Periodical = args.journal or args.newspaper or args.magazine or args.work
    local Series = args.series
    local Volume = args.volume
    local Issue = args.issue or args.number
    local Pages = args.pages or args.page
    local Edition = args.edition
    local Place = args.place or args.location
    local PublicationPlace = args.publicationplace or args.place or args.location
    local Publisher = args.publisher
    local SubscriptionRequired = args.subscription
    local Via = args.via
    local Accessed = args.accessdate
    local Language = args.language
    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.DoiBroken
    local ID = args.id or args.ID
    local ISBN = 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  

    -- At this point fields may be nil if they weren't specified in the template use.  We can use that fact.
    
    -- These data form a COinS tag (see <http://ocoins.info/>) which allows automated tools to parse the citation information.
    local OCinSdata = {}
    OCinSdata.ctx_ver = "Z39.88-2004" 
    OCinSdata.rft_val_fmt = "info:ofi/fmt:kev:mtx:"
    OCinSdata.rfr_id = "info:sid/en.wikipedia.org:" .. config.fullpagename    
    if ( nil ~= Periodical ) then
        OCinSdata["rft.genre"] = "article"
        OCinSdata["rft.jtitle"] = Periodical
	    if ( nil ~= Title ) then OCinSdata["rft.atitle"] = Title end
    elseif ( 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
    if ( PublicationPlace or Place ) then OCinSdata["rft.place"] = (PublicationPlace or Place) end
    OCinSdata["rft.date"] = Date
    OCinSdata["rft.series"] = Series
    OCinSdata["rft.volume"] = Volume
    OCinSdata["rft.issue"] = Issue
    OCinSdata["rft.pages"] = At
    OCinSdata["rft.edition"] = Edition
    OCinSdata["rft.pub"] = Publisher
    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 = {}
    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 = ""    
    for name,value in pairs(OCinSids) do
        OCinStitle = OCinStitle .. "rft_id=" .. z.wikitext.urlencode(name .. "/" .. value) .. "&"
    end
    for name,value in pairs(OCinSdata) do
        OCinStitle = OCinStitle .. z.wikitext.urlencode(name .. "=" .. value) .. "&"
    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 Authors = listpeople(config, a) end
    if ( Editors == nil ) then Editors = listpeople(config, e) end
    if ( Date == nil ) then
        Date = Year
        if ( Date ~= nil ) then
            if ( args.month ~= nil ) then 
                Date = args.month .. " " .. Date 
                if ( args.day ~= nil ) then Date = args.day .. " " .. Date end
            end
        end        
    end
    if ( Periodical ~= nil ) then
        Chapter = Title
        Title = Periodical
    end
    if ( Chapter ~= nil ) then 
        Chapter = "\"" .. Chapter .. "\""
        if ( ChapterURL ~= nil ) then
            Chapter = "[" .. ChapterURL .. " " .. Chapter .. "]"
        elseif ( URL ~= nil ) then 
            Chapter = "[" .. URL .. " " .. Chapter .. "]"
            URL = nil
        end
        Chapter = " " .. Chapter .. "."
    else 
        Chapter = "" 
    end    
    if ( Title ~= nil ) then
        if ( URL ~= nil ) then 
            Title = "[" .. URL .. " " .. Title .. "]"
            URL = nil
        end
        Title = " ''" .. Title .. "''."
    else 
        Title = "" 
    end
    if ( Publisher ~= nil ) then Publisher = " " .. Publisher .. "." else Publisher = "" 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 = " '''" .. Volume .. "'''" else Volume = "" end
    if ( Issue ~= nil ) then Issue = " (" .. Issue .. ")" else Issue = "" end
    if ( Pages ~= nil ) then Pages = " :" .. Pages else Pages = "" end
    if ( Series ~= nil ) then Series = " " .. Series .. "." else Series = "" end
    if ( Format ~= nil ) then Format = " (" .. Format .. ")" else Format = "" end
    if ( Date ~= nil ) then Date = " (" .. Date .. ")" else Date = "" end
    if ( Via ~= nil ) then Via = " &mdash; via " .. Via else Via = "" end
    if ( Accessed ~= nil ) then Accessed = " Accessed on " .. Accessed .. "." else Accessed = "" end
    if ( SubscriptionRequired ~= nil ) then
        SubscriptionRequired = z.wikitext.tag(frame, {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, id) 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
    
    -- Piece all of the bits together at last.  At this point, all of these should be guaranteed 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 common = ARXIV .. ASIN .. BIBCODE .. DOI .. ID .. ISBN .. JFM .. JSTOR .. LCCN .. MR .. OCLC .. OL .. OSTI .. PMC .. PMID .. RFC .. SSRN .. URL .. ZBL .. Accessed .. Via .. SubscriptionRequired
    local text
    if ( "" ~= Authors ) then
        if ( "" ~= Date ) then Date = Date .. "." else Authors = Authors .. "." end
        if ( "" ~= Editors ) then Editors = " in " .. Editors .. "." end
        text = Authors .. Date .. Chapter .. Editors .. Title .. Format .. Edition .. Language .. Volume .. Issue .. Pages .. Series .. PublicationPlace .. Publisher .. common
    elseif ( "" ~= Editors) then
        Editors = Editors .. " (eds.)"
        if ( "" ~= Date ) then Date = Date .. "." else Editors = Editors .. "." end
        text = Editors .. Date .. Chapter .. Title .. Format .. Edition .. Language .. Volume .. Issue .. Pages .. Series .. PublicationPlace .. Publisher .. common
    else
        text = Chapter .. Title .. Format .. Edition .. Language .. Volume .. Issue .. Pages .. Series .. PublicationPlace .. Publisher .. Date .. common
    end
    
    -- Now enclose the whole thing in a <span/> element if it is cross-linked from elsewhere.
    if ( Year == nil ) then Year = "" end
    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
        local args = { class="citation " .. (config.CitationClass or ""), id=id }
        text = z.wikitext.tag(frame, {name="span", contents=text, params=args})
    end
    
    local hiddenspace = z.wikitext.tag(frame, {name="span", contents="&nbsp;", params={style="display: none;"))) 
    local OCinS = z.wikitext.tag(frame, {name="span", contents=hiddenspace, params={class="Z3988",title=OCinStitle))) 
        
    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.wikitext.tag(frame, {name="sup",contents=contents,params={class="reference",style="white-space:nowrap;"))) 
    end
    return z.wikitext.tag(frame, {name="ref",contents="",params={name=name,group=group))) .. p
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 mw.text.tag{name = "ref", contents = content, params = args}
    return z.wikitext.tag(frame, {name = "ref", contents = content, params = args})
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 and args.noid ~= "" ) then params.id = "ref_" .. P1 .. P3 end
    return z.wikitext.tag(frame, {name="sup",contents=contents,params=params})
end

return z