Módulo:Navegación
La documentación para este módulo puede ser creada en Módulo:Navegación/doc
-- port a lua de la [[Plantilla:Navegación]]
-- hecho por DennouNeko y traducido por Daisuke
-- == Funciones de ayuda ==
--[[ librerias ]]
local common = require("Module:Common")
local style = require("Module:Styles")
local colors = style.main_colors
if mw.text == nil then mw.text = require("Module:MW.text") end
--[[ Recuperar una lista completa de argumentos como 'lista#', 'estilolista#', 'grupo#' y 'estilogrupo#'
como una tabla de objetos con campos como 'índice', 'lista', 'estilolista', 'grupo' y 'estilogrupo'
en donde 'índice' es el número del nombre del argumento 'lista#'
'lista' e 'índice' son los únicos que siempre están definidos. Los elementos que no se especifiquen estarán vacíos.
Si no se define el argumento 'lista#', los demás elementos que tengan un índice serán ignorados.
La clave del argumento debe coincidir con el número en el nombre de los argumentos. ]]
local function scan_lists(frame)
local idx = {}
local list = {}
local group = {}
local liststyle = {}
local groupstyle = {}
local ret = {}
local s,e,t
for k,v in frame:argumentPairs() do
-- sólo acepta parámetros que no comienzen con ceros
s,e,t = string.find(k, '^estilogrupo([1-9]%d*)$')
if s ~= nil then groupstyle[tonumber(t)] = v end
s,e,t = string.find(k, '^estilolista([1-9]%d*)$')
if s ~= nil then liststyle[tonumber(t)] = v end
s,e,t = string.find(k, '^grupo([1-9]%d*)$')
if s ~= nil then group[tonumber(t)] = v end
s,e,t = string.find(k, '^lista([1-9]%d*)$')
if s ~= nil then
list[tonumber(t)] = v
idx[#idx+1] = tonumber(t)
end
end
table.sort(idx)
for k,v in pairs(idx) do
local tmp = {}
tmp['índice'] = v
tmp['lista'] = list[v]
if common.isset(group[v]) then tmp['grupo'] = group[v] end
if common.isset(liststyle[v]) then tmp['estilo lista'] = liststyle[v] end
if common.isset(groupstyle[v]) then tmp['estilo grupo'] = groupstyle[v] end
ret[#ret+1] = tmp
end
return ret
end
-- == Funciones que genera el documento de elementos ==
--[[ Se genera el incio de la caja, basado en un 'ttype' y en un 'borde' específico. ]]
local function start_box(frame, border, ttype)
local ret = {}
if border == "subgroup" or border == "child" then
-- ya que estamos en una celda de la navegación matriz, debemos cerrarlo con un elemento <div>
ret[#ret+1] = '</div>'
elseif border == "none" then
-- no hay nada que hacer
else
-- uno nuevo, una navegación independiente - se creará un marco a su alrededor
ret[#ret+1] = '<table class="navbox'
if common.isset(frame.args['clase cuerpo']) then ret[#ret+1] = " " .. frame.args['clase cuerpo'] end
ret[#ret+1] = '" cellspacing="0" style="'
if common.isset(colors[ttype]) then ret[#ret+1] = 'background:' .. colors[ttype]['background'] .. ';' end
-- ret[#ret+1] = 'border:1px solid #aaa; padding:1px;width:100%;vertical-align:middle;margin:auto;clear:both;font-size:88%;text-align:center;'
style.add(ret, frame.args['estilo cuerpo'])
style.add(ret, frame.args['estilo'])
ret[#ret+1] = '"><tr><td style="padding: 2px;">'
end
-- La navegación de ahora comienza aquí
ret[#ret+1] = '<table cellspacing="0" class="nowraplinks'
if common.isset(frame.args['título']) and frame.args['estado'] ~= "plain" and frame.args['estado'] ~= "off" then
--TODO: si soporta los parámetrps collapsible y autocollapse, comenta aquí
--ret[#ret+1] = ' collapsible '
ret[#ret+1] = ' mw-collapsible '
if common.isset(frame.args['estado']) then
ret[#ret+1] = frame.args['estado']
else
--ret[#ret+1] = 'autocollapse'
ret[#ret+1] = 'mw-collapsed'
end
end
if border == "subgroup" or border == "child" or border == "none" then
ret[#ret+1] = ' navbox-subgroup" style="'
if common.isset(colors[ttype]) then table.insert(ret, 'background:' .. colors[ttype]['background'] .. ';') end
-- ret[#ret+1] = 'margin:auto;clear:both;font-size:88%;text-align:center;width:100%;vertical-align:middle;'
ret[#ret+1] = 'width: 100%;'
style.add(ret, frame.args['estilo cuerpo'])
style.add(ret, frame.args['estilo'])
ret[#ret+1] = '">'
else
ret[#ret+1] = '" style="width:100%;background:transparent;color:inherit;">'
end
return table.concat(ret)
end
--[[ Terminado la caja, se basa en un 'ttype' y 'borde' específico ]]
local function end_box(frame, border, ttype)
local ret = {""}
ret[#ret+1] = '</table>'
if border == "subgroup" or border == "child" then
-- como cerramos un <div>, abremos otro para comenzar esta navegación child
ret[#ret+1] = '<div>'
elseif border == "none" then
-- no hay nada que hacer
else
-- cerremos la tabla al comenzar un marco
ret[#ret+1] = '</td></tr></table>'
end
return table.concat(ret)
end
--[[ Generar la fila del título: botones 'v(er) • d(iscusión) • e(ditar)' + títulos + '[Expand]'/'[Collapse]'. ]]
local function build_title(frame, border, ttype)
local ret = {""}
if not common.isset(frame.args['título']) then return '' end
table.insert(ret, '<tr>')
if common.isset(frame.args['título grupo']) then
-- en caso de que no haya un grupo para el título
ret[#ret+1] = '<td class="navbox-group" style="'
if common.isset(colors[ttype]) then ret[#ret+1] = 'background:' .. colors[ttype]['grupo'] .. ';' end
ret[#ret+1] = 'padding-left:1em;padding-right:1em;white-space:nowrap;text-align:right;'
style.add(ret, frame.args['estilo base'])
style.add(ret, frame.args['estilo grupo'])
style.add(ret, frame.args['estilo título grupo'])
ret[#ret+1] = '">\n'
ret[#ret+1] = frame.args['título grupo']
ret[#ret+1] = '</td>'
ret[#ret+1] = '<th style="border-left:2px solid '
ret[#ret+1] = common.cv(common.isset(colors[ttype]), colors[ttype]['background'], '#fdfdfd')
ret[#ret+1] = ';width:100%;'
else
-- sin grupo para el título
table.insert(ret, '<th style="')
end
if common.isset(colors[ttype]) then ret[#ret+1] = 'background:' .. colors[ttype]['título'] .. ';' end
ret[#ret+1] = 'text-align:center;'
style.add(ret, frame.args['estilo base'])
style.add(ret, frame.args['estilo título'])
ret[#ret+1] = '"'
-- calcular el colspan para el título
local cs = 2 -- 2 porque cada grupo con el elemnto lista ocupa 2 columnas
if common.isset(frame.args['imagen izquierda']) then cs = cs + 1 end
if common.isset(frame.args['imagen']) then cs = cs + 1 end
if common.isset(frame.args['título grupo']) then cs = cs - 1 end -- si en el caso en que hubiese un título grupo, este ocuparía una celda ya hecha
ret[#ret+1] = ' colspan = "' .. cs .. '"'
ret[#ret+1] = ' class="navbox-title">'
-- agrega navbars y/o padding cuando se necesita
if frame.args['navbar'] == "plain" or frame.args['navbar'] == "off" or border == "subgroup" or border == "child" or border == "none" then
if frame.args['navbar'] == "off" then
if frame.args['estado'] == "plain" then ret[#ret+1] = '<div style="float:right;width:6em;"> </div>' end
else
if frame.args['estado'] ~= "plain" then ret[#ret+1] = '<div style="float:left; width:6em;text-align:left;"> </div>' end
end
else
if frame.args['estado'] == "plain" then ret[#ret+1] = '<div style="float:right;width:6em;"> </div>' end
ret[#ret+1] = '<div style="float:left; width:6em;text-align:left;">'
if frame.args['nombre'] ~= nil then
local args = {}
args[#args+1] = frame.args['nombre']
args['mini'] = '1'
-- TODO: ¿Contruir el navbar sin una plantilla externa?
local q = {""}
q[#q+1] = 'text-align:left;'
style.add(q, frame.args['estilo base'])
style.add(q, frame.args['estilo título'])
q[#q+1] = 'border:none;'
args['fontstyle'] = table.concat(q)
ret[#ret+1] = frame:expandTemplate{title = 'Navbar', args = args}
else
ret[#ret+1] = ' '
ret[#ret+1] = '[[Categoría:Navegaciones sin nombre]]'
end
ret[#ret+1] = '</div>'
end
-- el título comienza aquí
ret[#ret+1] = '<span'
if common.isset(frame.args['clase título']) then ret[#ret+1] = ' class="' .. frame.args['clase título'] .. '"' end
ret[#ret+1] = ' style="font-size:' .. common.cv((border == "subgroup" or border == "child" or border == "none"), '100%', '110%') .. ';">\n'
ret[#ret+1] = frame.args['título']
ret[#ret+1] = '</span>'
ret[#ret+1] = '</th></tr>'
return table.concat(ret)
end
--[[ Genera las filas 'arriba' y 'abajo'.
Regresa la fila generada y se actualiza el valor 'sep' (si es que la separación se va a necesitar). ]]
local function build_above_below(frame, border, ttype, text, rstyle, sep)
local ret = {''}
if common.isset(text) then
if sep then -- si se necesita la separación
table.insert(ret, '<tr style="height: 2px;"><td></td></tr>')
end
-- comienza la fila 'arriba' o 'abajo'
ret[#ret+1] = '<tr>'
ret[#ret+1] = '<td class="navbox-abovebelow" style="'
if common.isset(colors[ttype]) then
-- los parámetros arriba y abajo usan el mismo color por defecto de la tabla 'colores'
ret[#ret+1] = 'background:' .. common.cv((border ~= "subgroup" and border ~= "child"), colors[ttype]['arriba'], colors[ttype]['grupo']) .. ';'
end
ret[#ret+1] = 'padding-left:1em;padding-right:1em;text-align:center;'
style.add(ret, frame.args['estilo base'])
style.add(ret, rstyle)
ret[#ret+1] = '"'
-- calcula y se agrega un colspan (el ancho de la tabla siempre están completo)
local cs = 2
if common.isset(frame.args['imagen izquierda']) then cs = cs + 1 end
if common.isset(frame.args['imagen']) then cs = cs + 1 end
ret[#ret+1] = ' colspan="' .. cs .. '">\n'
-- el contenido de la fila
ret[#ret+1] = text
ret[#ret+1] = '</td></tr>'
sep = true -- ahora se va usar una separación
end
return table.concat(ret),sep
end
--[[ Genera una sola fila de lista. ]]
local function build_row(frame, border, ttype, k, group, list, groupstyle, liststyle)
local ret = {""}
if common.isset(group) then
-- como la lista actual tiene un nombre grupo, se agrega una celda para esta
ret[#ret+1] = '<td class="navbox-group" style="'
if common.isset(colors[ttype]) then
ret[#ret+1] = 'background:' .. common.cv((border ~= "subgroup" and border ~= "child"), colors[ttype]['grupo'], colors[ttype]['subgroup']) .. ';'
end
ret[#ret+1] = 'padding-left:1em; padding-right:1em; white-space:nowrap; text-align:right;'
style.add(ret, frame.args['estilo base'])
if common.isset(frame.args['ancho grupo']) then ret[#ret+1] = 'width:' .. frame.args['ancho grupo'] .. ';' end
style.add(ret, frame.args['estilo grupo'])
style.add(ret, groupstyle)
ret[#ret+1] = '">'
ret[#ret+1] = '<div style="padding:0;">\n'
ret[#ret+1] = group
ret[#ret+1] = '</div></td>'
-- comienza la celda contenida
ret[#ret+1] = '<td style="text-align:left;border-left-width:2px;border-left-style:solid;'
else
-- sin nombre grupo, comienza el contenido listo
ret[#ret+1] = '<td colspan=2 style="'
end
-- un poco complicado, pero esto funciona como XOR
if (frame.args['par impar'] == "swap") ~= ((k % 2) == 0) then
if common.isset(colors[ttype]) then ret[#ret+1] = 'background:' .. colors[ttype]['dark'] .. ';' end
else
ret[#ret+1] = 'background:transparent;'
end
if not common.isset(frame.args['ancho grupo']) then ret[#ret+1] = 'width:100%;' end
ret[#ret+1] = 'padding: 0;'
style.add(ret, frame.args['estilo lista'])
style.add(ret, common.cv((frame.args['par impar'] == "swap") ~= ((k % 2) == 0), frame.args['estilo par'], frame.args['estilo impar']))
style.add(ret, liststyle)
ret[#ret+1] = '" class="navbox-list ' .. common.cv((frame.args['par impar'] == "swap") ~= ((k % 2) == 0), 'navbox-even', 'navbox-odd') .. '">'
-- agregue el <div> con contenido (el mismo <div> que la navegación child tiene cerrado cuando se inica la tabla)
ret[#ret+1] = '<div style="padding:'
if common.isset(frame.args['list' .. k .. 'padding']) then
ret[#ret+1] = frame.args['list' .. k .. 'padding']
elseif common.isset(frame.args['listpadding']) then
ret[#ret+1] = frame.args['listpadding']
else
ret[#ret+1] = '0em 0.25em'
end
ret[#ret+1] = ';">\n'
ret[#ret+1] = list
ret[#ret+1] = '</div></td>'
return table.concat(ret)
end
--[[ Genera el "cuerpo" de la tabla (todo debajo del título) ]]
local function build_body(frame, border, ttype, lists)
local ret = {}
local sep = common.isset(frame.args['título']) -- si hay un título, se agregamos una separación a la primera fila
local imgs = true -- agrega imágenes si se presenta
local irows = common.cv( (#lists > 0), (2 * #lists - 1), 1 )
-- aff la fila 'arriba'
ret[#ret+1],sep = build_above_below(frame, border, ttype, frame.args['arriba'], frame.args['estilo arriba'], sep)
for k,v in pairs(lists) do
if sep then -- add separation if needed
ret[#ret+1] = '<tr style="height: 2px;"><td></td></tr>'
end
table.insert(ret, '<tr>')
-- agrega una imagen a la parte izquierda (si aún no se agrega hasta ahora)
if imgs then
if common.isset(frame.args['imagen izquierda']) then
ret[#ret+1] = '<td style="width:0%;padding:0px 2px 0px 0px;'
style.add(ret, frame.args['estilo imagen izquierda'])
ret[#ret+1] = '" rowspan="' .. irows .. '">' .. frame.args['imagen izquierda'] .. '</td>'
end
end
-- agrega la contenido de la lista
ret[#ret+1] = build_row(frame, border, ttype, v['índice'], v['grupo'], v['lista'], v['estilo grupo'], v['estilo lista'])
-- agrega una imagen a la parte derecha (si aún no se agrega hasta ahora)
if imgs then
if common.isset(frame.args['imagen']) then
ret[#ret+1] = '<td style="width:0%;padding:0px 0px 0px 2px;'
style.add(ret, frame.args['estilo imagen'])
ret[#ret+1] = '" rowspan="' .. irows .. '">' .. frame.args['imagen'] .. '</td>'
end
-- marca las imágenes que agregamos
imgs = false
end
ret[#ret+1] = '</tr>'
sep = true -- ahora la separación se va a utilizar por seguridad
end
ret[#ret+1],sep = build_above_below(frame, border, ttype, frame.args['abajo'], frame.args['estilo abajo'], sep)
return table.concat(ret)
end
-- == Funciones exportadas ==
--[[ Genera y regresa toda la tabla de navegación. ]]
local function buildNavbox(frame)
local template = {}
local border = ""
local ttype = ""
if common.isset(frame.args['borde']) then
border = frame.args['borde']
elseif common.isset(frame.args[1]) then
border = mw.text.trim(frame.args[1])
end
if common.isset(frame.args['tipo']) then
ttype = frame.args['tipo']
end
-- TODO: ¿filtrar los valores de borde y tipo?
-- prepara el primer dato
local lists = scan_lists(frame)
-- build the content
template[#template+1] = start_box(frame, border, ttype)
template[#template+1] = build_title(frame, border, ttype)
template[#template+1] = build_body(frame, border, ttype, lists)
template[#template+1] = end_box(frame, border, ttype)
return table.concat(template)
end
-- [[ Solución para la plantila "Navegación subgrupo" ]]
local function buildNavboxSubgroup(frame)
if not common.isset(frame.args['borde']) then frame.args['borde'] = 'child' end
-- TODO: ¿agregar/modificar/eliminar otros parámetros?
-- llamar la función principal
return buildNavbox(frame)
end
--[[ Principalmente para la depuración, se genera y regresa una tabla de conjuntos de colores
y el valor en las celdas con colores usados como fondos. ]]
local function buildColorTable(frame)
local ret = {""}
table.insert(ret, '<table class="wikitable" style="text-align: center;">')
table.insert(ret, '<caption>List of colors in order from darkest to brigthest one</caption>')
table.insert(ret, '<tr><th>"tipo"</th><th>título</th><th>arriba, abajo</th><th>grupo,<br/>sub-above/below</th><th>sub-group</th><th>dark background</th><th>background</th></tr>')
for k,v in pairs(colors) do
table.insert(ret, '<tr>')
table.insert(ret, '<td>' .. k .. '</td>')
table.insert(ret, '<td style="background:' .. v['título'] .. '">' .. v['título'] .. '</td>')
table.insert(ret, '<td style="background:' .. v['arriba'] .. '">' .. v['arriba'] .. '</td>')
table.insert(ret, '<td style="background:' .. v['grupo'] .. '">' .. v['grupo'] .. '</td>')
table.insert(ret, '<td style="background:' .. v['subgroup'] .. '">' .. v['subgroup'] .. '</td>')
table.insert(ret, '<td style="background:' .. v['dark'] .. '">' .. v['dark'] .. '</td>')
table.insert(ret, '<td style="background:' .. v['background'] .. '">' .. v['background'] .. '</td>')
table.insert(ret, '</tr>')
end
table.insert(ret, '</table>')
return table.concat(ret)
end
-- función de exportación local
return {
['construirnavegación'] = buildNavbox,
['construirplantillanavegación'] = function(frame) return buildNavbox(frame:getParent()) end, -- for wrappers
['construirsubgruponavegación'] = buildNavboxSubgroup,
['construirplantillasubgruponavegación'] = function(frame) return buildNavboxSubgroup(frame:getParent()) end, -- for wrappers
['contruirtablacolor'] = buildColorTable
}
-- [[Categoría:Scripts Lua|{{PAGENAME}}]]