Module:Template parameter value
To avoid major disruption and server load, any changes should be tested in the module's /sandbox or /testcases subpages, or in your own module sandbox. The tested changes can be added to this page in a single edit. Consider discussing changes on the talk page before implementing them.
Implements {{Template parameter value }} and {{HasTemplate }}, and can be used from other modules.
Module functions
getParameter
getParameter takes 4 arguments: The page name (string), the template/s (string or table of strings), the parameter (string), and an optional options table. It will return either true and the contents of the requested parameter or false and a reason for failure.
The following options are available:
- template_index: Which occurrence of the template to look for the parameter in. Set to -1 for last occurrence. (default: 1)
- parameter_index: Which occurrence of the parameter to look for (default: 1; only applies when
ignore_subtemplatesis false) - ignore_subtemplates: If parameters should only be searched for in the top-level template, ignoring the parameters in subtemplates (default: false)
- only_subtemplates: If parameters should only be searched for in subtemplates of the top-level template (default: false)
- ignore_blank: Whether or not blank values should count towards
parameter_index(default: false) - treat_as_regex: Whether or not the template string(s) should be treated as a lua regex (default: false)
getTemplate
getTemplate takes 3 arguments: The page name (string), the template/s (string or table of strings), and an optional options table. It will return either true and the text of the requested template or false and a reason for failure.
getTemplate supports the options template_index and treat_as_regex from getParameter.
Helper functions
The module exposes some of the helper functions used (matchAllTemplates, getParameters, and getAllParameters) for convenience. Each function has some comments above it in the code explaining its rough purpose.
Template functions
main implements {{Template parameter value }} and acts as a template wrapper for getParameter.
hasTemplate implements {{HasTemplate }} and somewhat acts as a wrapper for getTemplate (it only provides if the template was found, not the template text itself).
Testcases
Testcases are available at Module talk:Template parameter value/testcases
Editors can experiment in this module's sandbox (edit | diff) and testcases (edit | run) pages.
Subpages of this module.
localp={} localPrepareText=require("Module:Wikitext Parsing").PrepareText localfunctiongetTitle(title) localsuccess,titleObj=pcall(mw.title.new,title) ifsuccessthenreturntitleObj elsereturnnilend end -- Finds all templates in the given string, including nested templates -- Templates are returned in position order, e.g. "<a<b>>" returns {"<a<b>>", "<b>"} localfunctionmatchAllTemplates(str) localmatchLayers={{}} localunfinished={} localposition=1 locallastClosedLayer=1 whiletruedo localnextOpen=string.find(str,"{{",position,true) localnextClose=string.find(str,"}}",position,true) ifnextOpenand(notnextCloseornextOpen<nextClose)then unfinished[#unfinished+1]=nextOpen ifnotmatchLayers[#unfinished]then matchLayers[#unfinished]={} end position=nextOpen+2 elseifnextClosethen locallenLayers=#unfinished iflenLayers>0then localmatches=matchLayers[lenLayers] matches[#matches+1]=string.sub(str,unfinished[lenLayers],nextClose+1) unfinished[lenLayers]=nil -- Ensure templates are ordered by their starting position, not their ending position iflenLayers<lastClosedLayerthen localchildren=matchLayers[lenLayers+1] fori=1,#childrendo matches[#matches+1]=children[i] children[i]=nil end end lastClosedLayer=lenLayers end position=nextClose+2 else break end end -- Check for any uncaught matches caused by bad input strings fori=#matchLayers,2,-1do localcur,parent=matchLayers[i],matchLayers[i-1] fori=1,#curdo parent[#parent+1]=cur[i] end end returnmatchLayers[1] end --Forked version of getParameters from [[Module:Transcluder]] with extra features removed localfunctionescapeString(str) returnstring.gsub(str,'[%^%$%(%)%.%[%]%*%+%-%?%%]','%%%0') end localfunctiongetParameters(template) localparameters,parameterOrder={},{} localparams=string.match(template,'{{[^|}]-|(.*)}}') ifparamsthen localcount=0 -- Temporarily replace pipes in subtemplates and wikilinks to avoid chaos forsubtemplateinstring.gmatch(params,'{%b{}}')do params=string.gsub(params,escapeString(subtemplate),string.gsub(subtemplate,".",{["%"]="%%",["|"]="@@:@@",["="]="@@_@@"})) end forwikilinkinstring.gmatch(params,'%[%b[]%]')do params=string.gsub(params,escapeString(wikilink),string.gsub(wikilink,".",{["%"]="%%",["|"]="@@:@@",["="]="@@_@@"})) end forparameterinmw.text.gsplit(params,'|')do localparts=mw.text.split(parameter,'=') localkey=mw.text.trim(parts[1]) localvalue if#parts==1then value=key count=count+1 key=tostring(count) else value=mw.text.trim(table.concat(parts,'=',2)) end value=string.gsub(string.gsub(value,'@@:@@','|'),'@@_@@','=') key=string.gsub(string.gsub(key,'@@:@@','|'),'@@_@@','=') table.insert(parameterOrder,key) parameters[key]=value end end returnparameters,parameterOrder end -- Returns a table containing parameters and a table with the order in which each of their values were found. -- Since this considers all subtemplates, a single parameter is expected to have multiple values. -- E.g. {{ABC|X={{DEF|X=Value|Y=Other value}}{{ABC|X=Yes}}|Y=P}} -- Would return {X={"{{DEF|X=Value|Y=Other value}}", "Value", "Yes"}, Y={"Other value", "P"}} localfunctiongetAllParameters(template,ignore_blank,only_subtemplates) localparameterTree=setmetatable({},{ __index=function(self,key) rawset(self,key,{}) returnrawget(self,key) end }) localparams,paramOrder=getParameters(template) for_,keyinipairs(paramOrder)do localvalue=params[key] ifnotignore_blankorvalue~=""then ifnotonly_subtemplatesthen table.insert(parameterTree[key],value)--Insert the initial value into the tree end forsubtemplateinstring.gmatch(value,"{%b{}}")do--And now check for subvalues localsubparams=getAllParameters(subtemplate,ignore_blank) forsubkey,subsetinnext,subparamsdo for_,subvalueinipairs(subset)do table.insert(parameterTree[subkey],subvalue)--And add any we find to our tree end end end end end returnparameterTree end --Module entry point. Returns a success boolean and either the target template or why it failed functionp.getTemplate(page,templates,options) ifnottemplatesthen--Required parameters returnfalse,"Missing required parameter 'templates'" end options=optionsor{} localtemplate_index=tonumber(options.template_index)or1 localtreat_as_regex=options.treat_as_regexorfalse iftype(templates)=="string"then -- TODO: Find a good way to allow specifying multiple templates via template invocation -- (Modules can just provide a table so no concerns there) -- Comma splitting is a bad idea (lots of templates have a comma in their name) templates={templates} end localtitle=getTitle(page) iftitle==nilthen returnfalse,"Requested title doesn't exist" end localcontent=PrepareText(title:getContent()or"") localsanitisedTemplates={} fori,templateinpairs(templates)do ifnottreat_as_regexthen template=escapeString(template) end localfirstLetter=string.sub(template,1,1) localfirstUpper,firstLower=firstLetter:upper(),firstLetter:lower() iffirstUpper~=firstLowerthen template="["..firstUpper..firstLower.."]"..string.sub(template,2) end sanitisedTemplates[i]=template end localfoundTemplates=0 localfoundTemplate for_,templateinnext,matchAllTemplates(content)do for_,wantedTemplateinpairs(sanitisedTemplates)do ifstring.match(template,"^{{%s*"..wantedTemplate.."%s*[|}]")then foundTemplate=template foundTemplates=foundTemplates+1 iffoundTemplates==template_indexthen--Found our wanted template returntrue,foundTemplate end end end end iffoundTemplates>0andtemplate_index==-1then returntrue,foundTemplate end returnfalse,"No valid template found" end --Module entry point. Returns a success boolean and either the target parameter's value or why it failed functionp.getParameter(page,templates,parameter,options) ifnot(templatesandparameter)then--Required parameters returnfalse,"Missing required parameters 'templates' and 'parameter'" end parameter=tostring(parameter)--Force consistency options=optionsor{} localsuccess,text=p.getTemplate(page,templates,options) ifnotsuccessthen returnsuccess,text else localparameter_index=tonumber(options.parameter_index)or1 localignore_subtemplates=options.ignore_subtemplatesorfalse localonly_subtemplates=options.only_subtemplatesorfalse localignore_blank=options.ignore_blankorfalse localvalue ifignore_subtemplatesthen value=getParameters(text)[parameter]or"" else localparams=getAllParameters(text,ignore_blank,only_subtemplates) value=params[parameter][parameter_index]or"" end value=string.gsub(value,"</?%a*include%a*>","") value=mw.text.trim(value)--technically wrong in some cases but not a big issue returntrue,mw.text.decode(value)--decode due to PrepareText end end --Template entry point. Returns either "yes" or nothing depending on if the wanted template is found --Will return error text if no template is provided functionp.hasTemplate(frame) localargs=require('Module:Arguments').getArgs(frame) localyesno=require("Module:Yesno") localpage=args[1]orargs.page localtemplate=args[2]orargs.template localtemplate_index=tonumber(args[3]orargs.N)or1 ifnottemplateortemplate==""then return'<span class="error">No template provided for hasTemplate</span>' end localfollow=yesno(args.follow)orfalse iffollowthen page=require("Module:Redirect").luaMain(page) end localoptions={ template_index=template_index, treat_as_regex=yesno(args.treat_as_regex)orfalse, } localsuccess,_=p.getTemplate(page,template,options) returnsuccessand"yes"or"" end --Template entry point for getParameter. Returns an empty string upon failure functionp.main(frame) localargs=require('Module:Arguments').getArgs(frame,{ wrappers='Template:Template parameter value' }) localyesno=require("Module:Yesno") localoptions={ template_index=args[3]orargs.template_index, parameter_index=args[5]orargs.parameter_index, ignore_subtemplates=yesno(args.ignore_subtemplatesorargs.ist)orfalse, only_subtemplates=yesno(args.only_subtemplates)orfalse, ignore_blank=yesno(args.ignore_blank)orfalse, treat_as_regex=yesno(args.treat_as_regex)orfalse, } localpage=args[1]orargs.page localtemplate=args[2]orargs.template localparameter=args[4]orargs.parameter localsuccess,result=p.getParameter(page,template,parameter,options) ifnotsuccessthen return"" else ifargs.dontprocessthen returnresult else returnframe:preprocess(result) end end end --Backwards compatability p.getValue=p.getParameter --Potentially useful module entry points p.matchAllTemplates=matchAllTemplates p.getParameters=getParameters p.getAllParameters=getAllParameters returnp