Jump to content

Module:Template wrapper

Permanently protected module
From Wikipedia, the free encyclopedia

require('strict');localerror_msg='<span style=\"font-size:100%\" class=\"error\"><code style=\"color:inherit; border:inherit; padding:inherit;\">&#124;_template=</code> missing or empty</span>';--[[--------------------------< I S _ I N _ T A B L E >--------------------------------------------------------scan through tbl looking for value; return true if found, false else]]localfunctionis_in_table(tbl,value)fork,vinpairs(tbl)doifv==valuethenreturntrueendendreturnfalse;end--[[--------------------------< A D D _ P A R A M E T E R >----------------------------------------------------adds parameter name and its value to args table according to the state of boolean list argument; kv pair fortemplate execution; k=v string for template listing.]]localfunctionadd_parameter(k,v,args,list)iflistthentable.insert(args,table.concat({k,'=',v}));-- write parameter names and values to args table as stringelseargs[k]=v;-- copy parameters to args tableendend--[[--------------------------< A L I A S _ M A P _ G E T >----------------------------------------------------returns a table of local template (parent frame) parameter names and the target template names that match wherein [key]=<value> pairs where: [key] is local template parameter name (an alias) <value> is target template parameter name (the canonical parameter name used in the working template)The parameter |_alias-map= has the form: |_alias-map=<list>where <list> is a comma-separated list of alias / canonical parameter name pairs in the form <from> : <to>where: <from> is the local template's parameter name (alias) <to> is the target template's parameter name (canonical) for enumerated parameters place an octothorp (#) where the enumerator digits are placed in the parameter names: <from#> : <to#>]]localfunctionalias_map_get(_alias_map)localT=mw.text.split(_alias_map,'%s*,%s*');-- convert the comma-separated list into a table of alias pairslocalmapped_aliases={};-- mapped aliases will go herelocall_name,t_name;-- parameter namesfor_,alias_pairinipairs(T)do-- loop through the table of alias pairsl_name,t_name=alias_pair:match('(.-)%s*:%s*(.+)');-- from each pair, get local and target parameter namesifl_nameandt_namethen-- if both are setiftonumber(l_name)thenl_name=tonumber(l_name);-- convert number-as-text to a numberendmapped_aliases[l_name]=t_name;-- add them to the map tableendendreturnmapped_aliases;end--[[--------------------------< F R A M E _ A R G S _ G E T >--------------------------------------------------Fetch the wrapper template's 'default' and control parameters; adds default parameters to argsreturns content of |_template= parameter (name of the working template); nil else]]localfunctionframe_args_get(frame_args,args,list)localtemplate;fork,vinpairs(frame_args)do-- here we get the wrapper template's 'default' parametersif'string'==type(k)and(vand(''~=v))then-- do not pass along positional or empty parametersif'_template'==kthentemplate=v;-- save the name of template that we are wrappingelseif'_exclude'~=kand'_reuse'~=kand'_include-positional'~=kand'_alias-map'~=kthen-- these already handled so ignore here; add_parameter(k,v,args,list);-- add all other parameters to args in the style dictated by listendendendreturntemplate;-- return contents of |_template= parameterend--[=[--------------------------< P F R A M E _ A R G S _ G E T >------------------------------------------------Fetches the wrapper template's 'live' parameters; adds live parameters that aren't members of the exclude table toargs table; positional parameters may not be excludedno return value]=]localfunctionpframe_args_get(pframe_args,args,exclude,_include_positional,list)fork,vinpairs(pframe_args)doif'string'==type(k)andnotis_in_table(exclude,k)then-- do not pass along excluded parametersifvand(''~=v)then-- pass along only those parameters that have assigned valuesif'unset'==v:lower()then-- special keyword to unset 'default' parameters set in the wrapper templatev='';-- unset the value in the args tableendadd_parameter(k,v,args,list)-- add all other parameters to args in the style dictated by list; alias map only supported for local-template parametersendendendif_include_positionalthenfori,vinipairs(pframe_args)do-- pass along positional parametersif'unset'==v:lower()then-- special keyword to unset 'default' parameters set in the wrapper templatev='';-- unset the value in the args tableendadd_parameter(i,v,args,list);endendend--[[--------------------------< _ M A I N >--------------------------------------------------------------------Collect the various default and live parameters into args styled according to boolean list.returns name of the working or listed template or nil for an error message]]localfunction_main(frame,args,list)localtemplate;localexclude={};-- table of parameter names for parameters that are not passed to the working templatelocalreuse_list={};-- table of pframe parameter names whose values are modified before they are passed to the working template as the same namelocalalias_map={};-- table that maps parameter aliases to working template canonical parameter nameslocal_include_positional;ifframe.args._excludeand(''~=frame.args._exclude)then-- if there is |_exclude= and it's not emptyexclude=mw.text.split(frame.args._exclude,"%s*,%s*");-- make a table from its contentsend-- TODO: |_reuse= needs a better name (|_reuse=)ifframe.args._reuseand(''~=frame.args._reuse)then-- if there is |_reuse= and it's not emptyreuse_list=mw.text.split(frame.args._reuse,"%s*,%s*");-- make a table from its contentsendifframe.args['_alias-map']and(''~=frame.args['_alias-map'])then-- if there is |_alias-map= and it's not emptyalias_map=alias_map_get(frame.args['_alias-map']);-- make a table from its contentsendtemplate=frame_args_get(frame.args,args,list);-- get parameters provided in the {{#invoke:template wrapper|...|...}}ifnil==templateor''==templatethen-- this is the one parameter that is required by this modulereturnnil;-- not present, tell calling function to emit an error messageend_include_positional='yes'==frame.args['_include-positional'];-- when true pass all positional parameters along with non-excluded named parameters to ...-- ... the working template; positional parameters are not excludablelocal_pframe_args=frame:getParent().args;-- here we get the wrapper template's 'live' parameters from pframe.argslocalpframe_args={};-- a local table that we can modifyfork,vinpairs(_pframe_args)do-- make a copy that we can modifypframe_args[k]=v;end-- here we look for pframe parameters that are aliases of canonical parameter names; when found-- we replace the alias with the canonical. We do this here because the reuse_list works on-- canonical parameter names so first we convert alias parameter names to canonical names and then-- we remove those canonical names from the pframe table that are reused (provided to the working-- template through the frame args table)fork,vinpairs(alias_map)do-- k is alias name, v is canonical nameifpframe_args[k]then-- if pframe_args has parameter with alias namepframe_args[v]=_pframe_args[k];-- create new canonical name with alias' valuepframe_args[k]=nil;-- unset the aliasendendfork,vinpairs(pframe_args)do-- do enumerated parameter alias -> canonical translationif'string'==type(k)then-- only named parameters can be enumeratedifalias_map[k..'#']then-- non-enumerated alias matches enumerated parameter pattern? enumerator at end onlypframe_args[alias_map[k..'#']:gsub('#','')]=v;-- remove '#' and copy parameter to pframe_args tablepframe_args[k]=nil;-- unset the aliaselseifk:match('%d+')then-- if this parameter name contains digitslocaltemp=k:gsub('%d+','#');-- make a copy; digits replaced with single '#'localenum=k:match('%d+');-- get the enumeratorifalias_map[temp]then-- if this parameter is a recognized enumerated aliaspframe_args[alias_map[temp]:gsub('#',enum)]=v;-- use canonical name and replace '#' with enumerator and add to pframe_argspframe_args[k]=nil;-- unset the aliasendendendend-- pframe parameters that are _reused are 'reused' have the form something like this:-- |chapter=[[wikisource:{{{chapter}}}|{{{chapter}}}]]-- where a parameter in the wrapping template is modified and then passed to the working template-- using the same parameter name (in this example |chapter=)-- remove parameters that will be reusedfork,vinipairs(reuse_list)do-- k is numerical index, v is canonical parameter name to ignoreifpframe_args[v]then-- if pframe_args has parameter that should be ignoredpframe_args[v]=nil;-- unset the ignored parameterendendpframe_args_get(pframe_args,args,exclude,_include_positional,list);-- add parameters and values to args that are not listed in the exclude tablereturntemplate;-- args now has all default and live parameters, return working template nameend--[[--------------------------< W R A P >----------------------------------------------------------------------Template entry point. Call this function to 'execute' the working template]]localfunctionwrap(frame)localargs={};-- table of default and live parameters and their values to be passed to the wrapped templatelocaltemplate;-- the name of the working templatetemplate=_main(frame,args,false);-- get default and live parameters and the name of the working templateifnottemplatethen-- template name is requiredreturnerror_msg;-- emit error message and abandon if template name not presentendreturnframe:expandTemplate{title=template,args=args};-- render the working templateend--[[--------------------------< L I S T >----------------------------------------------------------------------Template entry point. Call this function to 'display' the source for the working template. This function addedas a result of a TfD here: Wikipedia:Templates_for_discussion/Log/2018_April_28#Module:PassArgumentsThis function replaces a similarly named function which was used in {{cite compare}} and {{cite compare2}}Values in the args table are numerically indexed strings in the form 'name=value']]localfunctionlist(frame,do_link)localargs={};-- table of default and live parameters and their values to be passed to the listed templatelocaltemplate;-- the name of the listed templatetemplate=_main(frame,args,true);-- get default and live parameters and the name of the listed templateifnottemplatethen-- template name is requiredreturnerror_msg;-- emit error message and abandon if template name not presentendifdo_linkthentemplate=('[[%s|%s]]'):format(frame:expandTemplate{title='Transclude',args={template}},template)endtable.sort(args)fori=1,#argsdolocalstripped=args[i]:match('^'..i..'=([^=]*)$')ifstrippedthenargs[i]=strippedelsebreakendendreturnframe:preprocess(table.concat({'<code style="color:inherit; background:inherit; border:none;">&#123;&#123;',template,('<wbr><nowiki>|%s</nowiki>'):rep(#args):format(unpack(args)),'&#125;&#125;</code>'}));-- render the templateendlocalfunctionlink(frame)returnlist(frame,true)end--[[--------------------------< E X P O R T E D F U N C T I O N S >------------------------------------------]]return{link=link,list=list,wrap=wrap,};
close