Module:Template parameter value/sandbox
See also the companion subpage for test cases (run).
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
[edit ]getParameter
[edit ]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_subtemplates
is 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
[edit ]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
[edit ]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
[edit ]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
[edit ]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.
Add categories to the /doc subpage. Subpages of this module.
localp={} localPrepareText=require("Module:Wikitext Parsing/sandbox").PrepareText localfunctiongetTitle(title) localsuccess,titleObj=pcall(mw.title.new,title) ifsuccessthenreturntitleObj elsereturnnilend end --string.gmatch will check the largest block it can without re-scanning whats inside, but we need whats inside localfunctionmatchAllTemplates(str) localmatches={} fortemplateinstring.gmatch(str,"{%b{}}")do table.insert(matches,template) localinnerContent=string.sub(template,3,-3) for_,subtemplateinnext,matchAllTemplates(innerContent)do table.insert(matches,subtemplate) end end returnmatches 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"") localfoundTemplates=0 localfoundTemplate for_,templateinnext,matchAllTemplates(content)do for_,wantedTemplateinpairs(templates)do ifnottreat_as_regexthen wantedTemplate=escapeString(wantedTemplate) end localfirstLetter=string.sub(wantedTemplate,1,1) localfirstUpper,firstLower=firstLetter:upper(),firstLetter:lower() iffirstUpper~=firstLowerthen wantedTemplate="["..firstUpper..firstLower.."]"..string.sub(wantedTemplate,2) end 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