Jump to content
Wikipedia The Free Encyclopedia

Module:Template test case

From Wikipedia, the free encyclopedia
Module documentation[view] [edit] [history] [purge]

This module provides a framework for making templates which produce a template test case. While test cases can be made manually, using Lua-based templates such as the ones provided by this module has the advantage that the template arguments only need to be input once, thus reducing the effort involved in making test cases and reducing the possibility of errors in the input.

Usage

This module should not usually be called directly. Instead, you should use one of the following templates:

Parameter-based templates:

The only difference between these templates is their default arguments. For example, it is possible to display test cases side by side in Template:Testcase rows by specifying |_format=columns

Nowiki-based templates:

It is also possible to use a format of {{#invoke:template test case|main|parameters}}. This uses the same defaults as Template:Test case; please see that page for documentation of the parameters.

There is no direct interface to this module for other Lua modules. Lua modules should generally use Lua-based test case modules such as Module:UnitTests or Module:ScribuntoUnit. If it is really necessary to use this module, you can use frame:expandTemplate with one of the templates listed above.

Configuration

This module has a configuration module at Module:Template test case/config. You can edit it to add new wrapper templates, or to change the messages that the module outputs.

Tracking categories

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

 --[[
  A module for generating test case templates.

  This module incorporates code from the English Wikipedia's "Testcase table"
  module,[1] written by Frietjes [2] with contributions by Mr. Stradivarius [3]
  and Jackmcbarn,[4] and the English Wikipedia's "Testcase rows" module,[5]
  written by Mr. Stradivarius.

  The "Testcase table" and "Testcase rows" modules are released under the
  CC BY-SA 3.0 License [6] and the GFDL.[7]

  License: CC BY-SA 3.0 and the GFDL
  Author: Mr. Stradivarius

  [1] https://en.wikipedia.org/wiki/Module:Testcase_table
  [2] https://en.wikipedia.org/wiki/User:Frietjes
  [3] https://en.wikipedia.org/wiki/User:Mr._Stradivarius
  [4] https://en.wikipedia.org/wiki/User:Jackmcbarn
  [5] https://en.wikipedia.org/wiki/Module:Testcase_rows
  [6] https://en.wikipedia.org/wiki/Wikipedia:Text_of_Creative_Commons_Attribution-ShareAlike_3.0_Unported_License
  [7] https://en.wikipedia.org/wiki/Wikipedia:Text_of_the_GNU_Free_Documentation_License
 ]]

 -- Load required modules
 localyesno=require('Module:Yesno')

 -- Set constants
 localDATA_MODULE='Module:Template test case/data'

 -------------------------------------------------------------------------------
 -- Shared methods
 -------------------------------------------------------------------------------

 localfunctionmessage(self,key,...)
 -- This method is added to classes that need to deal with messages from the
 -- config module.
 localmsg=self.cfg.msg[key]
 ifselect(1,...)then
 returnmw.message.newRawMessage(msg,...):plain()
 else
 returnmsg
 end
 end

 -------------------------------------------------------------------------------
 -- Template class
 -------------------------------------------------------------------------------

 localTemplate={}

 Template.memoizedMethods={
 -- Names of methods to be memoized in each object. This table should only
 -- hold methods with no parameters.
 getFullPage=true,
 getName=true,
 makeHeader=true,
 getOutput=true
 }

 functionTemplate.new(invocationObj,options)
 localobj={}

 -- Set input
 fork,vinpairs(optionsor{})do
 ifnotTemplate[k]then
 obj[k]=v
 end
 end
 obj._invocation=invocationObj

 -- Validate input
 ifnotobj.templateandnotobj.titlethen
 error('no template or title specified',2)
 end

 -- Memoize expensive method calls
 localmemoFuncs={}
 returnsetmetatable(obj,{
 __index=function(t,key)
 ifTemplate.memoizedMethods[key]then
 localfunc=memoFuncs[key]
 ifnotfuncthen
 localval=Template[key](t)
 func=function()returnvalend
 memoFuncs[key]=func
 end
 returnfunc
 else
 returnTemplate[key]
 end
 end
 })
 end

 functionTemplate:getFullPage()
 ifnotself.templatethen
 returnself.title.prefixedText
 elseifself.template:sub(1,7)=='#invoke'then
 return'Module'..self.template:sub(8):gsub('|.*','')
 else
 localstrippedTemplate,hasColon=self.template:gsub('^:','',1)
 hasColon=hasColon>0
 localns=strippedTemplate:match('^(.-):')
 ns=nsandmw.site.namespaces[ns]
 ifnsthen
 returnstrippedTemplate
 elseifhasColonthen
 returnstrippedTemplate-- Main namespace
 else
 returnmw.site.namespaces[10].name..':'..strippedTemplate
 end
 end
 end

 functionTemplate:getName()
 ifself.templatethen
 returnself.template
 else
 returnrequire('Module:Template invocation').name(self.title)
 end
 end

 functionTemplate:makeLink(display)
 ifdisplaythen
 returnstring.format('[[:%s|%s]]',self:getFullPage(),display)
 else
 returnstring.format('[[:%s]]',self:getFullPage())
 end
 end

 functionTemplate:makeBraceLink(display)
 display=displayorself:getName()
 locallink=self:makeLink(display)
 returnmw.text.nowiki('{{')..link..mw.text.nowiki('}}')
 end

 functionTemplate:makeHeader()
 returnself.headingorself:makeBraceLink()
 end

 functionTemplate:getInvocation(format)
 localinvocation=self._invocation:getInvocation{
 template=self:getName(),
 requireMagicWord=self.requireMagicWord,
 }
 ifformat=='code'then
 invocation='<code>'..mw.text.nowiki(invocation)..'</code>'
 elseifformat=='kbd'then
 invocation='<kbd>'..mw.text.nowiki(invocation)..'</kbd>'
 elseifformat=='plain'then
 invocation=mw.text.nowiki(invocation)
 else
 -- Default is pre tags
 invocation=mw.text.encode(invocation,'&')
 invocation='<pre style="white-space: pre-wrap;">'..invocation..'</pre>'
 invocation=mw.getCurrentFrame():preprocess(invocation)
 end
 returninvocation
 end

 functionTemplate:getOutput()
 localprotect=require('Module:Protect')
 -- calling self._invocation:getOutput{...}
 returnprotect(self._invocation.getOutput)(self._invocation,{
 template=self:getName(),
 requireMagicWord=self.requireMagicWord,
 })
 end

 -------------------------------------------------------------------------------
 -- TestCase class
 -------------------------------------------------------------------------------

 localTestCase={}
 TestCase.__index=TestCase
 TestCase.message=message-- add the message method

 TestCase.renderMethods={
 -- Keys in this table are values of the "format" option, values are the
 -- method for rendering that format.
 columns='renderColumns',
 rows='renderRows',
 tablerows='renderRows',
 inline='renderInline',
 cells='renderCells',
 default='renderDefault'
 }

 functionTestCase.new(invocationObj,options,cfg)
 localobj=setmetatable({},TestCase)
 obj.cfg=cfg

 -- Separate general options from template options. Template options are
 -- numbered, whereas general options are not.
 localgeneralOptions,templateOptions={},{}
 fork,vinpairs(options)do
 localprefix,num
 iftype(k)=='string'then
 prefix,num=k:match('^(.-)([1-9][0-9]*)$')
 end
 ifprefixthen
 num=tonumber(num)
 templateOptions[num]=templateOptions[num]or{}
 templateOptions[num][prefix]=v
 else
 generalOptions[k]=v
 end
 end

 -- Set general options
 generalOptions.showcode=yesno(generalOptions.showcode)
 generalOptions.showheader=yesno(generalOptions.showheader)~=false
 generalOptions.showcaption=yesno(generalOptions.showcaption)~=false
 generalOptions.collapsible=yesno(generalOptions.collapsible)
 generalOptions.notcollapsed=yesno(generalOptions.notcollapsed)
 generalOptions.wantdiff=yesno(generalOptions.wantdiff)
 obj.options=generalOptions

 -- Preprocess template args
 fornum,tinpairs(templateOptions)do
 ift.showtemplate~=nilthen
 t.showtemplate=yesno(t.showtemplate)
 end
 end

 -- Set up first two template options tables, so that if only the
 -- "template3" is specified it isn't made the first template when the
 -- the table options array is compressed.
 templateOptions[1]=templateOptions[1]or{}
 templateOptions[2]=templateOptions[2]or{}

 -- Allow the "template" option to override the "template1" option for
 -- backwards compatibility with [[Module:Testcase table]].
 ifgeneralOptions.templatethen
 templateOptions[1].template=generalOptions.template
 end

 -- Add default template options
 iftemplateOptions[1].templateandnottemplateOptions[2].templatethen
 templateOptions[2].template=templateOptions[1].template..
 '/'..obj.cfg.sandboxSubpage
 end
 ifnottemplateOptions[1].templatethen
 templateOptions[1].title=mw.title.getCurrentTitle().basePageTitle
 end
 ifnottemplateOptions[2].templatethen
 templateOptions[2].title=templateOptions[1].title:subPageTitle(
 obj.cfg.sandboxSubpage
 )
 end

 -- Remove template options for any templates where the showtemplate
 -- argument is false. This prevents any output for that template.
 fornum,tinpairs(templateOptions)do
 ift.showtemplate==falsethen
 templateOptions[num]=nil
 end
 end

 -- Check for missing template names.
 fornum,tinpairs(templateOptions)do
 ifnott.templateandnott.titlethen
 error(obj:message(
 'missing-template-option-error',
 num,num
 ),2)
 end
 end

 -- Compress templateOptions table so we can iterate over it with ipairs.
 templateOptions=(function(t)
 localnums={}
 fornuminpairs(t)do
 nums[#nums+1]=num
 end
 table.sort(nums)
 localret={}
 fori,numinipairs(nums)do
 ret[i]=t[num]
 end
 returnret
 end)(templateOptions)

 -- Don't require the __TEMPLATENAME__ magic word for nowiki invocations if
 -- there is only one template being output.
 if#templateOptions<=1then
 templateOptions[1].requireMagicWord=false
 end

 mw.logObject(templateOptions)

 -- Make the template objects
 obj.templates={}
 fori,optionsinipairs(templateOptions)do
 table.insert(obj.templates,Template.new(invocationObj,options))
 end

 -- Add tracking categories. At the moment we are only tracking templates
 -- that use any "heading" parameters or an "output" parameter.
 obj.categories={}
 fork,vinpairs(options)do
 iftype(k)=='string'andk:find('heading')then
 obj.categories['Test cases using heading parameters']=true
 elseifk=='output'then
 obj.categories['Test cases using output parameter']=true
 end
 end

 returnobj
 end

 functionTestCase:getTemplateOutput(templateObj)
 localoutput=templateObj:getOutput()
 ifself.options.resetRefsthen
 mw.getCurrentFrame():extensionTag('references')
 end
 returnoutput
 end

 functionTestCase:templateOutputIsEqual()
 -- Returns a boolean showing whether all of the template outputs are equal.
 -- The random parts of strip markers (see [[Help:Strip markers]]) are
 -- removed before comparison. This means a strip marker can contain anything
 -- and still be treated as equal, but it solves the problem of otherwise
 -- identical wikitext not returning as exactly equal.
 localfunctionnormaliseOutput(obj)
 localout=obj:getOutput()
 -- Remove the random parts from strip markers.
 out=out:gsub('(127円[^127円]*UNIQ%-%-%l+%-)%x+(%-%-?QINU[^127円]*127円)','%1%2')
 returnout
 end
 localfirstOutput=normaliseOutput(self.templates[1])
 fori=2,#self.templatesdo
 localoutput=normaliseOutput(self.templates[i])
 ifoutput~=firstOutputthen
 returnfalse
 end
 end
 returntrue
 end

 functionTestCase:makeCollapsible(s)
 localtitle=self.options.titleorself.templates[1]:makeHeader()
 ifself.options.titlecodethen
 title=self.templates[1]:getInvocation('kbd')
 end
 localisEqual=self:templateOutputIsEqual()
 localroot=mw.html.create('div')
 root
 :wikitext(mw.getCurrentFrame():extensionTag{
 name='templatestyles',
 args={src='Module:Template test case/styles.css'},
 })
 :addClass('mw-collapsible')
 :addClass('test-case-collapsible')
 :addClass(self.options.notcollapsed==falseand'mw-collapsed'ornil)
 ifself.options.wantdiffthen
 root
 :tag('div')
 :addClass(isEqualand'test-case-collapsible-b1'or'test-case-collapsible-b2')
 :wikitext(title)
 :done()
 else
 ifself.options.notcollapsed~=trueorfalsethen
 root
 :addClass(isEqualand'mw-collapsed'ornil)
 end
 root
 :tag('div')
 :addClass(isEqualand'test-case-collapsible-b3'or'test-case-collapsible-b1')
 :wikitext(title)
 :done()
 end
 root
 :tag('div')
 :addClass('mw-collapsible-content')
 :newline()
 :wikitext(s)
 :newline()
 returntostring(root)
 end

 functionTestCase:renderColumns()
 localroot=mw.html.create()
 ifself.options.showcodethen
 root
 :wikitext(self.templates[1]:getInvocation())
 :newline()
 end

 localtableroot=root:tag('table')

 ifself.options.showheaderthen
 -- Caption
 ifself.options.showcaptionthen
 tableroot
 :addClass(self.options.class)
 :cssText(self.options.style)
 :tag('caption')
 :wikitext(self.options.captionorself:message('columns-header'))
 end

 -- Headers
 localheaderRow=tableroot:tag('tr')
 ifself.options.rowheaderthen
 -- rowheader is correct here. We need to add another th cell if
 -- rowheader is set further down, even if heading0 is missing.
 headerRow:tag('th'):wikitext(self.options.heading0)
 end
 localwidth
 if#self.templates>0then
 width=tostring(math.floor(100/#self.templates))..'%'
 else
 width='100%'
 end
 fori,objinipairs(self.templates)do
 headerRow
 :tag('th')
 :css('width',width)
 :wikitext(obj:makeHeader())
 end
 end

 -- Row header
 localdataRow=tableroot:tag('tr'):css('vertical-align','top')
 ifself.options.rowheaderthen
 dataRow:tag('th')
 :attr('scope','row')
 :wikitext(self.options.rowheader)
 end

 -- Template output
 fori,objinipairs(self.templates)do
 ifself.options.output=='nowiki+'then
 dataRow:tag('td')
 :newline()
 :wikitext(self.options.before)
 :wikitext(self:getTemplateOutput(obj))
 :wikitext(self.options.after)
 :wikitext('<pre style="white-space: pre-wrap;">')
 :wikitext(mw.text.nowiki(self.options.beforeor""))
 :wikitext(mw.text.nowiki(self:getTemplateOutput(obj)))
 :wikitext(mw.text.nowiki(self.options.afteror""))
 :wikitext('</pre>')
 elseifself.options.output=='nowiki'then
 dataRow:tag('td')
 :newline()
 :wikitext(mw.text.nowiki(self.options.beforeor""))
 :wikitext(mw.text.nowiki(self:getTemplateOutput(obj)))
 :wikitext(mw.text.nowiki(self.options.afteror""))
 else
 dataRow:tag('td')
 :newline()
 :wikitext(self.options.before)
 :wikitext(self:getTemplateOutput(obj))
 :wikitext(self.options.after)
 end
 end

 returntostring(root)
 end

 functionTestCase:renderRows()
 localroot=mw.html.create()
 ifself.options.showcodethen
 root
 :wikitext(self.templates[1]:getInvocation())
 :newline()
 end

 localtableroot=root:tag('table')
 tableroot
 :addClass(self.options.class)
 :cssText(self.options.style)

 ifself.options.captionthen
 tableroot
 :tag('caption')
 :wikitext(self.options.caption)
 end

 for_,objinipairs(self.templates)do
 localdataRow=tableroot:tag('tr')

 -- Header
 ifself.options.showheaderthen
 ifself.options.format=='tablerows'then
 dataRow:tag('th')
 :attr('scope','row')
 :css('vertical-align','top')
 :css('text-align','left')
 :wikitext(obj:makeHeader())
 dataRow:tag('td')
 :css('vertical-align','top')
 :css('padding','0 1em')
 :wikitext('→')
 else
 dataRow:tag('td')
 :css('text-align','center')
 :css('font-weight','bold')
 :wikitext(obj:makeHeader())
 dataRow=tableroot:tag('tr')
 end
 end

 -- Template output
 ifself.options.output=='nowiki+'then
 dataRow:tag('td')
 :newline()
 :wikitext(self.options.before)
 :wikitext(self:getTemplateOutput(obj))
 :wikitext(self.options.after)
 :wikitext('<pre style="white-space: pre-wrap;">')
 :wikitext(mw.text.nowiki(self.options.beforeor""))
 :wikitext(mw.text.nowiki(self:getTemplateOutput(obj)))
 :wikitext(mw.text.nowiki(self.options.afteror""))
 :wikitext('</pre>')
 elseifself.options.output=='nowiki'then
 dataRow:tag('td')
 :newline()
 :wikitext(mw.text.nowiki(self.options.beforeor""))
 :wikitext(mw.text.nowiki(self:getTemplateOutput(obj)))
 :wikitext(mw.text.nowiki(self.options.afteror""))
 else
 dataRow:tag('td')
 :newline()
 :wikitext(self.options.before)
 :wikitext(self:getTemplateOutput(obj))
 :wikitext(self.options.after)
 end
 end

 returntostring(root)
 end

 functionTestCase:renderInline()
 localarrow=mw.language.getContentLanguage():getArrow('forwards')
 localret={}
 fori,objinipairs(self.templates)do
 localline={}
 line[#line+1]=self.options.prefixor'* '
 ifself.options.showcodethen
 line[#line+1]=obj:getInvocation('code')
 line[#line+1]=' '
 line[#line+1]=arrow
 line[#line+1]=' '
 end
 ifself.options.output=='nowiki+'then
 line[#line+1]=self.options.beforeor""
 line[#line+1]=self:getTemplateOutput(obj)
 line[#line+1]=self.options.afteror""
 line[#line+1]='<pre style="white-space: pre-wrap;">'
 line[#line+1]=mw.text.nowiki(self.options.beforeor"")
 line[#line+1]=mw.text.nowiki(self:getTemplateOutput(obj))
 line[#line+1]=mw.text.nowiki(self.options.afteror"")
 line[#line+1]='</pre>'
 elseifself.options.output=='nowiki'then
 line[#line+1]=mw.text.nowiki(self.options.beforeor"")
 line[#line+1]=mw.text.nowiki(self:getTemplateOutput(obj))
 line[#line+1]=mw.text.nowiki(self.options.afteror"")
 else
 line[#line+1]=self.options.beforeor""
 line[#line+1]=self:getTemplateOutput(obj)
 line[#line+1]=self.options.afteror""
 end
 ret[#ret+1]=table.concat(line)
 end
 ifself.options.addlinethen
 localline={}
 line[#line+1]=self.options.prefixor'* '
 line[#line+1]=self.options.addline
 ret[#ret+1]=table.concat(line)
 end
 returntable.concat(ret,'\n')
 end

 functionTestCase:renderCells()
 localroot=mw.html.create()
 localdataRow=root:tag('tr')
 dataRow
 :css('vertical-align','top')
 :addClass(self.options.class)
 :cssText(self.options.style)

 -- Row header
 ifself.options.rowheaderthen
 dataRow:tag('th')
 :attr('scope','row')
 :newline()
 :wikitext(self.options.rowheaderorself:message('row-header'))
 end
 -- Caption
 ifself.options.showcaptionthen
 dataRow:tag('th')
 :attr('scope','row')
 :newline()
 :wikitext(self.options.captionorself:message('columns-header'))
 end

 -- Show code
 ifself.options.showcodethen
 dataRow:tag('td')
 :newline()
 :wikitext(self:getInvocation('code'))
 end

 -- Template output
 fori,objinipairs(self.templates)do
 ifself.options.output=='nowiki+'then
 dataRow:tag('td')
 :newline()
 :wikitext(self.options.before)
 :wikitext(self:getTemplateOutput(obj))
 :wikitext(self.options.after)
 :wikitext('<pre style="white-space: pre-wrap;">')
 :wikitext(mw.text.nowiki(self.options.beforeor""))
 :wikitext(mw.text.nowiki(self:getTemplateOutput(obj)))
 :wikitext(mw.text.nowiki(self.options.afteror""))
 :wikitext('</pre>')
 elseifself.options.output=='nowiki'then
 dataRow:tag('td')
 :newline()
 :wikitext(mw.text.nowiki(self.options.beforeor""))
 :wikitext(mw.text.nowiki(self:getTemplateOutput(obj)))
 :wikitext(mw.text.nowiki(self.options.afteror""))
 else
 dataRow:tag('td')
 :newline()
 :wikitext(self.options.before)
 :wikitext(self:getTemplateOutput(obj))
 :wikitext(self.options.after)
 end
 end

 returntostring(root)
 end

 functionTestCase:renderDefault()
 localret={}
 ifself.options.showcodethen
 ret[#ret+1]=self.templates[1]:getInvocation()
 end
 fori,objinipairs(self.templates)do
 ret[#ret+1]='<div style="clear: both;"></div>'
 ifself.options.showheaderthen
 ret[#ret+1]=obj:makeHeader()
 end
 ifself.options.output=='nowiki+'then
 ret[#ret+1]=(self.options.beforeor"")..
 self:getTemplateOutput(obj)..
 (self.options.afteror"")..
 '<pre style="white-space: pre-wrap;">'..
 mw.text.nowiki(self.options.beforeor"")..
 mw.text.nowiki(self:getTemplateOutput(obj))..
 mw.text.nowiki(self.options.afteror"")..'</pre>'
 elseifself.options.output=='nowiki'then
 ret[#ret+1]=mw.text.nowiki(self.options.beforeor"")..
 mw.text.nowiki(self:getTemplateOutput(obj))..
 mw.text.nowiki(self.options.afteror"")
 else
 ret[#ret+1]=(self.options.beforeor"")..
 self:getTemplateOutput(obj)..
 (self.options.afteror"")
 end
 end
 returntable.concat(ret,'\n\n')
 end

 functionTestCase:__tostring()
 localformat=self.options.format
 localmethod=formatandTestCase.renderMethods[format]or'renderDefault'
 localret=self[method](self)
 ifself.options.collapsiblethen
 ret=self:makeCollapsible(ret)
 end
 forcatinpairs(self.categories)do
 ret=ret..string.format('[[Category:%s]]',cat)
 end
 returnret
 end

 -------------------------------------------------------------------------------
 -- Nowiki invocation class
 -------------------------------------------------------------------------------

 localNowikiInvocation={}
 NowikiInvocation.__index=NowikiInvocation
 NowikiInvocation.message=message-- Add the message method

 functionNowikiInvocation.new(invocation,cfg)
 localobj=setmetatable({},NowikiInvocation)
 obj.cfg=cfg
 invocation=mw.text.unstrip(invocation)
 -- Decode HTML entities for <, >, and ". This means that HTML entities in
 -- the original code must be escaped as e.g. &amp;lt;, which is unfortunate,
 -- but it is the best we can do as the distinction between <, >, " and &lt;,
 -- &gt;, &quot; is lost during the original nowiki operation.
 invocation=invocation:gsub('&lt;','<')
 invocation=invocation:gsub('&gt;','>')
 invocation=invocation:gsub('&quot;','"')
 obj.invocation=invocation
 returnobj
 end

 functionNowikiInvocation:getInvocation(options)
 localtemplate=options.template:gsub('%%','%%%%')-- Escape "%" with "%%"
 localinvocation,count=self.invocation:gsub(
 self.cfg.templateNameMagicWordPattern,
 template
 )
 ifoptions.requireMagicWord~=falseandcount<1then
 error(self:message(
 'nowiki-magic-word-error',
 self.cfg.templateNameMagicWord
 ))
 end
 returninvocation
 end

 functionNowikiInvocation:getOutput(options)
 localinvocation=self:getInvocation(options)
 returnmw.getCurrentFrame():preprocess(invocation)
 end

 -------------------------------------------------------------------------------
 -- Table invocation class
 -------------------------------------------------------------------------------

 localTableInvocation={}
 TableInvocation.__index=TableInvocation
 TableInvocation.message=message-- Add the message method

 functionTableInvocation.new(invokeArgs,nowikiCode,cfg)
 localobj=setmetatable({},TableInvocation)
 obj.cfg=cfg
 obj.invokeArgs=invokeArgs
 obj.code=nowikiCode
 returnobj
 end

 functionTableInvocation:getInvocation(options)
 ifself.codethen
 localnowikiObj=NowikiInvocation.new(self.code,self.cfg)
 returnnowikiObj:getInvocation(options)
 else
 returnrequire('Module:Template invocation').invocation(
 options.template,
 self.invokeArgs
 )
 end
 end

 functionTableInvocation:getOutput(options)
 if(options.template:sub(1,7)=='#invoke')then
 localmoduleCall=mw.text.split(options.template,'|',true)
 localargs=mw.clone(self.invokeArgs)
 table.insert(args,1,moduleCall[2])
 returnmw.getCurrentFrame():callParserFunction(moduleCall[1],args)
 end
 returnmw.getCurrentFrame():expandTemplate{
 title=options.template,
 args=self.invokeArgs
 }
 end

 -------------------------------------------------------------------------------
 -- Bridge functions
 --
 -- These functions translate template arguments into forms that can be accepted
 -- by the different classes, and return the results.
 -------------------------------------------------------------------------------

 localbridge={}

 functionbridge.table(args,cfg)
 cfg=cfgormw.loadData(DATA_MODULE)

 localoptions,invokeArgs={},{}
 fork,vinpairs(args)do
 localoptionKey=type(k)=='string'andk:match('^_(.*)$')
 ifoptionKeythen
 iftype(v)=='string'then
 v=v:match('^%s*(.-)%s*$')-- trim whitespace
 end
 ifv~=''then
 options[optionKey]=v
 end
 else
 invokeArgs[k]=v
 end
 end

 -- Allow passing a nowiki invocation as an option. While this means users
 -- have to pass in the code twice, whitespace is preserved and &lt; etc.
 -- will work as intended.
 localnowikiCode=options.code
 options.code=nil

 localinvocationObj=TableInvocation.new(invokeArgs,nowikiCode,cfg)
 localtestCaseObj=TestCase.new(invocationObj,options,cfg)
 returntostring(testCaseObj)
 end

 functionbridge.nowiki(args,cfg)
 cfg=cfgormw.loadData(DATA_MODULE)

 -- Convert args beginning with _ for consistency with the normal bridge
 localnewArgs={}
 fork,vinpairs(args)do
 localnormalName=type(k)=="string"andstring.match(k,"^_(.*)$")
 ifnormalNamethen
 newArgs[normalName]=v
 else
 newArgs[k]=v
 end
 end

 localcode=newArgs.codeornewArgs[1]
 localinvocationObj=NowikiInvocation.new(code,cfg)
 newArgs.code=nil
 newArgs[1]=nil
 -- Assume we want to see the code as we already passed it in.
 newArgs.showcode=newArgs.showcodeortrue
 localtestCaseObj=TestCase.new(invocationObj,newArgs,cfg)
 returntostring(testCaseObj)
 end

 -------------------------------------------------------------------------------
 -- Exports
 -------------------------------------------------------------------------------

 localp={}

 functionp.main(frame,cfg)
 cfg=cfgormw.loadData(DATA_MODULE)

 -- Load the wrapper config, if any.
 localwrapperConfig
 ifframe.getParentthen
 localtitle=frame:getParent():getTitle()
 localtemplate=title:gsub(cfg.sandboxSubpagePattern,'')
 wrapperConfig=cfg.wrappers[template]
 end

 -- Work out the function we will call, use it to generate the config for
 -- Module:Arguments, and use Module:Arguments to find the arguments passed
 -- by the user.
 localfunc=wrapperConfigandwrapperConfig.funcor'table'
 localuserArgs=require('Module:Arguments').getArgs(frame,{
 parentOnly=wrapperConfig,
 frameOnly=notwrapperConfig,
 trim=func~='table',
 removeBlanks=func~='table'
 })

 -- Get default args and build the args table. User-specified args overwrite
 -- default args.
 localdefaultArgs=wrapperConfigandwrapperConfig.argsor{}
 localargs={}
 fork,vinpairs(defaultArgs)do
 args[k]=v
 end
 fork,vinpairs(userArgs)do
 args[k]=v
 end

 returnbridge[func](args,cfg)
 end

 functionp._exportClasses()-- For testing
 return{
 Template=Template,
 TestCase=TestCase,
 NowikiInvocation=NowikiInvocation,
 TableInvocation=TableInvocation
 }
 end

 returnp

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