Más idiomas
Más acciones
Módulo para colocar texto en columnas:
- Reparto automático o manual de las líneas. En el reparto se prioriza que la cumplimentación sea según el orden de la columna (así, por ejemplo, se descarta un reparto en dos columnas, más ajustadas por contenido, en que la segunda columna estuviera más llena que la primera).
- Para mejorar la lectura el reparto automático en columnas tiene en cuenta no romper:
- Las líneas que contienen "sublíneas". Así, las "sublíneas" siempre estarán debajo de la línea principal y, por tanto, en la misma columna. Un ejemplo de línea con "sublíneas" sería:
- línea 1
- sublínea 1.1
- sublínea 1.2
- línea 1
- Las agrupaciones de líneas (véase #Agrupando).
- Para el grupo de columnas: se puede definir anchura, encabezado, pie, color de fondo, alineación. La alineación a derecha o izquierda permite que el texto del artículo fluya por el otro lado.
- Para las columnas, se puede definir:
- Que la anchura de cada una sea igual o ajustada al contenido.
- La separación entre columnas.
Para más información véase la plantilla {{XCols}}
.
local p = {}
local SA = require "Module:SimpleArgs"
--local SD = require "Module:SimpleDebug"
--local TNTT = require "Module:TNTTools"
local dir = require "Module:Dir"
local RS = {
Lines = 'Lines',
Header = 'Header',
FreeHeader = 'FreeHeader',
Footer = 'Footer',
NumColumns = 'NumColumns',
NumDisplay = 'NumDisplay',
Width = 'Width',
SameWidth = 'SameWidth',
HAlign = 'HAlign',
VAlign = 'VAlign',
SepCols = 'SepCols',
BgColor = 'BgColor',
HeaderBgColor = 'HeaderBgColor',
FooterBgColor = 'FooterBgColor',
NColsBiggerNLabs = 'NColsBiggerNLabs',
}
local i18n = {
[RS.Lines] = "lines",
[RS.Header] = "header",
[RS.FreeHeader] = "free_header",
[RS.Footer] = "footer",
[RS.NumColumns] = "col_n",
[RS.NumDisplay] = "display_n",
[RS.Width] = "width",
[RS.SameWidth] = "same_width",
[RS.HAlign] = "h_align",
[RS.VAlign] = "v_align",
[RS.SepCols] = "col_sep",
[RS.BgColor] = "bg_color",
[RS.HeaderBgColor] = "header_bg_color",
[RS.FooterBgColor] = "footer_bg_color",
[RS.NColsBiggerNLabs] = "The column number ($1) is greater than the label number ($2)",
}
local I18n = 'XCols'
i18n = SA.loadI18n (I18n, i18n)
local function I18nStr (S, ...)
--return TNTT.GetMsgP (I18n, S, {...})
return SA.I18nStrParams (i18n[S], ...)
end
local function I18nStrArrOr1 (S)
--return TNTT.TabTransMT (I18n, S, 2)
return SA.I18nParamsTab (i18n[S])
end
local lang = mw.language.getContentLanguage().code
local dirh = ''
if dir.isRTL(lang) then
dirh = 'rtl'
else
dirh = 'ltr'
end
function p.MultiCol (splited, NCols, LinesByLin)
local NLines = 0
local LinCol = {}
local WithBreakLine = false
local HeightByLin = {}
local ColWidht = {}
function CountChBegin (s, achar)
local c = 1
for j = 2, #s do
if string.sub(s,j,j) == achar then
c = c + 1
else
break
end
end
return c
end --CountChBegin
function PrepareItems ()
local IsUl = false
local IsFirst = true
local NLinesCol = 0
for k, v in ipairs(LinesByLin) do
NLinesCol = NLinesCol + 1
v = mw.text.trim (v)
if splited then
local z = {}
table.insert (z, v)
LinesByLin[k] = z
else
v = mw.text.split(v, "\n")
LinesByLin[k] = v
end
end
WithBlankLin = false
for k, v in ipairs(LinesByLin) do
if #v > 1 then
WithBlankLin = true
end
local Char = string.sub(v[1],1,1) or ''
if Char == ';' then
local Sep = string.find(v[1],':') or 0
if Sep ~=0 then
local Temp = {}
local Begin = mw.text.trim (string.sub (v[1],1,Sep-1))
local End = mw.text.trim (string.sub (v[1],Sep+1))
table.insert (Temp, Begin)
table.insert (Temp, End)
for kk = 2, #v do
table.insert (Temp, v[kk])
end
LinesByLin[k] = Temp
end
end
end
local TempH = {}
for k, v in ipairs(LinesByLin) do
if #v == 1 then
table.insert (TempH, v)
else
local vz = {}
for kk, vv in ipairs(v) do
local Begin = string.sub(vv, 1, 3)
if (Begin == '---') then
if #vz > 0 then
table.insert (TempH, vz)
vz = {}
end
table.insert (TempH, {vv})
else
table.insert (vz, vv)
end
end
if #vz > 0 then
table.insert (TempH, vz)
end
end
end
LinesByLin = {}
for k, v in ipairs(TempH) do
table.insert (LinesByLin, v)
end
for k, v in ipairs(LinesByLin) do
local Begin = string.sub(v[1], 1, 3)
if (#v == 1) and (Begin == '---') then
WithBreakLine = true
break
end
end
if WithBreakLine then
local LinesByLinTemp = {}
local CurCol = 1
for k, v in ipairs(LinesByLin) do
local Begin = string.sub(v[1], 1, 3)
if (#v == 1) and (Begin == '---') then
if k ~= 1 then
CurCol = CurCol + 1
end
local width = string.sub(v[1], 4)
if width ~= '' then
SA.CheckSize (CurCol, width)
end
table.insert (ColWidht, width)
else
table.insert (LinesByLinTemp, v)
table.insert (LinCol, CurCol)
end
end
NCols = CurCol
LinesByLin = {}
for k, v in ipairs(LinesByLinTemp) do
table.insert (LinesByLin, v)
end
else
if not WithBlankLin then
Levels = {}
local MaxLevel = 0
local MinLevel = 3
for k, v in ipairs(LinesByLin) do
local Begin = string.sub(v[1], 1, 1)
local Begin2 = string.sub(v[1], 2, 2)
function GetLev (achar)
if Begin2 == achar then
return 3
else
return 2
end
end
if Begin == '=' then
Lev = 0
elseif Begin == '*' then
Lev = GetLev ('*')
elseif Begin == '#' then
Lev = GetLev ('#')
elseif Begin == ':' then
Lev = GetLev (':')
else
Lev = 1
end
MinLevel = math.min (MinLevel, Lev)
MaxLevel = math.max (MaxLevel, Lev)
table.insert (Levels, Lev)
end
local c = false
local various = MinLevel ~= MaxLevel
if various then
local LinesByLinTemp = {}
local Lines = {}
for k, v in ipairs(LinesByLin) do
if Levels[k] == MinLevel then
if #Lines == 0 then
table.insert (Lines, v[1])
else
table.insert (LinesByLinTemp, Lines)
Lines = {v[1]}
end
else
table.insert (Lines, v[1])
end
end
table.insert (LinesByLinTemp, Lines)
LinesByLin = {}
for k, v in ipairs(LinesByLinTemp) do
table.insert (LinesByLin, v)
end
end
end
for k, v in ipairs(LinesByLin) do
table.insert (LinCol, 1)
local h = 0
for kk, vv in ipairs(v) do
local HByL = 0
if kk == 1 then
local Char = string.sub(vv,1,1) or ''
if Char == '=' then
local HH = {2, 1.8, 1.38, 1.28, 1.2}
local c = CountChBegin (vv, '=')
HByL = HH[c]
elseif (Char == ';') or (Char == '*') then
HByL = 0.8
elseif #v > 1 then
local Char = string.sub(v[2],1,1) or ''
if (Char == '*') or (Char == '#') or (Char == ':') then
HByL = 1
else
HByL = 0.8
end
else
HByL = 1
end
elseif kk == #v then
HByL = 1
else
HByL = 0.8
end
h = h + HByL
end
table.insert (HeightByLin, h)
NLines = NLines + h
end
end
end --PrepareItems
function SetColToLines ()
local AbsLinesPerCol = 0
function CalcLinesPerCol (L,C)
AbsLinesPerCol = L/C
end
CalcLinesPerCol (NLines, NCols)
local DoItN = 0
local LinesForDo = NLines
local ColsForDo = NCols
local CurrCol = 1
for k, v in ipairs(LinesByLin) do
local fornext = false
if (CurrCol < NCols) and (((AbsLinesPerCol - DoItN) + (HeightByLin[k]/2)) < ((DoItN + HeightByLin[k]) - AbsLinesPerCol)) then
LinesForDo = LinesForDo - DoItN
CalcLinesPerCol (LinesForDo, ColsForDo-1)
CurrCol = CurrCol + 1
DoItN = HeightByLin[k]
ColsForDo = ColsForDo - 1
else
DoItN = DoItN + HeightByLin[k]
end
LinCol[k] = CurrCol
end
end --SetColToLines
function TheItems ()
local IsUl = 0
local IsUlIntra = false
local LastWasUl = false
local IsOl = 0
local IsOlIntra = false
local LastWasOl = false
local IsDl = false
local IsDlx = false
local IsDlIntra = false
local LastWasDl = false
local Lines = {}
local vv = ''
local Result = {}
local CurrCol = 1
function SplitChBegin0 (k, i, achar)
local s = LinesByLin[k][i]
local c = 1
for j = 2, #s do
if string.sub(s,j,j) == achar then
c = c + 1
else
break
end
end
return mw.text.trim (string.sub(s,c+1)), c
end --SplitChBegin0
function SplitChBegin (k, i, achar)
local s, c = SplitChBegin0 (k, i, achar)
LinesByLin[k][i] = '<li>'..s..'</li>'
return c
end --SplitChBegin
function WithHeader (k, i)
local s, c = SplitChBegin0 (k, i, '=')
local cc = 0
for j = #s, 1, -1 do
if string.sub(s,j,j) == '=' then
cc = cc + 1
else
break
end
end
s = string.sub (s,1,#s-cc)
LinesByLin[k][i] = '<h'..c..'>'..s..'</h'..c..'>'
end --WithHeader
function AddClose (num, achar)
for i = 1, num do
vv = vv..'</'..achar..'l>'
end
end --AddClose
function OnEnd ()
if IsUl > 0 then
AddClose (IsUl, 'u')
IsUl = 0
elseif IsOl > 0 then
AddClose (IsOl, 'o')
IsOl = 0
elseif IsDlx then
vv = vv..'</dl>'
IsDlx = false
elseif IsDl then
vv = vv..'</dl>'
IsDl = false
end
end --OnEnd
for k, v in ipairs(LinesByLin) do
if #v ~= 1 then
vv = vv..'<p>'
end
for i, j in ipairs(LinesByLin[k]) do
function BetweenAny (What)
LinesByLin[k][i] = '<'..What..'>'..string.sub(LinesByLin[k][i], 2)..'</'..What..'>'
end
function BeginUlOrOlOrDl (What)
LinesByLin[k][i] = '<'..What..'l>'..LinesByLin[k][i]
end
function EndUlOrOlOrDl (What)
LinesByLin[k][i] = '</'..What..'l>'..LinesByLin[k][i]
end
function BeginOrEndUlOrOl (IniV, NewV, achar)
local IsBegin = IniV < NewV
local s = ''
if IsBegin then
for k = 1, NewV-IniV do
s = s..'<'..achar..'l>'
end
else
for k = 1, (IniV-NewV)-1 do
s = s..'</'..achar..'l>'
end
EndUlOrOlOrDl (achar)
end
LinesByLin[k][i] = s..LinesByLin[k][i]
end --BeginOrEndUlOrOl
local Char = string.sub(LinesByLin[k][i],1,1) or ''
if Char == '*' then
local c = SplitChBegin (k, i, '*')
if IsUl ~= c then
BeginOrEndUlOrOl (IsUl, c, 'u')
IsUl = c
end
IsUlIntra = i > 1
elseif Char == '#' then
local c = SplitChBegin (k, i, '#')
if IsOl ~= c then
BeginOrEndUlOrOl (IsUl, c, 'o')
IsOl = c
end
IsOlIntra = i > 1
elseif Char == '=' then
OnEnd ()
WithHeader (k, i)
elseif Char == ';' then
BetweenAny ('dt')
BeginUlOrOlOrDl ('d')
IsDlx = true
elseif Char == ':' then
BetweenAny ('dd')
if not IsDl then
BeginUlOrOlOrDl ('d')
end
IsDl = true
IsDlIntra = i > 1
else
if #v == 1 then
LinesByLin[k][i] = '<p>'..LinesByLin[k][i]..'</p>'
elseif i ~= #LinesByLin[k] then
LinesByLin[k][i] = LinesByLin[k][i]..'<br>'
end
if IsUl > 0 then
BeginOrEndUlOrOl (IsUl, 0, 'u')
IsUl = 0
end
if IsOl > 0 then
BeginOrEndUlOrOl (IsUl, 0, 'o')
IsOl = 0
end
if IsDl then
EndUlOrOlOrDl ('d')
end
if IsDlx then
LinesByLin[k][i] = '<dd>'..LinesByLin[k][i]..'</dd>'
end
IsUlIntra = false
IsOlIntra = false
IsDlIntra = false
end
--revised intralin
if vv ~= '' then
if IsUl > 0 then
vv = vv..LinesByLin[k][i]
if (i < #LinesByLin[k]) and ((LinesByLin[k][i+1] == '') or (string.sub(LinesByLin[k][i+1],1,1) ~= '*')) then
vv = vv..'</ul>'
IsUl = IsUl - 1
IsUlIntra = false
LastWasUl = true
end
elseif IsOl > 0 then
vv = vv..LinesByLin[k][i]
if (i < #LinesByLin[k]) and ((LinesByLin[k][i+1] == '') or (string.sub(LinesByLin[k][i+1],1,1) ~= '#')) then
vv = vv..'</ol>'
IsOl = IsOl - 1
IsOlIntra = false
LastWasOl = true
end
elseif IsDl then
vv = vv..LinesByLin[k][i]
if (i < #LinesByLin[k]) and ((LinesByLin[k][i+1] == '') or (string.sub(LinesByLin[k][i+1],1,1) ~= ':')) then
vv = vv..'</dl>'
IsDl = false
IsDlIntra = false
LastWasDl = true
end
elseif LastWasUl then
vv = vv..LinesByLin[k][i]
LastWasUl = false
elseif LastWasOl then
vv = vv..LinesByLin[k][i]
LastWasOl = false
elseif LastWasDl then
vv = vv..LinesByLin[k][i]
LastWasDl = false
else
vv = vv..LinesByLin[k][i]
end
else
vv = LinesByLin[k][i]
end
end
--revised lin with lines
if IsUlIntra then
AddClose (IsUl, 'u')
IsUl = 0
IsUlIntra = false
end
if IsOlIntra then
AddClose (IsOl, 'o')
IsOl = 0
IsOlIntra = false
end
if IsDlx then
vv = vv..'</dl>'
IsDlx = false
end
if IsDlIntra then
vv = vv..'</dl>'
IsDl = false
IsDlIntra = false
end
if #v ~= 1 then
vv = vv..'</p>'
end
local IsLastLine = (k == #LinesByLin)
if IsLastLine or (CurrCol ~= LinCol[k+1]) then
if not IsLastLine then
CurrCol = LinCol[k+1]
end
OnEnd ()
if vv ~= '' then
table.insert(Result, vv)
vv = ''
end
end
end
return Result
end --TheItems
PrepareItems()
if (not WithBreakLine) then
SetColToLines ()
end
return TheItems (true), NCols, ColWidht
end --MultiCol
function p.MultiColX (splited, width, same_width, sep_cols, NCols, Lines, h_align, v_align, header, footer, bg_color, free_header, header_bg_color, footer_bg_color)
Lines, NCols, ColWidht = p.MultiCol (splited, NCols, Lines)
local col_width = ''
if same_width then
col_width = math.floor(100/NCols)..'%'
end
local td = {}
local s = mw.html.create("table")
function AddAny (S, IsHeader, Color)
if (S ~= nil) and (S ~= '') then
local tr = s:newline():tag('tr')
if Color ~= nil then
tr: css ('background-color', Color)
end
local td = tr:newline():tag('td')
:attr('colspan', NCols)
if Color ~= nil then
td: css ('padding-right', '0.3em')
td: css ('padding-left', '0.3em')
td: css ('padding-top', '0.2em')
td: css ('padding-bottom', '0.2em')
end
if IsHeader then
local d = td:newline():tag('div')
:addClass ('center')
:css ('width', 'auto')
:css ('margin-left', 'auto')
:css ('margin-right', 'auto')
:wikitext ( "'''"..S.."'''")
else
S = mw.text.split (S, "\n")
S = table.concat(S, '<br>')
td :wikitext (S)
end
end
end
s: attr ('direction', dirh)
if h_align ~= nil then
s: attr ('align', h_align)
if h_align ~= 'center' then
s: css ('padding-left', '8px')
s: css ('padding-right', '8px')
if h_align == 'right' then
s: css ('margin-left', '12px')
elseif h_align == 'left' then
s: css ('margin-right', '12px')
end
end
end
if width ~= nil then
s: css ('width', width)
end
if bg_color ~= nil then
s: css ('background-color', bg_color)
s: css ('padding-right', sep_cols)
s: css ('padding-left', sep_cols)
end
AddAny (header, true, header_bg_color)
AddAny (free_header, false, header_bg_color)
local tr = s:newline():tag('tr')
if v_align ~= nil then
tr:attr ('valign', v_align)
end
for k = 1, NCols do
td[k] = tr:newline():tag('td')
if same_width then
td[k]:css ('width', col_width)
elseif (#ColWidht > 0) and (ColWidht[k] ~= '') then
td[k]:css ('width', ColWidht[k])
end
local AddRight = false
local AddLeft = false
if NCols > 1 then
if k == 1 then
if dir.isRTL(lang) then
AddLeft = true
else
AddRight = true
end
elseif k == NCols then
if dir.isRTL(lang) then
AddRight = true
else
AddLeft = true
end
else
AddRight = true
AddLeft = true
end
end
if AddRight then
td[k] :css ('padding-right', sep_cols)
end
if AddLeft then
td[k] :css ('padding-left', sep_cols)
end
td[k]:wikitext (Lines[k])
end
AddAny (footer, false, footer_bg_color)
return tostring (s)
end --MultiColX
function p.MainVals (args, Required)
local lines = ''
if Required then
lines = SA.RStr_Par (args, I18nStrArrOr1(RS.Lines))
else
lines = SA.Str_Par (args, I18nStrArrOr1(RS.Lines))
end
local NLines = 0
local splited = false
if lines ~= nil then
lines = mw.text.split(mw.text.trim(lines), "\n\n")
NLines = #lines
if NLines == 1 then
lines = mw.text.split (lines[1], "\n")
NLines = #lines
splited = true
end
end
local NCols = SA.PosInt_Par (args, I18nStrArrOr1(RS.NumColumns), 1, 1, 10)
local width = SA.Size_Par (args, I18nStrArrOr1(RS.Width), true, {perc={20,100},em={12,119},px={200,1900}})
local same_width = SA.Bool_Par (args, I18nStrArrOr1(RS.SameWidth), false)
local sep_cols = SA.Size_Par (args, I18nStrArrOr1(RS.SepCols), false, {em={0.6,2.2},px={9,36}}, '0.6em')
local h_align = SA.HAlign_Par (args, I18nStrArrOr1(RS.HAlign))
local v_align = SA.VAlign_Par (args, I18nStrArrOr1(RS.VAlign), 'top')
local header = SA.Str_Par (args, I18nStrArrOr1(RS.Header))
local footer = SA.Str_Par (args, I18nStrArrOr1(RS.Footer))
return splited, NLines, lines, NCols, width, same_width, sep_cols, h_align, v_align, header, footer
end --MainVals
function p.main (frame)
local args,NArgs = SA.GetArgs (frame)
if NArgs == 0 then return end
local splited, NLines, Lines, NCols, width, same_width, sep_cols, h_align, v_align, header, footer, bg_color, free_header, header_bg_color = p.MainVals (args, true)
if NCols > NLines then
error (I18nStr (RS.NColsBiggerNLabs, NCols, NLines))
else
local bg_color = SA.Str_Par (args, I18nStrArrOr1(RS.BgColor))
local free_header = SA.Str_Par (args, I18nStrArrOr1(RS.FreeHeader))
local header_bg_color = SA.Str_Par (args, I18nStrArrOr1(RS.HeaderBgColor))
local footer_bg_color = SA.Str_Par (args, I18nStrArrOr1(RS.FooterBgColor))
return p.MultiColX (splited, width, same_width, sep_cols, NCols, Lines, h_align, v_align, header, footer, bg_color, free_header, header_bg_color, footer_bg_color)
end
end --main
return p