Módulo:Exemplo teste predefinição
Este módulo depende dos seguintes outros módulos: |
Este módulo fornece uma estrutura para criar predefinições que produzem um exemplo para teste de predefinição. Embora os exemplos para testes possam ser criados manualmente, o uso de predefinições baseadas em Lua, como as fornecidas por este módulo, tem a vantagem de que os argumentos da predefinição só precisam ser inseridos uma vez, reduzindo assim o esforço envolvido na criação de exemplos para teste e reduzindo a possibilidade de erros na entrada.
Uso
editarEste módulo geralmente não deve ser chamado diretamente. Em vez disso, você deve usar um dos seguintes modelos:
Predefinições baseadas em parâmetros:
- Predefinição:Exemplo teste – para exemplos para teste padrão
- Predefinição:Exemplo teste tabela – para exemplos para teste dispostos lado a lado em colunas
- Predefinição:Exemplo teste linhas – para exemplos para teste organizados como linhas em uma tabela
- Predefinição:Exemplo teste desmontável – para exemplos para teste que são recolhidos por padrão se os resultados forem os mesmos
- Predefinição:Exemplo teste em linha – para exemplos para teste com invocações pequenas e saída pequena, que não contêm quebras de linha
A única diferença entre essas predefiniçõed são os argumentos padrão. Por exemplo, é possível exibir exemplos para teste lado a lado em Predefinição:Exemplo teste linhas especificando |_format=columns
Predefinições baseadas em Nowiki:
- Predefinição:Exemplo teste nowiki –para exemplos para teste criados a partir de código de predefinição agrupado em marcações (tags) nowiki (útil para exibir invocações de predeginições complexss)
- Predefinição:Demo predefinição nowiki – para uso em documentação de predefinição
Também é possível usar um formato de {{#invoke:Exemplo teste predefinição|main|parâmetros}}
. Isso usa os mesmos padrões que Predefinição:Exemplo teste; consulte essa página para documentação dos parâmetros.
Não há interface direta para este módulo para outros módulos Lua. Os módulos Lua geralmente devem usar módulos de exemplo para teste baseados em Lua, como Módulo:UnitTests ou Módulo:ScribuntoUnit. Se for realmente necessário usar este módulo, você pode usar frame:expandTemplate com uma das predefinições listadas acima.
Configuração
editarEste módulo possui um módulo de configuração em Módulo:Exemplo teste predefinição/config. Você pode editá-lo para adicionar novas predefinições de wrapper ou para alterar as mensagens que o módulo gera.
Categorias de rastreamento/manutenção
editar
--[[
Um módulo para gerar predefinições de exemplos para testes.
Este módulo incorpora código do módulo "Testcase table" da Wikipedia em
inglês,[1] escrito por Frietjes [2] com contribuições do Sr. Stradivarius [3]
e Jackmcbarn,[4] e o módulo "Testcase rows" da Wikipédia em inglês,[5]
escrito pelo Sr. Stradivarius.
Os módulos "Testcase table" e "Testcase rows" são lançados sob a
Licença CC BY-SA 3.0 [6] e GFDL.[7]
Licença: CC BY-SA 3.0 e GFDL
Autor: Sr. 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
]]
-- Carrega os módulos necessários
local yesno = require('Módulo:Yesno')
-- Define constantes
local DATA_MODULE = 'Módulo:Exemplo teste predefinição/data'
-------------------------------------------------------------------------------
-- Métodos compartilhados
-------------------------------------------------------------------------------
local function message(self, key, ...)
-- Este método é adicionado às classes que precisam lidar com mensagens do
-- módulo de configuração.
local msg = self.cfg.msg[key]
if select(1, ...) then
return mw.message.newRawMessage(msg, ...):plain()
else
return msg
end
end
-------------------------------------------------------------------------------
-- Classe de predefinição
-------------------------------------------------------------------------------
local Template = {}
Template.memoizedMethods = {
-- Nomes de métodos a serem memorizados em cada objeto. Esta tabela deve
-- conter apenas métodos sem parâmetros.
getFullPage = true,
getName = true,
makeHeader = true,
getOutput = true
}
function Template.new(invocationObj, options)
local obj = {}
-- Define entrada
for k, v in pairs(options or {}) do
if not Template[k] then
obj[k] = v
end
end
obj._invocation = invocationObj
-- Valida entrada
if not obj.template and not obj.title then
error('nenhuma predefinição ou título especificados', 2)
end
-- Memoriza chamadas de métodos caras
local memoFuncs = {}
return setmetatable(obj, {
__index = function (t, key)
if Template.memoizedMethods[key] then
local func = memoFuncs[key]
if not func then
local val = Template[key](t)
func = function () return val end
memoFuncs[key] = func
end
return func
else
return Template[key]
end
end
})
end
function Template:getFullPage()
if not self.template then
return self.title.prefixedText
elseif self.template:sub(1, 7) == '#invoke' then
return 'Módulo' .. self.template:sub(8):gsub('|.*', '')
else
local strippedTemplate, hasColon = self.template:gsub('^:', '', 1)
hasColon = hasColon > 0
local ns = strippedTemplate:match('^(.-):')
ns = ns and mw.site.namespaces[ns]
if ns then
return strippedTemplate
elseif hasColon then
return strippedTemplate -- Espaço nomeado principal
else
return mw.site.namespaces[10].name .. ':' .. strippedTemplate
end
end
end
function Template:getName()
if self.template then
return self.template
else
return require('Módulo:Template invocation').name(self.title)
end
end
function Template:makeLink(display)
if display then
return string.format('[[:%s|%s]]', self:getFullPage(), display)
else
return string.format('[[:%s]]', self:getFullPage())
end
end
function Template:makeBraceLink(display)
display = display or self:getName()
local link = self:makeLink(display)
return mw.text.nowiki('{{') .. link .. mw.text.nowiki('}}')
end
function Template:makeHeader()
return self.heading or self:makeBraceLink()
end
function Template:getInvocation(format)
local invocation = self._invocation:getInvocation{
template = self:getName(),
requireMagicWord = self.requireMagicWord,
}
if format == 'code' then
invocation = '<code>' .. mw.text.nowiki(invocation) .. '</code>'
elseif format == 'kbd' then
invocation = '<kbd>' .. mw.text.nowiki(invocation) .. '</kbd>'
elseif format == 'plain' then
invocation = mw.text.nowiki(invocation)
else
-- Marcações (tags) pre são o padrão
invocation = mw.text.encode(invocation, '&')
invocation = '<pre style="white-space: pre-wrap;">' .. invocation .. '</pre>'
invocation = mw.getCurrentFrame():preprocess(invocation)
end
return invocation
end
function Template:getOutput()
local protect = require('Módulo:Protect')
-- calling self._invocation:getOutput{...}
return protect(self._invocation.getOutput)(self._invocation, {
template = self:getName(),
requireMagicWord = self.requireMagicWord,
})
end
-------------------------------------------------------------------------------
-- Classe TestCase
-------------------------------------------------------------------------------
local TestCase = {}
TestCase.__index = TestCase
TestCase.message = message -- adiciona o método de mensagem
TestCase.renderMethods = {
-- As chaves nesta tabela são valores da opção "format", os valores são os
-- método para renderizar esse formato.
columns = 'renderColumns',
rows = 'renderRows',
tablerows = 'renderRows',
inline = 'renderInline',
cells = 'renderCells',
default = 'renderDefault'
}
function TestCase.new(invocationObj, options, cfg)
local obj = setmetatable({}, TestCase)
obj.cfg = cfg
-- Separa as opções gerais das opções de predefinição. As opções de
-- predefinição são numeradas, enquanto as opções gerais não são.
local generalOptions, templateOptions = {}, {}
for k, v in pairs(options) do
local prefix, num
if type(k) == 'string' then
prefix, num = k:match('^(.-)([1-9][0-9]*)$')
end
if prefix then
num = tonumber(num)
templateOptions[num] = templateOptions[num] or {}
templateOptions[num][prefix] = v
else
generalOptions[k] = v
end
end
-- Define opções gerais
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
-- Pré-processa argumentos de predefinição
for num, t in pairs(templateOptions) do
if t.showtemplate ~= nil then
t.showtemplate = yesno(t.showtemplate)
end
end
-- Configura as duas primeiras tabelas de opções de predefinição, de modo
-- que se apenas a "template3" for especificada, ela não será a primeira
-- predefinição quando o arranjo de opções da tabela for compactado.
templateOptions[1] = templateOptions[1] or {}
templateOptions[2] = templateOptions[2] or {}
-- Permite que a opção "template" substitua a opção "template1" para
-- compatibilidade retroativa com [[Módulo:Exemplo teste tabela]].
if generalOptions.template then
templateOptions[1].template = generalOptions.template
end
-- Adiciona opções de predefinição padrão
if templateOptions[1].template and not templateOptions[2].template then
templateOptions[2].template = templateOptions[1].template ..
'/' .. obj.cfg.sandboxSubpage
end
if not templateOptions[1].template then
templateOptions[1].title = mw.title.getCurrentTitle().basePageTitle
end
if not templateOptions[2].template then
templateOptions[2].title = templateOptions[1].title:subPageTitle(
obj.cfg.sandboxSubpage
)
end
-- Remove opções de predefinição para quaisquer predefinições em que o
-- argumento showtemplate seja falso. Isso impede qualquer saída para essa
-- predefinição.
for num, t in pairs(templateOptions) do
if t.showtemplate == false then
templateOptions[num] = nil
end
end
-- Verifica se há nomes de predefinição ausentes.
for num, t in pairs(templateOptions) do
if not t.template and not t.title then
error(obj:message(
'missing-template-option-error',
num, num
), 2)
end
end
-- Compacta a tabela templateOptions para que possamos iterá-la com ipairs.
templateOptions = (function (t)
local nums = {}
for num in pairs(t) do
nums[#nums + 1] = num
end
table.sort(nums)
local ret = {}
for i, num in ipairs(nums) do
ret[i] = t[num]
end
return ret
end)(templateOptions)
-- Não requer a palavra mágica __TEMPLATENAME__ para invocações nowiki se
-- há apenas uma predefinição sendo gerada.
if #templateOptions <= 1 then
templateOptions[1].requireMagicWord = false
end
mw.logObject(templateOptions)
-- Faz os objetos de predefinição
obj.templates = {}
for i, options in ipairs(templateOptions) do
table.insert(obj.templates, Template.new(invocationObj, options))
end
-- Adiciona categorias de rastreamento/manutenção. No momento estamos apenas
-- acompanhando predefinições que usam qualquer parâmetro de "cabeçalho" ou
-- um parâmetro de "saída".
obj.categories = {}
for k, v in pairs(options) do
if type(k) == 'string' and k:find('heading') then
obj.categories['!Exemplos para testes que usam parâmetros de cabeçalho'] = true
elseif k == 'output' then
obj.categories['!Exemplos para testes que usam parâmetro de output'] = true
end
end
return obj
end
function TestCase:getTemplateOutput(templateObj)
local output = templateObj:getOutput()
if self.options.resetRefs then
mw.getCurrentFrame():extensionTag('references')
end
return output
end
function TestCase:templateOutputIsEqual()
-- Retorna um booleano que mostra se todas as saídas de predefinição são
-- iguais. As partes aleatórias dos marcadores de tira (veja
-- [[:en:Help:Strip markers]]) são removidas antes da comparação. Isso
-- significa que um marcador de tira pode conter qualquer coisa e ainda ser
-- tratado como igual, mas resolve o problema de textos wiki idênticos não
-- retornarem exatamente iguais.
local function normaliseOutput(obj)
local out = obj:getOutput()
-- Remove as partes aleatórias dos marcadores de tira.
out = out:gsub('(\127[^\127]*UNIQ%-%-%l+%-)%x+(%-%-?QINU[^\127]*\127)', '%1%2')
return out
end
local firstOutput = normaliseOutput(self.templates[1])
for i = 2, #self.templates do
local output = normaliseOutput(self.templates[i])
if output ~= firstOutput then
return false
end
end
return true
end
function TestCase:makeCollapsible(s)
local title = self.options.title or self.templates[1]:makeHeader()
if self.options.titlecode then
title = self.templates[1]:getInvocation('kbd')
end
local isEqual = self:templateOutputIsEqual()
local root = mw.html.create('div')
root
:addClass('mw-collapsible')
:css('width', '100%')
:css('border', 'solid silver 1px')
:css('padding', '0.2em')
:css('clear', 'both')
:addClass(self.options.notcollapsed == false and 'mw-collapsed' or nil)
if self.options.wantdiff then
root
:tag('div')
:css('background-color', isEqual and 'yellow' or '#90a8ee')
:css('font-weight', 'bold')
:css('padding', '0.2em')
:wikitext(title)
:done()
else
if self.options.notcollapsed ~= true or false then
root
:addClass(isEqual and 'mw-collapsed' or nil)
end
root
:tag('div')
:css('background-color', isEqual and 'lightgreen' or 'yellow')
:css('font-weight', 'bold')
:css('padding', '0.2em')
:wikitext(title)
:done()
end
root
:tag('div')
:addClass('mw-collapsible-content')
:newline()
:wikitext(s)
:newline()
return tostring(root)
end
function TestCase:renderColumns()
local root = mw.html.create()
if self.options.showcode then
root
:wikitext(self.templates[1]:getInvocation())
:newline()
end
local tableroot = root:tag('table')
if self.options.showheader then
-- Legenda
if self.options.showcaption then
tableroot
:addClass(self.options.class)
:cssText(self.options.style)
:tag('caption')
:wikitext(self.options.caption or self:message('columns-header'))
end
-- Cabeçalhos
local headerRow = tableroot:tag('tr')
if self.options.rowheader then
-- rowheader está correto aqui. Precisamos adicionar outra célula se
-- rowheader for definido mais abaixo, mesmo se o header0 estiver
-- faltando.
headerRow:tag('th'):wikitext(self.options.heading0)
end
local width
if #self.templates > 0 then
width = tostring(math.floor(100 / #self.templates)) .. '%'
else
width = '100%'
end
for i, obj in ipairs(self.templates) do
headerRow
:tag('th')
:css('width', width)
:wikitext(obj:makeHeader())
end
end
-- Cabeçalho de linha
local dataRow = tableroot:tag('tr'):css('vertical-align', 'top')
if self.options.rowheader then
dataRow:tag('th')
:attr('scope', 'row')
:wikitext(self.options.rowheader)
end
-- Saída de predefinição
for i, obj in ipairs(self.templates) do
if self.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.before or ""))
:wikitext(mw.text.nowiki(self:getTemplateOutput(obj)))
:wikitext(mw.text.nowiki(self.options.after or ""))
:wikitext('</pre>')
elseif self.options.output == 'nowiki' then
dataRow:tag('td')
:newline()
:wikitext(mw.text.nowiki(self.options.before or ""))
:wikitext(mw.text.nowiki(self:getTemplateOutput(obj)))
:wikitext(mw.text.nowiki(self.options.after or ""))
else
dataRow:tag('td')
:newline()
:wikitext(self.options.before)
:wikitext(self:getTemplateOutput(obj))
:wikitext(self.options.after)
end
end
return tostring(root)
end
function TestCase:renderRows()
local root = mw.html.create()
if self.options.showcode then
root
:wikitext(self.templates[1]:getInvocation())
:newline()
end
local tableroot = root:tag('table')
tableroot
:addClass(self.options.class)
:cssText(self.options.style)
if self.options.caption then
tableroot
:tag('caption')
:wikitext(self.options.caption)
end
for _, obj in ipairs(self.templates) do
local dataRow = tableroot:tag('tr')
-- Cabeçalho
if self.options.showheader then
if self.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
-- Saída de predefinição
if self.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.before or ""))
:wikitext(mw.text.nowiki(self:getTemplateOutput(obj)))
:wikitext(mw.text.nowiki(self.options.after or ""))
:wikitext('</pre>')
elseif self.options.output == 'nowiki' then
dataRow:tag('td')
:newline()
:wikitext(mw.text.nowiki(self.options.before or ""))
:wikitext(mw.text.nowiki(self:getTemplateOutput(obj)))
:wikitext(mw.text.nowiki(self.options.after or ""))
else
dataRow:tag('td')
:newline()
:wikitext(self.options.before)
:wikitext(self:getTemplateOutput(obj))
:wikitext(self.options.after)
end
end
return tostring(root)
end
function TestCase:renderInline()
local arrow = mw.language.getContentLanguage():getArrow('forwards')
local ret = {}
for i, obj in ipairs(self.templates) do
local line = {}
line[#line + 1] = self.options.prefix or '* '
if self.options.showcode then
line[#line + 1] = obj:getInvocation('code')
line[#line + 1] = ' '
line[#line + 1] = arrow
line[#line + 1] = ' '
end
if self.options.output == 'nowiki+' then
line[#line + 1] = self.options.before or ""
line[#line + 1] = self:getTemplateOutput(obj)
line[#line + 1] = self.options.after or ""
line[#line + 1] = '<pre style="white-space: pre-wrap;">'
line[#line + 1] = mw.text.nowiki(self.options.before or "")
line[#line + 1] = mw.text.nowiki(self:getTemplateOutput(obj))
line[#line + 1] = mw.text.nowiki(self.options.after or "")
line[#line + 1] = '</pre>'
elseif self.options.output == 'nowiki' then
line[#line + 1] = mw.text.nowiki(self.options.before or "")
line[#line + 1] = mw.text.nowiki(self:getTemplateOutput(obj))
line[#line + 1] = mw.text.nowiki(self.options.after or "")
else
line[#line + 1] = self.options.before or ""
line[#line + 1] = self:getTemplateOutput(obj)
line[#line + 1] = self.options.after or ""
end
ret[#ret + 1] = table.concat(line)
end
if self.options.addline then
local line = {}
line[#line + 1] = self.options.prefix or '* '
line[#line + 1] = self.options.addline
ret[#ret + 1] = table.concat(line)
end
return table.concat(ret, '\n')
end
function TestCase:renderCells()
local root = mw.html.create()
local dataRow = root:tag('tr')
dataRow
:css('vertical-align', 'top')
:addClass(self.options.class)
:cssText(self.options.style)
-- Cabeçalho de linha
if self.options.rowheader then
dataRow:tag('th')
:attr('scope', 'row')
:newline()
:wikitext(self.options.rowheader or self:message('row-header'))
end
-- Legenda
if self.options.showcaption then
dataRow:tag('th')
:attr('scope', 'row')
:newline()
:wikitext(self.options.caption or self:message('columns-header'))
end
-- Mostrar código
if self.options.showcode then
dataRow:tag('td')
:newline()
:wikitext(self:getInvocation('code'))
end
-- Saída de predefinição
for i, obj in ipairs(self.templates) do
if self.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.before or ""))
:wikitext(mw.text.nowiki(self:getTemplateOutput(obj)))
:wikitext(mw.text.nowiki(self.options.after or ""))
:wikitext('</pre>')
elseif self.options.output == 'nowiki' then
dataRow:tag('td')
:newline()
:wikitext(mw.text.nowiki(self.options.before or ""))
:wikitext(mw.text.nowiki(self:getTemplateOutput(obj)))
:wikitext(mw.text.nowiki(self.options.after or ""))
else
dataRow:tag('td')
:newline()
:wikitext(self.options.before)
:wikitext(self:getTemplateOutput(obj))
:wikitext(self.options.after)
end
end
return tostring(root)
end
function TestCase:renderDefault()
local ret = {}
if self.options.showcode then
ret[#ret + 1] = self.templates[1]:getInvocation()
end
for i, obj in ipairs(self.templates) do
ret[#ret + 1] = '<div style="clear: both;"></div>'
if self.options.showheader then
ret[#ret + 1] = obj:makeHeader()
end
if self.options.output == 'nowiki+' then
ret[#ret + 1] = (self.options.before or "") ..
self:getTemplateOutput(obj) ..
(self.options.after or "") ..
'<pre style="white-space: pre-wrap;">' ..
mw.text.nowiki(self.options.before or "") ..
mw.text.nowiki(self:getTemplateOutput(obj)) ..
mw.text.nowiki(self.options.after or "") .. '</pre>'
elseif self.options.output == 'nowiki' then
ret[#ret + 1] = mw.text.nowiki(self.options.before or "") ..
mw.text.nowiki(self:getTemplateOutput(obj)) ..
mw.text.nowiki(self.options.after or "")
else
ret[#ret + 1] = (self.options.before or "") ..
self:getTemplateOutput(obj) ..
(self.options.after or "")
end
end
return table.concat(ret, '\n\n')
end
function TestCase:__tostring()
local format = self.options.format
local method = format and TestCase.renderMethods[format] or 'renderDefault'
local ret = self[method](self)
if self.options.collapsible then
ret = self:makeCollapsible(ret)
end
for cat in pairs(self.categories) do
ret = ret .. string.format('[[Categoria:%s]]', cat)
end
return ret
end
-------------------------------------------------------------------------------
-- Classe de invocação Nowiki
-------------------------------------------------------------------------------
local NowikiInvocation = {}
NowikiInvocation.__index = NowikiInvocation
NowikiInvocation.message = message -- Adiciona o método de mensagem
function NowikiInvocation.new(invocation, cfg)
local obj = setmetatable({}, NowikiInvocation)
obj.cfg = cfg
invocation = mw.text.unstrip(invocation)
-- Decodifica entidades de HTML para <, > e ". Isso significa que as
-- entidades de HTML no código original devem ser escapadas como, por
-- exemplo, &lt;, o que é lamentável, mas é o melhor que podemos fazer,
-- pois a distinção entre <, >, " e <, >, " é perdida durante a
-- operação original de nowiki.
invocation = invocation:gsub('<', '<')
invocation = invocation:gsub('>', '>')
invocation = invocation:gsub('"', '"')
obj.invocation = invocation
return obj
end
function NowikiInvocation:getInvocation(options)
local template = options.template:gsub('%%', '%%%%') -- Escapa "%" com "%%"
local invocation, count = self.invocation:gsub(
self.cfg.templateNameMagicWordPattern,
template
)
if options.requireMagicWord ~= false and count < 1 then
error(self:message(
'nowiki-magic-word-error',
self.cfg.templateNameMagicWord
))
end
return invocation
end
function NowikiInvocation:getOutput(options)
local invocation = self:getInvocation(options)
return mw.getCurrentFrame():preprocess(invocation)
end
-------------------------------------------------------------------------------
-- Classe de invocação de tabela
-------------------------------------------------------------------------------
local TableInvocation = {}
TableInvocation.__index = TableInvocation
TableInvocation.message = message -- Adiciona o método de mensagem
function TableInvocation.new(invokeArgs, nowikiCode, cfg)
local obj = setmetatable({}, TableInvocation)
obj.cfg = cfg
obj.invokeArgs = invokeArgs
obj.code = nowikiCode
return obj
end
function TableInvocation:getInvocation(options)
if self.code then
local nowikiObj = NowikiInvocation.new(self.code, self.cfg)
return nowikiObj:getInvocation(options)
else
return require('Módulo:Template invocation').invocation(
options.template,
self.invokeArgs
)
end
end
function TableInvocation:getOutput(options)
if (options.template:sub(1, 7) == '#invoke') then
local moduleCall = mw.text.split(options.template, '|', true)
local args = mw.clone(self.invokeArgs)
table.insert(args, 1, moduleCall[2])
return mw.getCurrentFrame():callParserFunction(moduleCall[1], args)
end
return mw.getCurrentFrame():expandTemplate{
title = options.template,
args = self.invokeArgs
}
end
-------------------------------------------------------------------------------
-- Funções de ponte
--
-- Estas funções traduzem argumentos de predefinição em formulários que podem
-- ser aceitos pelas diferentes classes e retornam os resultados.
-------------------------------------------------------------------------------
local bridge = {}
function bridge.table(args, cfg)
cfg = cfg or mw.loadData(DATA_MODULE)
local options, invokeArgs = {}, {}
for k, v in pairs(args) do
local optionKey = type(k) == 'string' and k:match('^_(.*)$')
if optionKey then
if type(v) == 'string' then
v = v:match('^%s*(.-)%s*$') -- corta espaços em branco
end
if v ~= '' then
options[optionKey] = v
end
else
invokeArgs[k] = v
end
end
-- Permite passar uma invocação nowiki como opção. Embora isso signifique
-- que os usuários tenham que passar o código duas vezes, os espaços em
-- branco são preservados e < etc. funcionarão conforme planejado.
local nowikiCode = options.code
options.code = nil
local invocationObj = TableInvocation.new(invokeArgs, nowikiCode, cfg)
local testCaseObj = TestCase.new(invocationObj, options, cfg)
return tostring(testCaseObj)
end
function bridge.nowiki(args, cfg)
cfg = cfg or mw.loadData(DATA_MODULE)
-- Converte argumentos começando com _ para consistência com a ponte normal
local newArgs = {}
for k, v in pairs(args) do
local normalName = type(k) == "string" and string.match(k, "^_(.*)$")
if normalName then
newArgs[normalName] = v
else
newArgs[k] = v
end
end
local code = newArgs.code or newArgs[1]
local invocationObj = NowikiInvocation.new(code, cfg)
newArgs.code = nil
newArgs[1] = nil
-- Supõe que nós queremos ver o código como já o passamos.
newArgs.showcode = newArgs.showcode or true
local testCaseObj = TestCase.new(invocationObj, newArgs, cfg)
return tostring(testCaseObj)
end
-------------------------------------------------------------------------------
-- Exportações
-------------------------------------------------------------------------------
local p = {}
function p.main(frame, cfg)
cfg = cfg or mw.loadData(DATA_MODULE)
-- Carrega a configuração de wrapper, se houver.
local wrapperConfig
if frame.getParent then
local title = frame:getParent():getTitle()
local template = title:gsub(cfg.sandboxSubpagePattern, '')
wrapperConfig = cfg.wrappers[template]
end
-- Elabora a função que nós iremos chamar, usa-a para gerar a configuração
-- para Módulo:Arguments, e usa Módulo:Arguments para
-- encontrar os argumentos passados pelo usuário.
local func = wrapperConfig and wrapperConfig.func or 'table'
local userArgs = require('Módulo:Arguments').getArgs(frame, {
parentOnly = wrapperConfig,
frameOnly = not wrapperConfig,
trim = func ~= 'table',
removeBlanks = func ~= 'table'
})
-- Obtém argumentos padrão e constrói a tabela de argumentos. Os argumentos
-- especificados pelo usuário substituem os argumentos padrão.
local defaultArgs = wrapperConfig and wrapperConfig.args or {}
local args = {}
for k, v in pairs(defaultArgs) do
args[k] = v
end
for k, v in pairs(userArgs) do
args[k] = v
end
return bridge[func](args, cfg)
end
function p._exportClasses() -- Para teste
return {
Template = Template,
TestCase = TestCase,
NowikiInvocation = NowikiInvocation,
TableInvocation = TableInvocation
}
end
return p