Jump to content
Wikipedia The Free Encyclopedia

Module:Cite Q

From Wikipedia, the free encyclopedia
Module documentation[view] [edit] [history] [purge]
Warning This Lua module is used on approximately 16,000 pages and changes may be widely noticed. Test changes in the module's /sandbox or /testcases subpages, or in your own module sandbox. Consider discussing changes on the talk page before implementing them.
This module depends on the following other modules:

Implements {{Cite Q }}

Test cases at:

The above documentation is transcluded from Module:Cite Q/doc. (edit | history)
Editors can experiment in this module's sandbox (edit | diff) and testcases (create) pages.
Subpages of this module.

 require('strict')

 localwdib=require('Module:WikidataIB')
 localgetValue=wdib._getValue
 local_getPropOfProp=wdib._getPropOfProp
 localfollowQid=wdib._followQid
 localgetPropertyIDs=wdib._getPropertyIDs
 localcite_cfg=mw.loadData('Module:Cite/config')
 localcfg=mw.loadData('Module:Cite_Q/config')
 localcs1_module='Module:Citation/CS1'-- don't load the module yet, may not be needed

 -------------------------------------------------------------------------------
 -- makeOrdinal needs to be internationalised along with cfg.i18n_t
 -- takes cardinal number as a numeric and returns the ordinal as a string
 -- we need three exceptions in English for 1st, 2nd, 3rd, 21st, .. 31st, etc.
 -------------------------------------------------------------------------------
 localmakeOrdinal=function(cardinal)
 localcard=tonumber(cardinal)
 ifnotcardthenreturncardinalend
 localordsuffix=cfg.i18n_t.ordinal.default
 ifcard%10==1then
 ordsuffix=cfg.i18n_t.ordinal[1]
 elseifcard%10==2then
 ordsuffix=cfg.i18n_t.ordinal[2]
 elseifcard%10==3then
 ordsuffix=cfg.i18n_t.ordinal[3]
 end
 -- In English, 1, 21, 31, etc. use 'st', but 11, 111, etc. use 'th'
 -- similarly for 12 and 13, etc.
 if(card%100==11)or(card%100==12)or(card%100==13)then
 ordsuffix=cfg.i18n_t.ordinal.default
 end
 returncard..ordsuffix
 end

 --[[--------------------------< I S _ S E T >--------------------------------------------------------------
 Returns true if argument is set; false otherwise. Argument is 'set' when it exists (not nil) or when it is not an empty string.
 ]]
 localfunctionis_set(var)
 returnnot(var==nilorvar=='')
 end

 --[[--------------------------< I N _ A R R A Y >--------------------------------------------------------------
 Whether needle is in haystack (taken from Module:Citation/CS1/Utilities)
 ]]
 localfunctionin_array(needle,haystack)
 ifneedle==nilthen
 returnfalse
 end
 forn,vinipairs(haystack)do
 ifv==needlethen
 returnn
 end
 end
 returnfalse
 end


 --[[--------------------------< A C C E P T _ V A L U E >-------------------------------------------------------
 Accept WD value by framing in ((...)) if param_val is equal to keyword; else pass-through WD value as is.
 ]]
 localfunctionaccept_value(param_val,wd_val)
 localval=param_val

 ifvalthen
 ifin_array(val,{'accept','))((',':d:'})then
 val='(('..wd_val..'))'
 elseif'((accept))'==valthen
 val='accept'
 elseif'(())(())'==valthen
 val='))(('
 elseif'((:d:))'==valthen
 val=':d:'
 else
 val=wd_val
 end
 end

 returnval
 end

 -- function to fetch a value to display
 localfunctionmakelink(v,out,link,maxpos,wdl)
 locallabel
 ifv.mainsnak.snaktype=="value"then
 ifv.mainsnak.datatype=="wikibase-item"then
 localqnumber=v.mainsnak.datavalue.value.id
 localsitelink=mw.wikibase.getSitelink(qnumber)
 ifqnumber=="Q2818964"thensitelink=nilend-- suppress link to "Various authors"
 ifv.qualifiersandv.qualifiers.P1932then
 label=v.qualifiers.P1932[1].datavalue.value
 else
 label=mw.wikibase.getLabel(qnumber)
 iflabelthen
 label=mw.text.nowiki(label)
 else
 label=qnumber-- should add tracking category
 end
 end
 localposition=maxpos+1-- Default to 'next' author.
 -- use P1545 (series ordinal) instead of default position.
 ifv["qualifiers"]andv.qualifiers["P1545"]andv.qualifiers["P1545"][1]then
 position=tonumber(v.qualifiers["P1545"][1].datavalue.value)
 end
 maxpos=math.max(maxpos,position)
 ifsitelinkthen
 -- just the plain name,
 -- but keep a record of the links, using the same index
 out[position]=label
 link[position]=sitelink
 else
 ifwdlthen
 -- show that there's a Wikidata entry available
 out[position]=string.format(
 "[[:d:Q%s|%s]]&nbsp;<span title='%s'>[[File:Wikidata-logo.svg|16px|alt=|link=]]</span>",
 v.mainsnak.datavalue.value["numeric-id"],
 label,
 cfg.i18n_t["errors"]["local-article-not-found"]
 )
 else
 -- no Wikidata links wanted, so just give the plain label
 out[position]=label
 end
 end
 elseifv.mainsnak.datatype=="string"then
 localposition=maxpos+1-- Default to 'next' author.
 -- use P1545 (series ordinal) instead of default position.
 ifv["qualifiers"]andv.qualifiers["P1545"]andv.qualifiers["P1545"][1]then
 position=tonumber(v.qualifiers["P1545"][1].datavalue.value)
 end
 maxpos=math.max(maxpos,position)
 out[position]=v.mainsnak.datavalue.value
 else
 -- not a wikibase-item or a string!
 end
 else
 -- code here if we want to return something when author is "unknown"
 ifv.qualifiersandv.qualifiers.P1932then
 label=v.qualifiers.P1932[1].datavalue.value
 else
 label=cfg.i18n_t["unknown-author"]..(cfg.i18n_t.trackingcat["unknown-author"]or"")
 end
 maxpos=maxpos+1
 out[maxpos]=label
 end
 returnmaxpos
 end

 --[=[-------------------------< G E T _ N A M E _ L I S T >----------------------------------------------------
 get_name_list -- adapted from getAuthors code taken from Module:RexxS
 arguments:
 	nl_type - type of name list to fetch: nl_type = 'author' for authors; 'editor' for editors; 'translator' for translators
 	args - pointer to the parameter arguments table from the template call
 	qid - value from |qid= parameter; the Q-id of the source (book, etc.) in qid
 	wdl - value from the |wdl= parameter; a Boolean passed to enable links to Wikidata when no article exists
 returns nothing; modifies the args table
 ]=]

 localfunctionget_name_list(nl_type,args,qid,wdl)
 localpropertyID="P50"
 localfallbackID="P2093"-- author name string

 ifnl_type=="author"then
 propertyID='P50'-- for authors
 fallbackID='P2093'-- author-string
 elseifnl_type=="editor"then
 propertyID='P5769'-- "editor-in-chief"
 fallbackID='P98'-- for editors - So-called "fallbacks" are actually a second set of properties processed
 -- TBD. Take book series editors into account as well (if they have a separate P code as well)?
 elseifnl_type=="translator"then
 propertyID='P655'-- for translators
 fallbackID=nil
 --	elseif 'contributor' == nl_type then
 --		f.e. author of forewords (P2679) and afterwords (P2680); requires |contribution=, |title= and |author=
 --		propertyID = 'P'		-- for contributors
 --		fallbackID = nil
 else
 return-- not specified so return
 end

 -- wdl is a Boolean passed to enable links to Wikidata when no article exists
 -- if "false" or "no" or "0" is passed set it false
 -- if nothing or an empty string is passed set it false
 ifwdland(#wdl>0)then
 wdl=wdl:lower()
 wdl=in_array(wdl,{"false","no","0"})
 else
 -- wdl is empty, so
 wdl=false
 end

 localprops=nil
 localfallback=nil
 ifmw.wikibase.entityExists(qid)then
 props=mw.wikibase.getAllStatements(qid,propertyID)
 ifpropsandfallbackIDthen
 fallback=mw.wikibase.getAllStatements(qid,fallbackID)
 end
 end

 -- Make sure it actually has at least one of the properties requested
 ifnot(propsandprops[1])andnot(fallbackandfallback[1])then
 returnnil
 end

 -- So now we have something to return:
 -- table 'out' is going to store the names(s):
 -- and table 'link' will store any links to the name's article
 localout={}
 locallink={}
 localmaxpos=0
 ifpropsandprops[1]then
 fork,vinpairs(props)do
 maxpos=makelink(v,out,link,maxpos,wdl)
 end
 end
 iffallbackandfallback[1]then
 -- second properties
 fork,vinpairs(fallback)do
 maxpos=makelink(v,out,link,maxpos,wdl)
 end
 end

 -- if there's anything to return, then insert the additions in the template arguments table
 -- in the form |author1=firstname secondname |author2= ...
 -- Renumber, in case we have inconsistent numbering
 localkeys={}
 fork,vinpairs(out)do
 keys[#keys+1]=k
 end
 table.sort(keys)-- as they might be out of order
 fori,kinipairs(keys)do
 out[k]=out[k]:gsub('&#39;','\'');-- prevent cs1|2 multiple names categorization; replace html entity with the actual character
 mw.log(i.." "..k.." "..(out[k]))
 ifargs[nl_type..i]then-- name gets overwritten
 -- pull corresponding -link only if overwritten name is same as WD name
 iflink[k]and(args[nl_type..i]==out[k])then
 args[nl_type..'-link'..i]=args[nl_type..'-link'..i]orlink[k]-- author-linkn or editor-linkn
 end
 else-- name does not get overwritten, so pull name from WD
 args[nl_type..i]=out[k]
 iflink[k]then
 args[nl_type..'-link'..i]=args[nl_type..'-link'..i]orlink[k]-- author-linkn or editor-linkn
 end
 end
 end
 end

 -- gets language codes used for a monolingual text property as a table
 localfunction_getLangOfProp(qid,pid)
 ifnotpidthenreturn{}end
 localout={}
 localprops=mw.wikibase.getAllStatements(qid,pid)
 fori,vinipairs(props)do
 ifv.mainsnak.datatype=="monolingualtext"andv.mainsnak.datavaluethen
 out[#out+1]=v.mainsnak.datavalue.value.language
 end
 end
 returnout
 end
 localfunctiongetLangOfProp(frame)
 localpid=frame.args.pidormw.text.trim(frame.args[1]or"")
 ifpid==""thenreturnend
 localqid=frame.args.qid
 ifqid==""thenqid=nilend
 returntable.concat(_getLangOfProp(qid,pid),", ")
 end

 -- gets the language codes of a Wikidata entry as a table
 localfunction_lang_code(qid)
 locallc=_getPropOfProp({qid=qid,prop1="P407",prop2="P424",ps=1})
 iflcthenreturnmw.text.split(lc,"[, ]+")end
 lc=_getPropOfProp({qid=qid,prop1="P407",prop2="P218",ps=1})
 iflcthenreturnmw.text.split(lc,"[, ]+")end
 return_getLangOfProp(qid,"P1476")
 end
 localfunctionlang_code(frame)
 returntable.concat(_lang_code(frame.args.qidormw.text.trim(frame.args[1]or"")),", ")
 end

 -- export for debug
 localfunctiongetPropOfProp(frame)
 return_getPropOfProp(frame.args)
 end

 -- wraps a string in nowiki unless disable flag is set
 localfunctionwrap_nowiki(str,disable)
 ifdisablethenreturnstror''end
 returnmw.text.nowiki(stror'')
 end

 -- sort sequence table whose values are key-value pairs by key
 localfunctioncomp_key(a,b)
 localparam_a,enum_a=a[1]:match('(%D+)(%d+)$');-- get param name and enumerator from <a>
 localparam_b,enum_b=b[1]:match('(%D+)(%d+)$');-- get param name and enumerator from <b>

 ifenum_aandenum_bthen-- if both parameters have neumerators
 ifparam_a==param_bthen-- are parameter names the same?
 returntonumber(enum_a)<tonumber(enum_b);-- yes: compare enumerators
 end
 end

 returna[1]<b[1];-- alpha sort if here
 end

 -- sort sequence table whose values are key-value pairs by value
 localfunctioncomp_val(a,b)
 returna[2]<b[2]
 end

 --[[-------------------------< C I T E _ Q >------------------------------------------------------------------
 Takes standard CS1|2 template parameters and passes all to {{citation}}. If neither of |author= and |author1=
 are set, calls get_authors() to try to get an author name-list from Wikidata. The result is passed to
 {{citation}} for rendering.
 --]]
 localfunction_cite_q(citeq_args)
 localframe=mw.getCurrentFrame()

 -- parameters that don't get passed to Citation
 localexpand=citeq_args.expand-- when set to anything, causes {{cite q}} to render <code><nowiki>{{citation|...}}</nowiki></code>
 localqid=citeq_args.qidorciteq_args[1]
 localwdl=citeq_args.wdl
 localtemplate=citeq_args.template
 citeq_args.expand=nil
 citeq_args[1]=nil
 citeq_args.qid=nil
 citeq_args.wdl=nil
 citeq_args.template=nil

 -- if title supplied, flag to not read html title
 localtitleforced=(citeq_args.title~=nil)

 localoth={}

 -- put the language codes into a sequential table langcodes[]
 locallangcodes={}
 ifciteq_args.languagethen
 -- check these are a supported language codes
 forlcinmw.text.gsplit(citeq_args.language,"[, ]+",false)do
 langcodes[#langcodes+1]=mw.language.isSupportedLanguage(citeq_args.language)andciteq_args.language
 end
 end
 ifnotlangcodes[1]then
 -- try to find language of work
 langcodes=_lang_code(qid)
 end
 ifnotlangcodes[1]then
 -- try fallback to journal's language
 localjournal_qid=followQid({qid=qid,props="P1433"})
 langcodes=journal_qidand_lang_code(journal_qid)
 end
 citeq_args.language=citeq_args.languageortable.concat(langcodes,", ")

 -- loop through list of simple properties and get their values in citeq_args
 forname,datainpairs(cfg.simple_properties_t)do
 citeq_args[name]=getValue({data.id,fwd="ALL",osd="no",noicon="true",qid=qid,maxvals=data.maxvals,linked=data.linked,rank=data.rankor"best",citeq_args[name]})
 ifdata.populate_from_journalthen
 localpublishedin=getValue({"P1433",ps=1,qid=qid,maxvals=0,citeq_args[name],qual=data.id,qualsonly='yes'})
 citeq_args[name]=publishedinor_getPropOfProp({qid=qid,prop1="P1433",prop2=data.id,maxvals=data.maxvals,ps=1})
 end
 ifciteq_args[name]andciteq_args[name]:find(cfg.i18n_t.trackingcat["missing-wikidata"],1,true)then
 -- try fallback to work's native language
 citeq_args[name]=getValue({data.id,ps=1,qid=qid,maxvals=data.maxvals,linked="no",lang=langcodes[1]})
 ifciteq_args[name]:find('^Q%d+$')then-- qid was returned
 -- try fallback to qid's native language
 localqid_languages=_lang_code(citeq_args[name])
 citeq_args[name]=getValue({data.id,ps=1,qid=qid,maxvals=data.maxvals,linked="no",lang=qid_languages[1]})
 ifciteq_args[name]:find('^Q%d+$')then-- qid was returned again
 citeq_args[name]=nil
 else
 -- record the language found if no lang specified
 citeq_args.language=citeq_args.languageorqid_languages[1]
 end
 end
 end
 ifdata.othersthen
 oth[#oth+1]=citeq_args[name]and(name:gsub("^%l",string.upper)..": "..citeq_args[name])
 citeq_args[name]=nil
 end
 end

 citeq_args.others=citeq_args.othersortable.concat(oth,". ")
 ifciteq_args.others==""then
 citeq_args.others=nil
 end

 citeq_args.journal=citeq_args.journalandciteq_args.journal:gsub("^''",""):gsub("''$",""):gsub("|''","|"):gsub("'']]","]]")

 citeq_args.ol=(getValue({"P648",ps=1,qid=qid,maxvals=1,citeq_args.ol})or''):gsub("^OL(.+)$","%1")
 ifciteq_args.ol==""then
 citeq_args.ol=nil
 end
 -- TBD. Take care of |ol-access=?

 citeq_args.biorxiv=citeq_args.biorxivand("10.1101/"..citeq_args.biorxiv)

 citeq_args.isbn=getValue({"P957",ps=1,qid=qid,maxvals=1,rank="best",citeq_args.isbn})-- try ISBN 10 (only one value accepted)

 -- if url then see if there's an archive: citeq_args.url
 localurl
 ifnotciteq_args.urlthen
 fori,prinipairs({"P953","P856","P2699"})do
 url=getValue({pr,ps=1,qid=qid,maxvals=1,qual="P1065"})
 ifurlthen
 citeq_args.url=mw.text.split(url," (",true)[1]
 localarcurl=mw.ustring.match(url," %((.*)%)")-- when there is an archive url, <url> holds: url<space>(archive url); here extract the archive url if present
 ifarcurlthen
 localarcy,arcm,arcd=arcurl:match("(20%d%d)%p?(%d%d)%p?(%d%d)")
 ifarcyandarcmandarcdthen
 citeq_args["archive-url"]=arcurl
 citeq_args["archive-date"]=tonumber(arcd).." "..cfg.i18n_t.months[tonumber(arcm)].." "..arcy
 end
 end
 break
 end
 end
 end

 ifciteq_args.publisher=="Unknown"then-- look for "stated as" (P1932)
 localstated_as=getValue({"P123",ps=1,qid=qid,maxvals=1,qual="P1932",qo="y"})
 ifstated_asthenciteq_args.publisher=stated_asend
 end

 ifnottitleforcedthen
 -- Handle subtitle.
 ifciteq_args.titlethen
 localsubtitle=mw.wikibase.getBestStatements(qid,'P1680');
 if0~=#subtitlethen
 subtitle=subtitle[1].mainsnak.datavalue.value.text;
 citeq_args.title=citeq_args.title..": "..subtitle
 end
 end

 localhtmltitle=getValue({"P1476",qual="P6833",ps=1,qid=qid,maxvals=1,qo="y"})
 ifhtmltitlethen
 citeq_args.title=htmltitle:gsub("</?i>","''")
 else
 localtitle_display=citeq_args.title
 ormw.wikibase.getLabel(qid)
 or(langcodes[1]andmw.wikibase.getLabelByLang(qid,langcodes[1]))
 or(cfg.i18n_t.errors["no-label-or-title"]..qid)
 ifciteq_args.urlthen
 citeq_args.title=wrap_nowiki(title_display)
 else
 localslink=mw.wikibase.getSitelink(qid)
 localslink_flag=false
 localwrap_title=''
 localwslink=false
 ifnotslinkthen
 -- See if we have wikisource
 ifnotciteq_args.urlthen
 localwikisource_sitelink=mw.wikibase.getSitelink(qid,cfg.i18n_t.wikisource)ornil
 ifwikisource_sitelinkthen
 slink=':s:'..wikisource_sitelink
 wslink=true
 end
 end
 end
 ifciteq_args.titlethen
 ifslinkthen
 wrap_title=wrap_nowiki(citeq_args.title)
 slink_flag=true
 else
 citeq_args.title=wrap_nowiki(citeq_args.title)
 end
 else
 ifslinkandnotwslinkthen
 ifslink:lower()==title_display:lower()then
 citeq_args.title='[['..slink..']]'
 else
 wrap_title=wrap_nowiki(slink:gsub("%s%(.+%)$",""):gsub(",.+$",""))
 slink_flag=true
 end
 elseifwslinkthen
 wrap_title=wrap_nowiki(title_display)
 slink_flag=true
 else
 citeq_args.title=wrap_nowiki(title_display)
 end
 end
 ifslink_flagthen
 ifslink==wrap_titleandnotwslinkthen-- direct link
 citeq_args.title='[['..slink..']]'
 else-- piped link
 citeq_args.title='[['..slink..'|'..wrap_title..']]'
 end
 end
 end
 end
 end

 -- TBD: incorporate |at, |sheets= and |sheet= here as well
 -- Sort out what should happen if several of them are given at the same time
 ifciteq_args.pageorciteq_args.pthen-- let single take precedence over multiple
 citeq_args.pages=nil
 citeq_args.pp=nil
 end
 ifciteq_args.pagesthen
 local_,count=string.gsub(citeq_args.pages,"[,;%s]%d+","")
 ifcount==1then
 citeq_args.page=citeq_args.pages
 citeq_args.pages=nil
 end
 end

 ifis_set(qid)then
 ifnotis_set(citeq_args.author)andnotis_set(citeq_args.author1)
 andnotis_set(citeq_args.subject)andnotis_set(citeq_args.subject1)
 andnotis_set(citeq_args.host)andnotis_set(citeq_args.host1)
 andnotis_set(citeq_args.last)andnotis_set(citeq_args.last1)
 andnotis_set(citeq_args.surname)andnotis_set(citeq_args.surname1)
 andnotis_set(citeq_args['author-last'])andnotis_set(citeq_args['author-last1'])andnotis_set(citeq_args['author1-last'])
 andnotis_set(citeq_args['author-surname'])andnotis_set(citeq_args['author-surname1'])andnotis_set(citeq_args['author1-surname1'])then-- if neither are set, try to get authors from Wikidata
 get_name_list('author',citeq_args,qid,wdl)-- modify citeq_args table with authors from Wikidata
 end

 ifnotis_set(citeq_args.editor)andnotis_set(citeq_args.editor1)
 andnotis_set(citeq_args['editor-last'])andnotis_set(citeq_args['editor-last1'])andnotis_set(citeq_args['editor1-last'])
 andnotis_set(citeq_args['editor-surname'])andnotis_set(citeq_args['editor-surname1'])andnotis_set(citeq_args['editor1-surname'])then-- if neither are set, try to get editors from Wikidata
 get_name_list('editor',citeq_args,qid,wdl)-- modify citeq_args table with editors from Wikidata
 end

 ifnotis_set(citeq_args.translator)andnotis_set(citeq_args.translator1)
 andnotis_set(citeq_args['translator-last'])andnotis_set(citeq_args['translator-last1'])andnotis_set(citeq_args['translator1-last'])
 andnotis_set(citeq_args['translator-surname'])andnotis_set(citeq_args['translator-surname1'])andnotis_set(citeq_args['translator1-surname'])then-- if neither are set, try to get translators from Wikidata
 get_name_list('translator',citeq_args,qid,wdl)-- modify citeq_args table with translators from Wikidata
 end
 end

 fork,vinpairs(citeq_args)do
 ifin_array(v,{'(())','unset','ignore'})or'string'~=type(k)then-- empty accept-as-is-written (()) markup to indicate an empty/unused parameter value, other ((...)) markups are deliberately passed down to {{citation}}
 citeq_args[k]=nil
 elseifin_array(v,{'((unset))','((ignore))'})then-- strip off markup for free-text values clashing with local keywords
 citeq_args[k]='unset'
 end
 end

 localauthor_count=0
 fork,vinpairs(citeq_args)do
 ifk:find("^author%d+$")then
 author_count=author_count+1
 end
 end
 ifauthor_count>8then-- convention in astronomy journals, optional mode for this?
 if'all'==citeq_args['display-authors']then
 citeq_args['display-authors']=nil;-- unset because no longer needed
 else
 citeq_args['display-authors']=citeq_args['display-authors']or3-- limit to three displayed names
 end
 end

 localeditor_count=0
 fork,vinpairs(citeq_args)do
 ifk:find("^editor%d+$")then
 editor_count=editor_count+1
 end
 end
 ifeditor_count>8then-- convention in astronomy journals, optional mode for this?
 if'all'==citeq_args['display-editors']then
 citeq_args['display-editors']=nil;-- unset because no longer needed
 else
 citeq_args['display-editors']=citeq_args['display-editors']or3-- limit to three displayed names
 end
 end

 -- change edition to ordinal if it's set and numeric
 citeq_args.edition=citeq_args.editionandmakeOrdinal(citeq_args.edition)

 -- code to make a guess what template to use from the supplied parameters
 -- (first draft for proof-of-concept)
 ifciteq_args.isbnthen
 template=templateor"book"
 citeq_args.asin=nil-- suppress ASIN if ISBN exists
 elseifciteq_args.journalthen
 template=templateor"journal"
 elseifciteq_args.websitethen
 template=templateor"web"
 end

 -- |id= could hold more than one identifier pulled from Wikidata not supported by {{citation}}, right now only add our qid to the list
 locallist_sep='. '
 ifciteq_args.mode~='cs1'then
 list_sep=', '
 end
 localid=cfg.i18n_t.wdq..'&nbsp;[[:d:'..qid..'|'..qid..']]'
 localold_id=citeq_args.id
 ifwdlthen-- show WD logo
 id=id..'[[File:Wikidata-logo.svg|16px|alt=|link=]]'-- possibly replace by WD edit icon?
 end
 ifis_set(old_id)then
 citeq_args.id=old_id..list_sep..id-- append to user-specified contents
 else
 citeq_args.id=id
 end

 -- clean up any blank parameters
 fork,vinpairs(citeq_args)do
 ifv==""thenciteq_args[k]=nilend
 end

 -- if |expand=<anything>, write a nowiki'd version to see what the {{citation}} template call looks like
 ifexpandthen

 localexpand_args={"{{"..(templateand("Cite "..template)or"Citation")}-- init with citation template
 ifexpand=="self"then
 citeq_args.id=old_id-- restore original |id= parameter
 expand_args={cfg.i18n_t.cite_q..qid}-- expand to itself
 end
 -- make a sortable table and sort it by param name
 localsorttable={}
 forparam,valinpairs(citeq_args)do
 table.insert(sorttable,{param,val})
 end
 table.sort(sorttable,comp_key)
 -- add contents to expand_args
 foridx,valinipairs(sorttable)do
 table.insert(expand_args,val[1]..'='..val[2])
 end
 -- make the nowiki'd string and done
 returnframe:preprocess(table.concat({'<syntaxhighlight lang="wikitext" inline="1">',table.concat(expand_args,' |')..'}}','</syntaxhighlight>'}));
 end

 localerratumid=getPropertyIDs({"P2507",qid=qid,fwd="ALL",osd="no",rank="best",maxvals=1})
 iferratumidthen
 erratumid=" [[d:"..erratumid.."|"..cfg.i18n_t.erratum.."]]"..cfg.i18n_t.trackingcat.erratum
 else
 erratumid=""
 end

 localopt_cat=''
 ifgetValue({"P5824",ps=1,qid=qid})then
 opt_cat=cfg.i18n_t.trackingcat.retracted
 end
 ifgetValue({"P1366",ps=1,qid=qid})then
 opt_cat=opt_cat..cfg.i18n_t.trackingcat.replaced
 end

 -- render the template
 locallc_template=templateandtemplate:lower()or"citation"
 localoutput
 ifcite_cfg.known_templates_t[lc_template]then
 localconfig_t={['CitationClass']=cite_cfg.citation_classes_t[lc_template]orlc_template};-- set CitationClass value
 output=require(cs1_module)._citation(nil,citeq_args,config_t)-- go render the citation
 else
 output=frame:expandTemplate{-- render the template
 title="Cite "..template,args=citeq_args
 }..cfg.i18n_t.trackingcat["unknown-template"]
 end
 returnoutput..erratumid..opt_cat
 end

 localfunctioncite_q(frame)
 localargs={}
 fork,vinpairs(frame:getParent().args)do
 ifv~=""thenargs[k]=vend
 end
 fork,vinpairs(frame.args)do
 ifv~=""thenargs[k]=vend
 end
 args.qid=args.qidorargs[1]or""
 ifargs.qid==""thenreturnnilend
 args[1]=nil

 localcitesep=(args.citesepor"")
 ifcitesep==""thencitesep=", "end
 citesep=citesep:gsub('"','')-- strip double quotes after setting default to allow |citesep="" as a blank separator
 args.citesep=nil

 localtag=args.tagor""
 iftag==""thentag=nilend
 args.tag=nil

 locallist=args.listor""
 iflist==""thenlist=nilend
 args.list=nil

 args.language=args.languageorargs.lang
 args.lang=nil

 localcites={}
 forqinargs.qid:gmatch("Q%d+")do
 -- make a new copy of the arguments
 localnewargs={}
 fork,vinpairs(args)do
 ifk~="qid"then
 newargs[k]=v
 end
 end
 newargs.qid=q
 iftag=="ref"then
 cites[#cites+1]=frame:callParserFunction{name="#tag:ref",args={_cite_q(newargs),name=q}}
 -- expand like this: args = { _cite_q(newargs), name = 'foo', group = 'bar' }
 else
 cites[#cites+1]=_cite_q(newargs)
 end
 end

 iflistthen
 returnframe:expandTemplate{title=list,args=cites}
 else
 returntable.concat(cites,citesep)
 end
 end

 --[[--------------------------< E X P O R T E D F U N C T I O N S >------------------------------------------
 ]]

 return{
 makeOrdinal=makeOrdinal,
 _getLangOfProp=_getLangOfProp,
 getLangOfProp=getLangOfProp,
 lang_code=lang_code,
 getPropOfProp=getPropOfProp,
 _cite_q=_cite_q,
 cite_q=cite_q
 }

AltStyle によって変換されたページ (->オリジナル) /