Vés al contingut

Mòdul:Ficha

De la Viquipèdia, l'enciclopèdia lliure
--
-- Este módulo es para implementar en {{Ficha}}
--
 
local p = {}
 
local HtmlBuilder = require('Mòdul:HtmlBuilder')
local marco = {} 
local args
local root
local anchoImagen = '245px' 
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(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(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')
              .css('background-color', args.colorfondo or args.colorfondotitulo or 'transparent')
              .css('color', args.colortexto or 'black')
              .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(args.claseimageninferior)
                .css('text-align', 'center')
                .cssText(args.estiloimageninferior)
                .newline()
                .wikitext(imageninferior)
                .tag('br', {selfClosing = true})
                    .done()
                .tag('span')
                    .cssText(args.estilopieinferior)
                    .wikitext(args.pieinferior)
                    .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(args.claseimagensuperior)
                .css('text-align', 'center')
                .cssText(args.estiloimagensuperior)
                .newline()
                .wikitext(imagensuperior)
                .tag('br', {selfClosing = true})
                    .done()
                .tag('span')
                    .cssText(args.estilopiesuperior)
                    .wikitext(args.piesuperior)
                    .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
      
      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')
                .css('background-color', 'transparent')
                .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('br')
                .tag('span')
                .cssText(args.estilopieizquierdo)
                .wikitext(args.pieizquierdo)
            .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
                .css('background-color', 'transparent')
                .addClass(args.claseimagenderecha)
                .cssText(args.estiloimagenderecha)       
                .wikitext('[[Archivo:' .. args.imagenderecha .. '|' .. args['tamañoimagenderecha'] .. ']]' )
                .tag('br')
                .tag('span')
                .cssText(args.estilopiederecho)
                .wikitext(args.piederecho)
                .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('span')
                .cssText(args['estilo' .. pieL])
                .wikitext(args[pieL])
    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.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
        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] .. ']]' )
            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('span')
                    .cssText(args.estilopie)
                    .wikitext(pie)
        end
        anadirfila({
            datos = tostring(datos),
            estilodatos = args.estiloimagen,
            clase = args.claseimagen,
            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 fila = root.tag('tr')
    fila.css('font-size', '88%')
    fila.css('text-align', 'center')
    
    local celda
    local width
    
    width = '33%'
    
    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('span')
                    .css('font-style', argumentosSucesion['estilo fuente'])
                    .wikitext(argumentosSucesion.anterior)
    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('span')
              .css('font-weight', 'bold')
              .css('font-style', argumentosSucesion['estilo fuente'] or '')
              .wikitext(argumentosSucesion.actual or args.titulo)
              
    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('span')
                    .css('font-style', argumentosSucesion['estilo fuente'])
                    .wikitext(argumentosSucesion.siguiente)
    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 wikibase = require('Módulo:Wikibase')
    local enlacePagina = mw.title.getCurrentTitle().text 
    local etiquetaPagina = mw.ustring.gsub(enlacePagina,'%s%(.*%)','') 
    local entidad = args.entidad or wikibase.id()
    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 = '<small>[<span class= plainlinks>[[d:' .. tostring(entidad) .. '|editar datos en Wikidata]]</span>]</small>'
        if args.entidad 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&nbsp;nuevo&nbsp;ítem]]</span>\n"..
"* Si existe en otras Wikipedias: [<span class=plainlinks>[[:d:Special:ItemByTitle|busca&nbsp;ítem&nbsp;para&nbsp;enlazar]]</span>]\n"..
"y añade el enlace en español: ".. enlacePagina ..".</small>"
    end
    if textoPie ~= '' then
    	root
        	.tag('tr')
	            .tag('td')
                	.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
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 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 sting 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