Mudanças

Ir para navegação Ir para pesquisar

Módulo:Ficha

20 332 bytes adicionados, 02h31min de 15 de dezembro de 2019
Criação do Módulo Ficha.
--
-- Este módulo implementa {{Ficha}}
--
local p = {}

local navbar = require('Módulo:Navbar')._navbar

local args = {}
local origArgs
local root

local function notempty( s ) return s and s:match( '%S' ) end

local function fixChildBoxes(sval, tt)
if notempty(sval) then
local marker = '<span class=special_infobox_marker>'
local s = sval
s = mw.ustring.gsub(s, '(<%s*[Tt][Rr])', marker .. '%1')
s = mw.ustring.gsub(s, '(</[Tt][Rr]%s*>)', '%1' .. marker)
if s:match(marker) then
s = mw.ustring.gsub(s, marker .. '%s*' .. marker, '')
s = mw.ustring.gsub(s, '([\r\n]|-[^\r\n]*[\r\n])%s*' .. marker, '%1')
s = mw.ustring.gsub(s, marker .. '%s*([\r\n]|-)', '%1')
s = mw.ustring.gsub(s, '(</[Cc][Aa][Pp][Tt][Ii][Oo][Nn]%s*>%s*)' .. marker, '%1')
s = mw.ustring.gsub(s, '(<%s*[Tt][Aa][Bb][Ll][Ee][^<>]*>%s*)' .. marker, '%1')
s = mw.ustring.gsub(s, '^(%{|[^\r\n]*[\r\n]%s*)' .. marker, '%1')
s = mw.ustring.gsub(s, '([\r\n]%{|[^\r\n]*[\r\n]%s*)' .. marker, '%1')
s = mw.ustring.gsub(s, marker .. '(%s*</[Tt][Aa][Bb][Ll][Ee]%s*>)', '%1')
s = mw.ustring.gsub(s, marker .. '(%s*\n|%})', '%1')
end
if s:match(marker) then
local subcells = mw.text.split(s, marker)
s = ''
for k = 1, #subcells do
if k == 1 then
s = s .. subcells[k] .. '</' .. tt .. '></tr>'
elseif k == #subcells then
local rowstyle = ' style="display:none"'
if notempty(subcells[k]) then rowstyle = '' end
s = s .. '<tr' .. rowstyle ..'><' .. tt .. ' colspan=2>\n' .. subcells[k]
elseif notempty(subcells[k]) then
if (k % 2) == 0 then
s = s .. subcells[k]
else
s = s .. '<tr><' .. tt .. ' colspan=2>\n' .. subcells[k] .. '</' .. tt .. '></tr>'
end
end
end
end
-- as próximas duas linhas adicionam um nova linha no final de listas para o analisador sintático de PHP
-- https://en.wikipedia.org/w/index.php?title=Template_talk:Infobox_musical_artist&oldid=849054481
-- remover quando [[:phab:T191516]] estiver consertado ou OBE
s = mw.ustring.gsub(s, '([\r\n][%*#;:][^\r\n]*)$', '%1\n')
s = mw.ustring.gsub(s, '^([%*#;:][^\r\n]*)$', '%1\n')
s = mw.ustring.gsub(s, '^([%*#;:])', '\n%1')
s = mw.ustring.gsub(s, '^(%{%|)', '\n%1')
return s
else
return sval
end
end

local function union(t1, t2)
-- Retorna a união dos valores de duas tabelas, em sequência.
local vals = {}
for k, v in pairs(t1) do
vals[v] = true
end
for k, v in pairs(t2) do
vals[v] = true
end
local ret = {}
for k, v in pairs(vals) do
table.insert(ret, k)
end
return ret
end

local function getArgNums(prefix)
-- Retorna uma tabela que contém os números dos argumentos que existem
-- para o prefixo identificado. Por exemplo, se o prefixo fosse 'data', e
-- 'data1', 'data2' e 'data5' existirem, retornaria {1, 2, 5}.
local nums = {}
for k, v in pairs(args) do
local num = tostring(k):match('^' .. prefix .. '([1-9]%d*)$')
if num then table.insert(nums, tonumber(num)) end
end
table.sort(nums)
return nums
end

local function addRow(rowArgs)
-- Adiciona uma linha à infobox, ou com uma célula de cabeçalho
-- ou com uma combinação rótulo/célula de dados.
if rowArgs.header then
root
:tag('tr')
:addClass(rowArgs.rowclass)
:cssText(rowArgs.rowstyle)
:attr('id', rowArgs.rowid)
:tag('th')
:attr('colspan', 2)
:attr('id', rowArgs.headerid)
:addClass(rowArgs.class)
:addClass(args.headerclass or args['cabeçalho-classe'])
:css('text-align', 'center')
:cssText(args.headerstyle or args['cabeçalho-estilo'])
:cssText(rowArgs.rowcellstyle)
:wikitext(fixChildBoxes(rowArgs.header, 'th'))
elseif rowArgs.data then
local row = root:tag('tr')
row:addClass(rowArgs.rowclass)
row:cssText(rowArgs.rowstyle)
row:attr('id', rowArgs.rowid)
if rowArgs.label then
row
:tag('th')
:attr('scope', 'row')
:attr('id', rowArgs.labelid)
:cssText(args.labelstyle or args['rótulo-estilo'])
:cssText(rowArgs.rowcellstyle)
:wikitext(rowArgs.label)
:done()
end

local dataCell = row:tag('td')
if not rowArgs.label then
dataCell
:attr('colspan', 2)
:css('text-align', 'center')
end
dataCell
:attr('id', rowArgs.dataid)
:addClass(rowArgs.class)
:cssText(rowArgs.datastyle)
:cssText(rowArgs.rowcellstyle)
:wikitext(fixChildBoxes(rowArgs.data, 'td'))
end
end

local function renderTitle()
local argsTitle = args.title or args['título']
if not argsTitle then return end

root
:tag('caption')
:addClass(args.titleclass or args['título-classe'])
:cssText(args.titlestyle or args['título-estilo'])
:wikitext(args.title or args['título'])
end

local function renderAboveRow()
local argsAbove = args.above or args.acima
if not argsAbove then return end

root
:tag('tr')
:tag('th')
:attr('colspan', 2)
:addClass(args.aboveclass or args['acima-classe'])
:css('text-align', 'center')
:css('font-size', '125%')
:css('font-weight', 'bold')
:cssText(args.abovestyle or args['acima-estilo'])
:wikitext(fixChildBoxes(argsAbove,'th'))
end

local function renderBelowRow()
local argsBelow = args.below or args.abaixo
if not argsBelow then return end

root
:tag('tr')
:tag('td')
:attr('colspan', '2')
:addClass(args.belowclass or args['abaixo-classe'])
:css('text-align', 'center')
:cssText(args.belowstyle or args['abaixo-estilo'])
:wikitext(fixChildBoxes(argsBelow,'td'))
end

local function renderSubheaders()
if args.subheader then
args.subheader1 = args.subheader
elseif args['subcabeçalho'] then
args['subcabeçalho1'] = args['subcabeçalho']
end
if args.subheaderrowclass then
args.subheaderrowclass1 = args.subheaderrowclass
elseif args['subcabeçalho-linha-classe'] then
args['subcabeçalho-linha-classe1'] = args['subcabeçalho-linha-classe']
end
local subheadernums = union(getArgNums('subheader'), getArgNums('subcabeçalho'))
table.sort(subheadernums)
for k, num in ipairs(subheadernums) do
addRow({
data = args['subheader' .. tostring(num)] or args['subcabeçalho' .. tostring(num)],
datastyle = args.subheaderstyle or args['subcabeçalho-estilo'],
rowcellstyle = args['subheaderstyle' .. tostring(num)] or args['subcabeçalho-estilo' .. tostring(num)],
class = args.subheaderclass or args['subcabeçalho-classe'],
rowclass = args['subheaderrowclass' .. tostring(num)] or args['subcabeçalho-linha-classe' .. tostring(num)]
})
end
end

local function renderImages()
if args.image then
args.image1 = args.image or args.imagem
end
if args.imagem then
args.imagem1 = args.imagem or args.image
end
if args.caption then
args.caption1 = args.caption or args.legenda
end
if args.legenda then
args.legenda1 = args.legenda or args.caption
end
local imagenums = union(getArgNums('image'), getArgNums('imagem'))
table.sort(imagenums)
for k, num in ipairs(imagenums) do
local caption = args['caption' .. tostring(num)] or args['legenda' .. tostring(num)]
local data = mw.html.create():wikitext(args['image' .. tostring(num)] or args['imagem' .. tostring(num)])
if caption then
data
:tag('div')
:cssText(args.captionstyle or args['legenda-estilo'])
:wikitext(caption)
end
addRow({
data = tostring(data),
datastyle = args.imagestyle or args['imagem-estilo'],
class = args.imageclass or args['imagem-classe'],
rowclass = args['imagerowclass' .. tostring(num)] or args['imagem-linha-classe' .. tostring(num)]
})
end
end

local function renderRows()
-- Recebe a união dos números dos argumentos de cabeçalho e de dados
-- e renderiza-os todos em ordem ao usar addRow.
local rownums = union(getArgNums('header'), getArgNums('data'))
table.sort(rownums)
rownums = union(rownums, getArgNums('cabeçalho'))
table.sort(rownums)
rownums = union(rownums, getArgNums('dados'))
table.sort(rownums)
for k, num in ipairs(rownums) do
addRow({
header = args['header' .. tostring(num)] or args['cabeçalho' .. tostring(num)],
label = args['label' .. tostring(num)] or args['rótulo' .. tostring(num)],
data = args['data' .. tostring(num)] or args['dados' .. tostring(num)],
datastyle = args.datastyle or args['dados-estilo'],
class = args['class' .. tostring(num)] or args['classe' .. tostring(num)],
rowclass = args['rowclass' .. tostring(num)] or args['linha-classe' .. tostring(num)],
rowstyle = args['rowstyle' .. tostring(num)] or args['linha-estilo' .. tostring(num)],
rowcellstyle = args['rowcellstyle' .. tostring(num)] or args['linha-célula-estilo' .. tostring(num)],
dataid = args['dataid' .. tostring(num)] or args['dados-id' .. tostring(num)],
labelid = args['labelid' .. tostring(num)] or args['rótulo-id' .. tostring(num)],
headerid = args['headerid' .. tostring(num)] or args['cabeçalho-id' .. tostring(num)],
rowid = args['rowid' .. tostring(num)] or args['linha-id' .. tostring(num)]
})
end
end

local function renderNavBar()
local argsName = args.name or args.nome
if not argsName then return end

root
:tag('tr')
:tag('td')
:attr('colspan', '2')
:css('text-align', 'right')
:wikitext(navbar{
argsName,
mini = 1,
})
end

local function renderItalicTitle()
local italicTitle = args['italic title'] and mw.ustring.lower(args['italic title'])
if italicTitle == '' or italicTitle == 'force' or italicTitle == 'forçar' or italicTitle == 'yes' or italicTitle == 'sim' then
root:wikitext(mw.getCurrentFrame():expandTemplate({title = 'Título em itálico'}))
end
end

local function renderTrackingCategories()
if args.decat ~= 'yes' and args.decat ~= 'sim' and args.descat ~= 'yes' and args.descat ~= 'sim' then
if args.child == 'yes' or args.child == 'sim' or args.filha == 'yes' or args.filha == 'sim' then
if args.title or args['título'] then
root:wikitext('[[Categoria:!Páginas que usam predefinições de infocaixas incorporadas com o parâmetro título]]')
end
elseif #(getArgNums('data')) == 0 and #(getArgNums('dados')) == 0 and mw.title.getCurrentTitle().namespace == 0 then
root:wikitext('[[Categoria:!Artigos que usam predefinições de infocaixas sem linhas de dados]]')
end
end
end

local function _infobox()
-- Especifica o layout completo da infobox, com definições específicas
-- caso a infobox seja utilizada com uma filha dentro de outra infobox.
local argsSubbox = args.subbox or args.subcaixa
if args.child ~= 'yes' and args.child ~= 'sim' and args.filho ~= 'yes' and args.filho ~= 'sim' and args.filha ~= 'yes' and args.filha ~= 'sim' then
root = mw.html.create('table')

root
:addClass((argsSubbox ~= 'yes' and argsSubbox ~= 'sim') and 'infobox' or nil)
:addClass(args.bodyclass or args['corpo-classe'])

if argsSubbox == 'yes' or argsSubbox == 'sim' then
root
:css('padding', '0')
:css('border', 'none')
:css('margin', '-3px')
:css('width', 'auto')
:css('min-width', '100%')
:css('font-size', '100%')
:css('clear', 'none')
:css('float', 'none')
:css('background-color', 'transparent')
else
root
:css('width', '22em')
end
root
:cssText(args.bodystyle or args['corpo-estilo'])

renderTitle()
renderAboveRow()
else
root = mw.html.create()

root
:wikitext(args.title or args['título'])
end

renderSubheaders()
renderImages()
renderRows()
renderBelowRow()
renderNavBar()
renderItalicTitle()
renderTrackingCategories()

return tostring(root)
end

local function preprocessSingleArg(argName)
-- Se o argumento exitir e não estiver em brancp, adicioná-lo à tabela de argumentos.
-- Argumentos em branco são tratados como nil para combinar com o comportamento de ParserFunctions.
if origArgs[argName] and origArgs[argName] ~= '' then
args[argName] = origArgs[argName]
end
end

local function preprocessArgs(prefixTable, step)
-- Atribuir os parâmetros aos prefixos dados para a tabela args, em ordem, em conjuntos
-- do tamanho de step especificado. Isto é para prevenir referências etc. de aparecer na
-- ordem errada. A prefixTable deve ser um array que contém tabelas, cada uma com
-- dois campos possíveis, um string "prefix" e uma tabela "depend". A função sempre analisa sintaticamente
-- parâmetros que contêm o string "prefix", mas somente analisa sintaticamente os parâmetros na tabela "depend"
-- se o parâmetro prefix estiver presente não estiver em branco.
if type(prefixTable) ~= 'table' then
error("Valor que não é uma tabela detetado para o prefixo tabela", 2)
end
if type(step) ~= 'number' then
error("Detetado valor de step inválido", 2)
end

-- Obter argumentos sem um sufixo de número, e checar por input ruim.
for i,v in ipairs(prefixTable) do
if type(v) ~= 'table' or type(v.prefix) ~= "string" or (v.depend and type(v.depend) ~= 'table') then
error('Dado de entrada inválido detetado para tabela de prefixo preprocessArgs', 2)
end
preprocessSingleArg(v.prefix)
-- Somente analisar sintaticamente o parâmetro depend caso o parâmetro prefixo estiver presente e não estiver em branco.
if args[v.prefix] and v.depend then
for j, dependValue in ipairs(v.depend) do
if type(dependValue) ~= 'string' then
error('Detetado valor do parâmetro "depend" inválido em preprocessArgs')
end
preprocessSingleArg(dependValue)
end
end
end

-- Obter argumentos com sufixos de números.
local a = 1 -- Variável de contagem.
local moreArgumentsExist = true
while moreArgumentsExist == true do
moreArgumentsExist = false
for i = a, a + step - 1 do
for j,v in ipairs(prefixTable) do
local prefixArgName = v.prefix .. tostring(i)
if origArgs[prefixArgName] then
moreArgumentsExist = true -- Fazer um outro loop caso quaisquer argumenos forem encontrados, mesmo os em branco.
preprocessSingleArg(prefixArgName)
end
-- Processar a tabela depend se o argumento prefix estiver presente não estiver em branco, ou
-- estamos a processar "prefix1" e "prefix" está presente e não está em branco, e
-- se a tabela depend estiver presente.
if v.depend and (args[prefixArgName] or (i == 1 and args[v.prefix])) then
for j,dependValue in ipairs(v.depend) do
local dependArgName = dependValue .. tostring(i)
preprocessSingleArg(dependArgName)
end
end
end
end
a = a + step
end
end

function p.infobox(frame)
-- Se chamado via #invoke, usar os argumentos na predefinição a invocar.
-- Do contrário, para propósitos de testes, presumir que args estão a ser passados diretamente.
if frame == mw.getCurrentFrame() then
origArgs = frame:getParent().args
else
origArgs = frame
end

-- Analisar sintaticamente os prâmetros data na mesma ordem que a antiga {{infobox}} fazia, para que
-- referências etc. sejam exibidas nos locais esperados. Parâmetros que dependem de
-- um outro parâmetro somente são processados se presentes, para evitar
-- referências fantasmas a aparecer nas lista de referências de artigos.
preprocessSingleArg('child')
preprocessSingleArg('filha')
preprocessSingleArg('bodyclass')
preprocessSingleArg('corpo-classe')
preprocessSingleArg('subbox')
preprocessSingleArg('subcaixa')
preprocessSingleArg('bodystyle')
preprocessSingleArg('corpo-estilo')
preprocessSingleArg('title')
preprocessSingleArg('título')
preprocessSingleArg('titleclass')
preprocessSingleArg('título-classe')
preprocessSingleArg('titlestyle')
preprocessSingleArg('título-estilo')
preprocessSingleArg('above')
preprocessSingleArg('acima')
preprocessSingleArg('aboveclass')
preprocessSingleArg('acima-classe')
preprocessSingleArg('abovestyle')
preprocessSingleArg('acima-estilo')
preprocessArgs({
{prefix = 'subheader', depend = {'subheaderstyle', 'subcabeçalho-estilo', 'subheaderrowclass', 'subcabeçalho-linha-classe'}}
}, 10)
preprocessArgs({
{prefix = 'subcabeçalho', depend = {'subheaderstyle', 'subcabeçalho-estilo', 'subheaderrowclass', 'subcabeçalho-linha-classe'}}
}, 10)
preprocessSingleArg('subheaderstyle')
preprocessSingleArg('subcabeçalho-estilo')
preprocessSingleArg('subheaderclass')
preprocessSingleArg('subcabeçalho-classe')
preprocessArgs({
{prefix = 'image', depend = {'caption', 'legenda', 'imagerowclass', 'imagem-linha-classe'}}
}, 10)
preprocessArgs({
{prefix = 'imagem', depend = {'caption', 'legenda', 'imagerowclass', 'imagem-linha-classe'}}
}, 10)
preprocessSingleArg('captionstyle')
preprocessSingleArg('legenda-estilo')
preprocessSingleArg('imagestyle')
preprocessSingleArg('imagem-estilo')
preprocessSingleArg('imageclass')
preprocessSingleArg('imagem-classe')
preprocessArgs({
{prefix = 'header'},
{prefix = 'data', depend = {'label', 'rótulo'}},
{prefix = 'rowclass'},
{prefix = 'rowstyle'},
{prefix = 'rowcellstyle'},
{prefix = 'class'},
{prefix = 'dataid'},
{prefix = 'labelid'},
{prefix = 'headerid'},
{prefix = 'rowid'}
}, 50)
preprocessArgs({
{prefix = 'cabeçalho'},
{prefix = 'dados', depend = {'rótulo', 'label'}},
{prefix = 'linha-classe'},
{prefix = 'linha-estilo'},
{prefix = 'linha-célula-estilo'},
{prefix = 'classe'},
{prefix = 'dados-id'},
{prefix = 'rótulo-id'},
{prefix = 'cabeçalho-id'},
{prefix = 'linha-id'}
}, 50)
preprocessSingleArg('headerclass')
preprocessSingleArg('cabeçalho-classe')
preprocessSingleArg('headerstyle')
preprocessSingleArg('cabeçalho-estilo')
preprocessSingleArg('labelstyle')
preprocessSingleArg('rótulo-estilo')
preprocessSingleArg('datastyle')
preprocessSingleArg('dados-estilo')
preprocessSingleArg('below')
preprocessSingleArg('abaixo')
preprocessSingleArg('belowclass')
preprocessSingleArg('abaixo-classe')
preprocessSingleArg('belowstyle')
preprocessSingleArg('abaixo-estilo')
preprocessSingleArg('name')
preprocessSingleArg('nome')
args['italic title'] = origArgs['italic title'] or origArgs['título itálico'] -- comportamento diferente caso em branco ou em falta
preprocessSingleArg('decat')
preprocessSingleArg('descat')

return _infobox()
end

return p

Menu de navegação