Módulo:Ficha
A
--
-- Este módulo es para implementar en {{Ficha}}
--
local p = {}
local HtmlBuilder = require('Module:HtmlBuilder')
local CategorizacionAByAD = require('Módulo:Categorización de buenos y destacados')
local marco = {}
local args
local root
local anchoImagen = '320px'
function union(t1, t2)
-- devuelve la unión de los valores de dos tablas, como una secuencia
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 depurarVacias(contenido)
if contenido and contenido ~= '' then
return contenido
end
end
local function getArgNums(prefix)
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 anadirfila(rowArgs)
if rowArgs.seccion then
root
.tag('tr')
.tag('th')
.attr('colspan', 3)
.addClass('section')
.addClass(rowArgs.clasefila)
.css('text-align', 'center')
.cssText(rowArgs.estiloseccion or args.estiloseccion)
.wikitext(rowArgs.seccion)
elseif rowArgs.datos then
local fila = root.tag('tr')
fila.addClass(rowArgs.clasefila)
if rowArgs.etiqueta then
fila
.tag('th')
.attr('scope', 'row')
.css('text-align', 'left')
.addClass('label')
.addClass(rowArgs.clasefila)
.cssText (rowArgs.estiloetiqueta or args.estiloetiqueta)
.wikitext(rowArgs.etiqueta)
.done()
end
local datosCelula = fila.tag('td')
if rowArgs.etiqueta then
datosCelula
.attr('colspan', 2)
else
datosCelula
.attr('colspan', 3)
.css('text-align', 'center')
end
datosCelula
.addClass(rowArgs.clase)
.cssText (rowArgs.estilodatos or args.estilodatos)
-- Se añade un salto de línea porque si no se hace así y por ejemplo en los
-- datos hay una lista con asteriscos en el primer elemento se muestra
-- un asterisco.
-- Se trata de un error que ya ocurre con tablas normales sin LUA. Por ejemplo
-- {|
-- | * elemento1
-- * elemento2
-- |}
-- El salto de línea ya se producía en la plantilla Ficha/fila
.wikitext('\n' .. rowArgs.datos)
--.newline()
end
end
local function hacerTitulo() -- Cabecera de la ficha
if not args.titulo then return end
local cabecera = {}
if args.media == 'si' and args.clasetitulo then
cabecera = 'media ' .. args['clasetitulo']
elseif args.media == 'si' then
cabecera = 'media '
elseif args.tipocabecera then
cabecera = 'cabecera ' .. args.tipocabecera
elseif args.clasetitulo then
cabecera = 'cabecera ' .. args.clasetitulo
else
cabecera = 'cabecera '
end
root
.tag('tr')
.tag('th')
.attr('colspan', 3)
.addClass(cabecera)
.css('text-align', 'center')
.cssText( (args.colorfondo or args.colorfondotitulo) and ('background-color:' .. (args.colorfondo or args.colorfondotitulo)) )
.cssText( (args.colortexto or args.colorfondo or args.colorfondotitulo) and ('color:' .. (args.colortexto or 'inherit')) )
.cssText(args.estilotitulo)
.wikitext(args.titulo)
end
local function hacerFilaArriba()
if not args.arriba and not args.titulo2 then return end
root
.tag('tr')
.tag('th')
.attr('colspan', 3)
.addClass(args.clasearribaor or args.clasetitulo2)
.css('text-align', 'center')
.css('font-size', '125%')
.css('font-weight', 'bold')
.cssText(args.estiloarriba or args.estilotitulo2)
.wikitext(args.arriba or args.titulo2)
end
local function hacerPieDeTabla()-- Pie de tabla, aparecerá abajo de la ficha
if not args.piedetabla then return end
root
.tag('tr')
.tag('td')
.attr('colspan', '3')
.addClass(args.clasepiedetabla)
.css('text-align', 'center')
.cssText(args.estilopiedetabla)
.wikitext(args.piedetabla)
end
local function hacerImagenInferior()-- Imagen que aparecerá en la parte inferior de la tabla
if not args.imageninferior then return end
imageninferior = {}
if args['tamañoimageninferior'] == nil or args['tamañoimageninferior'] == '' then
args['tamañoimageninferior'] = anchoImagen
end
if string.find(args.imageninferior, '[{[]') == nil then
imageninferior = ('[[Archivo:' .. args.imageninferior .. '|'.. args['tamañoimageninferior'] .. ']]' )
else
imageninferior = args.imageninferior
end
root
.tag('tr')
.tag('td')
.attr('colspan', '3')
.addClass('imagen ' .. (args.claseimageninferior or '') )
.css('text-align', 'center')
.cssText(args.estiloimageninferior)
.newline()
.wikitext(imageninferior)
.tag('br', {selfClosing = true})
.done()
.tag('div')
.css('display','inline')
.cssText(args.estilopieinferior)
.wikitext(args.pieinferior)
.done()
.newline()
end
local function hacerImagenSuperior()-- Imagen que aparecerá en la parte superior de la tabla
if not args.imagensuperior then return end
if args['tamañoimagensuperior'] == nil or args['tamañoimagensuperior'] == '' then
args['tamañoimagensuperior'] = anchoImagen
end
imagensuperior = {}
if string.find(args.imagensuperior, '[{[]') == nil then
imagensuperior = ('[[Archivo:' .. args.imagensuperior .. '|'.. args['tamañoimagensuperior'] .. ']]' )
else
imagensuperior = args.imagensuperior
end
root
.tag('tr')
.tag('td')
.attr('colspan', '3')
.addClass('imagen ' .. (args.claseimagensuperior or '') )
.css('text-align', 'center')
.cssText(args.estiloimagensuperior)
.newline()
.wikitext(imagensuperior)
.tag('br', {selfClosing = true})
.done()
.tag('div')
.css('display','inline')
.cssText(args.estilopiesuperior)
.wikitext(args.piesuperior)
.done()
.newline()
end
local function hacerSubtitulos()-- Subtítulos de la ficha
if args.subtitulo then
args.subtitulo1 = args.subtitulo
end
if args.clasesubtitulo then
args.clasesubtitulo1 = args.clasesubtitulo
end
local subtitulonumero = getArgNums('subtitulo')
for k, num in ipairs(subtitulonumero) do
anadirfila({
datos = args['subtitulo' .. num],
estilodatos = args['estilosubtitulo' .. num] or args.estilosubtitulo,
clase = args.clasesubtitulo,
clasefila = args['clasesubtitulo' .. num]
})
end
end
local function hacerfilassuperiores()-- filas encima de imagenes laterales
if args.datosup then
args.datosup1 = args.datosup
end
if args.clasedatosup then
args.clasedatosup1 = args.clasedatosup
end
if args.estilodatosup then
args.estilodatosup1 = args.estilodatosup
end
local datosupnumero = getArgNums('datosup')
for k, num in ipairs(datosupnumero) do
anadirfila({
datos = args['datosup' .. num],
estilodatos = args['estilodatosup' .. num],
clase = args.clasedatosup,
clasefila = args['clasedatosup' .. num]
})
end
end
local function hacerImageneslaterales()
-- Imagenes que apareceran arriba de forma geminada por ejemplo escudos y banderas
if args['tamañoimagenizquierda'] == "" or args['tamañoimagenizquierda'] == nil then
args['tamañoimagenizquierda'] = '100px'
end
if args['tamañoimagenderecha'] == "" or args['tamañoimagenderecha'] == nil then
args['tamañoimagenderecha'] = '100px'
end
if args.imagenderecha and args.imagenizquierda then
if args.pieizquierdo then brcondicionalizquierdo = 'br' end
if args.piederecho then brcondicionalderecho = 'br' end
root
.tag('tr')
.tag('td')
--.attr('cellspacing', '0em')
--.attr('padding','0em')
.attr('colspan', '3')
.css('align', 'center')
.tag('table') -- tiene que ir dentro de una tabla para que las filas no lo deformen
.css('width', '100%')
.addClass('mergedrow')
.tag('tr')
.tag('td')
.css('text-align', 'center')
.addClass(args.claseimagenizquierda)
.css('align', 'center')-- Se alinea en el centro horizontal
.css('text-align', 'center') -- Se alinea en el centro horizontal
.css('vertical-align', 'middle')-- Se alinea en el centro vertical
.cssText(args.estiloimagenizquierda)
.wikitext('[[Archivo:' .. args.imagenizquierda .. '|' .. args['tamañoimagenizquierda'] .. ']]' )
.tag(brcondicionalizquierdo)
.tag('div')
.css('display','inline')
.cssText(args.estilopieizquierdo)
.wikitext(args.pieizquierdo)
.done()
.tag('td')
.css('text-align', 'center')-- Se alinea en el centro horizontal
.css('align', 'center')-- Se alinea en el centro horizontal
.css('vertical-align', 'middle')-- Se alinea en el centro vertical
.addClass(args.claseimagenderecha)
.cssText(args.estiloimagenderecha)
.wikitext('[[Archivo:' .. args.imagenderecha .. '|' .. args['tamañoimagenderecha'] .. ']]' )
.tag(brcondicionalderecho)
.tag('div')
.css('display','inline')
.cssText(args.estilopiederecho)
.wikitext(args.piederecho)
.done()
.newline()
elseif args.imagenderecha or args.imagenizquierda then
-- Si solo una de las dos, la imagen que aparezca estará en el centro
imagenL = {}
if args.imagenderecha ~= '' and args.imagenderecha ~= nil then
imagenL = 'imagenderecha'
elseif args.imagenizquierda ~= '' and args.imagenizquierda ~= nil then
imagenL = 'imagenizquierda'
end
pieL = {}
if args.imagenderecha then
pieL = 'piederecho'
elseif args.imagenizquierda then
pieL = 'pieizquierdo'
end
root
.tag('tr')
.tag('td')
.attr('colspan', '3')
.addClass(args['clase' .. imagenL])
.css('text-align', 'center')
.cssText(args['estilo' .. imagenL])
.newline()
.wikitext('[[Archivo:' .. args[imagenL] .. '|'.. args['tamaño'..imagenL] .. ']]' )
.tag('br')
.tag('div')
.css('display','inline')
.cssText(args['estilo' .. pieL])
.wikitext(args[pieL])
.done()
end
end
local function hacerImagenes() -- Puede crear un número infinito de imágenes
if args.imagen then
args.imagen1 = args.imagen
end
if args['tamañoimagen'] then
args['tamañoimagen1'] = args['tamañoimagen']
end
if args['imagenmodooscuro'] then
args['imagenmodooscuro1'] = args['imagenmodooscuro']
end
if args.pie then
args.pie1 = args.pie
end
local imagenums = getArgNums('imagen')
for k, num in ipairs(imagenums) do
local pie = args['pie' .. num]
local flotante = args['imagenflotante' .. num] or false
if args['tamañoimagen'..num] == nil then
args['tamañoimagen'..num] = anchoImagen
end
-- Comprobamos si se ha activado el argumento imagenmodooscuro para esta imagen
local claseInversion = args['imagenmodooscuro' .. num] and 'class=skin-invert-image' or ''
imagen = {}
local cadenaBusqueda = mw.ustring.gsub(args['imagen'..num],'UNIQ','[') -- Para que no de problemas con ciertas plantillas
if mw.ustring.find(cadenaBusqueda, '[{[|]') == nil then -- Comprueba si hay [ o { para no añadir prefijo
imagen = ('[[Archivo:' .. args['imagen' .. num] .. '|'.. args['tamañoimagen' ..num] .. '|' .. claseInversion .. ']]' )
else
imagen = args['imagen'..num]
end
local datos = HtmlBuilder.create().wikitext(imagen)
if pie and not flotante then
datos
.tag('br', {selfClosing = true})
.done()
end
if pie then
datos
.tag('div')
.css('display','inline')
.cssText(args.estilopie)
.wikitext(pie)
.done()
end
anadirfila({
datos = tostring(datos),
estilodatos = args.estiloimagen,
clase = 'imagen ' .. (args.claseimagen or ''),
clasefila = args['claseimagen' .. num]
})
end
end
local function hacerFilas()
local filanum = union(getArgNums('seccion'), getArgNums('datos'))
table.sort(filanum)
for k, num in ipairs(filanum) do
anadirfila({
estilosubtitulo = depurarVacias(args['estilosubtitulo' .. num]),
seccion = depurarVacias(args['seccion' .. num]),
estiloseccion = depurarVacias(args['estilosección' .. num]),
etiqueta = depurarVacias(args['etiqueta' .. num]),
datos = depurarVacias(args['datos' .. num]),
estiloetiqueta = depurarVacias(args['estiloetiqueta' .. num]),
estilodatos = depurarVacias(args['estilodatos' .. num]),
clase = depurarVacias(args['clase' .. num]),
clasefila = depurarVacias(args['clasefila' .. num])
})
end
end
function tieneDatosFila(fila)
-- Función que devuelve true si la fila o grupo de filas (en el caso de
-- secciones) tiene datos.
if fila.tipo == 'sección' or fila.tipo == 'seccion' then
for k, filaSeccion in ipairs(fila) do
if tieneDatosFila(filaSeccion) then
return true
end
end
elseif fila.tipo == 'sucesión' or fila.tipo == 'sucesion' then
if depurarVacias(fila[1]) or depurarVacias(fila['anterior']) or
depurarVacias(fila[3]) or depurarVacias(fila['siguiente']) then
return true
end
else
if depurarVacias(fila[2]) or depurarVacias(fila['datos']) then
return true
end
end
return false
end
function anadirSucesion(argumentosSucesion)
local filaGen = root.tag('tr')
filaGen.css('font-size', '88%')
filaGen.css('text-align', 'center')
local celda
local width
width = '33%'
local celdaGen = filaGen.tag('td').attr('colspan', 3).css('padding', 0)
local tablaSuc = celdaGen.tag('table')
tablaSuc.css('width', '100%')
local fila = tablaSuc.tag('tr')
celda = fila.tag('td')
celda
.css('width', width)
.css('padding', '0.2em 0.1em 0.2em 0')
.css('vertical-align', 'middle')
if argumentosSucesion['estilo fuente'] then
celda
.tag('div')
.css('display','inline')
.css('font-style', argumentosSucesion['estilo fuente'])
.wikitext(argumentosSucesion.anterior)
.done()
else
celda.wikitext(argumentosSucesion.anterior)
end
if argumentosSucesion['año anterior'] then
celda
.tag('br')
.wikitext('(' .. argumentosSucesion['año anterior'] .. ')')
end
celda = fila.tag('td')
celda
.css('width', width)
.css('padding', '0.2em 0.1em')
.css('vertical-align', 'middle')
.css('background-color', argumentosSucesion.color or '#E6E8FA')
celda
.tag('div')
.css('display','inline')
.css('font-weight', 'bold')
.css('font-style', argumentosSucesion['estilo fuente'] or '')
.wikitext(argumentosSucesion.actual or args.titulo)
.done()
if argumentosSucesion['año'] then
celda
.tag('br')
.wikitext('(' .. argumentosSucesion['año'] .. ')')
end
celda = fila.tag('td')
celda
.css('width', width)
.css('padding', '0.2em 0 0.2em 0.1em')
.css('vertical-align', 'middle')
if argumentosSucesion['estilo fuente'] then
celda
.tag('div')
.css('display','inline')
.css('font-style', argumentosSucesion['estilo fuente'])
.wikitext(argumentosSucesion.siguiente)
.done()
else
celda.wikitext(argumentosSucesion.siguiente)
end
if argumentosSucesion['año siguiente'] then
celda
.tag('br')
.wikitext('(' .. argumentosSucesion['año siguiente'] .. ')')
end
end
function hacerFilasTabla(tabla)
-- Función que compone las filas de una tabla bien la ficha o bien una sección de la misma.
local anadidoTituloSeccion = false
for k, fila in ipairs(tabla) do
if tieneDatosFila(fila) then
if fila.tipo == 'sección' or fila.tipo == 'seccion' then
-- Añadir el título de la sección (si está informado)
local tituloSeccion = depurarVacias(fila.titulo) or depurarVacias(fila['título'])
if tituloSeccion then
anadirfila({
estiloseccion = fila['estilotitulo'] or fila['estilotítulo'],
seccion = tituloSeccion
})
end
hacerFilasTabla(fila)
elseif fila.tipo == 'sección desplegable' or fila.tipo == 'seccion desplegable' then -- FALTA
elseif fila.tipo == 'sucesión'or fila.tipo == 'sucesion' then
anadirSucesion({
['anterior'] = depurarVacias(fila[1]) or depurarVacias(fila['anterior']),
['actual'] = depurarVacias(fila['actual']),
['siguiente'] = depurarVacias(fila[3]) or depurarVacias(fila['siguiente']),
['año anterior'] = depurarVacias(fila['año anterior']),
['año'] = depurarVacias(fila['año']),
['año siguiente'] = depurarVacias(fila['año siguiente']),
['estilo fuente'] = depurarVacias(fila['estilo fuente']),
['color'] = depurarVacias(fila['color'])
})
elseif fila.tipo == 'dos columnas' then -- FALTA
elseif fila.tipo == 'tres columnas' then -- FALTA
else -- Etiqueta + Datos o solo Datos
anadirfila({
etiqueta = depurarVacias(fila[1]) or depurarVacias(fila['etiqueta']),
datos = depurarVacias(fila[2]) or depurarVacias(fila['datos']),
estiloetiqueta = fila['estiloetiqueta'] or tabla['estiloetiqueta'],
estilodatos = fila['estilodatos'] or tabla['estilodatos'],
clase = fila['clase'] or tabla['clase'],
clasefila = fila['clasefila'] or tabla['clasefila']
})
end
end
end
end
local function hacerBarraDeNavegacion()-- Crea en la parte inferior un enlace a la plantilla que se de con nombre
if not args.nombre then return end
root
.tag('tr')
.tag('td')
.attr('colspan', '3')
.css('text-align', 'right')
.wikitext(mw.getCurrentFrame():expandTemplate({
title = 'navbar',
args = { args.nombre, mini = 1 }
}))
end
local function hacerBarraWikidata()-- Crea en la parte inferior un enlace al ítem de Wikidata
local enlacePagina = mw.title.getCurrentTitle().prefixedText
local etiquetaPagina = mw.ustring.gsub(enlacePagina,'%s%(.*%)','')
local entidad = args.entidad or mw.wikibase.getEntityIdForCurrentPage()
local textoPie = ""
if (args.child == 'si' or args.integrada == 'sí' or args.wikidata == 'no') or (mw.title.getCurrentTitle().namespace ~= 0 and mw.title.getCurrentTitle().namespace ~= 104 and not args.entidad) then
textoPie = ''
elseif entidad ~= "" and entidad ~= nil then
textoPie = '<div class="plainlinks wikidata-link" style="font-size: 0.85em">[[[d:' .. tostring(entidad) .. '|editar datos en Wikidata]]]</div>'
if (entidad ~= mw.wikibase.getEntityIdForCurrentPage()) and (mw.title.getCurrentTitle().namespace == 0 or mw.title.getCurrentTitle().namespace == 104) then
textoPie = textoPie .. '[[Categoría:Wikipedia:Artículos con fichas que utilizan acceso arbitrario]]'
end
else
textoPie = "<small>'''Página no enlazada a [[Wikidata]]'''\n"..
"* Si no existe en otras Wikipedias: [<span class=plainlinks>[//www.wikidata.org/w/index.php?title=Special:NewItem&site=eswiki&page="..mw.uri.encode(enlacePagina,WIKI) .."&label="..mw.uri.encode(etiquetaPagina,WIKI) .." crea nuevo ítem]]</span>\n"..
"* Si existe en otras Wikipedias: [<span class=plainlinks>[[:d:Special:ItemByTitle|busca ítem para enlazar]]</span>]\n"..
"y añade el enlace en español: ".. enlacePagina ..".</small>"
end
if textoPie ~= '' then
root
.tag('tr')
.tag('td')
.addClass('noprint')
.attr('colspan', '3')
.css('text-align', 'left')
.wikitext(textoPie)
end
end
local function hacerCategoriasSeguimiento()
if args.decat ~= 'si' and #(getArgNums('datos')) == 0 and not args[1] and mw.title.getCurrentTitle().namespace == 0 then
root.wikitext('[[Categoría:Wikipedia:Artículos que usan ficha sin datos en filas]]')
end
if CategorizacionAByAD.hasAnyBadge() == '1' then
root.wikitext(CategorizacionAByAD.badgesCategories())
end
end
function _infobox()
if args.child ~= 'si' and args.integrada ~= 'sí' then
root = HtmlBuilder.create('table')
root -- Estilo de toda la ficha
.addClass('infobox')
.addClass(args.clase)
.cssText('width:22.7em; line-height: 1.4em; text-align:left; padding:.23em') -- Lo mismo que la plantilla:Ficha
.cssText(args.estilo)
if args.estilo and (mw.title.getCurrentTitle().namespace == 10) then -- Para que sólo lo añada en el espacio de nombres plantilla
root.wikitext('[[Categoría:Wikipedia:Fichas con el parámetro estilo]]')
end
hacerTitulo()
hacerFilaArriba()
else
root = HtmlBuilder.create()
if args.titulo then
root.wikitext("'''" .. args.titulo .. "'''")
end
end
hacerSubtitulos()
hacerImagenSuperior()
hacerImageneslaterales()
hacerfilassuperiores()
hacerImagenes()
if not args[1] then
hacerFilas()
else
hacerFilasTabla(args)
end
hacerImagenInferior()
hacerPieDeTabla()
hacerBarraDeNavegacion()
hacerBarraWikidata()
hacerCategoriasSeguimiento()
return mw.getCurrentFrame():extensionTag{ name = 'templatestyles', args = { src = 'Plantilla:Ficha/imagelimit.css' } } .. tostring(root)
end
local function touchParameters(prefixTable, origArgs, step)
-- Analiza los parámetros con los prefijos dados, en orden por lotes lotes y con el tamaño especificado a step.
-- Esto es para evitar referencias etc aparezca en el orden equivocado.
if type(prefixTable) ~= 'table' or type(origArgs) ~= 'table' then
error("Entrada no válida detectada para la función touchParameters. Ambos parámetros deben ser tablas.", 2)
end
if step and type(step) ~= 'number' then
error("Detectado valor no numérico en step.", 2)
end
step = step or 20 -- Si no se le da el tamaño a step, el valor predeterminado es 20.
local temp
local a = 1 -- variable de contador.
local moreArgumentsExist = true
for j,v in ipairs(prefixTable) do
if not type(v) == "string" then
error("Detectado un valor que no es string en el prefijo de la tabla por la función touchParameters.", 2)
end
temp = origArgs[v]
end
while moreArgumentsExist == true do
moreArgumentsExist = false
for i = a, a + step - 1 do
for j,v in ipairs(prefixTable) do
temp = origArgs[v .. tostring(i)]
if temp then
moreArgumentsExist = true
end
end
end
a = a + step
end
end
function p.infobox(frame)
local origArgs
marco = frame
-- Si se llama a través de #invoke, utilice los argumentos pasados a la plantilla de invocación.
-- De lo contrario, para fines de prueba, asume args que se pasan directamente como parámetros.
if frame == mw.getCurrentFrame() then
origArgs = frame:getParent().args
else
origArgs = frame
end
-- Analizar los parámetros de datos en el mismo orden que la plantilla {{ficha}} lo hace, por lo que
-- referencias etc. se mostrarán en los lugares previstos.
local temp
temp = origArgs.titulo
temp = origArgs.arriba
touchParameters({'subtitulo'}, origArgs, 5)
touchParameters({'imagen', 'pie'}, origArgs, 5)
touchParameters({'seccion', 'etiqueta', 'datos'}, origArgs, 20)
temp = origArgs.piedetabla
-- El analizador de funciones considera que una cadena vacía es falsa, por lo que para preservar el anterior
-- comportamiento de {{Ficha}}, debe cambiar los argumentos vacíos a cero, por lo que Lua los considerará
-- que son falsos también (excepto parámetros 'title cursiva', que especifica un comportamiento diferente
-- dependiendo de si está ausente o vacío)
args = {}
for k, v in pairs(origArgs) do
if v ~= '' then
args[k] = v
end
end
return _infobox()
end
return p