Module:Iteration/sandbox
CodeDiscussionEditHistoryLinksLink count Subpages:DocumentationTestsResultsSandboxLive code All modules
{{=}}
for title = "="
The module uses frequently the template
This module contains the functions for different templates, solving their iteration problem
The MediaWiki template coding does not support the repetitive processing of a parameter set, which leads often to a very primitive and long chain of parameter checks in the kind of:
{{#if:{{{1|}}} | perform an action with parameter 1 }}
{{#if:{{{2|}}} | perform an action with parameter 2 }}
{{#if:{{{3|}}} | perform an action with parameter 3 }}
{{#if:{{{4|}}} | perform an action with parameter 4 }}
•••
•••
{{#if:{{{33|}}} perform an action with parameter 33 }}
with the disadvantage that such a construct will fail as soon as there comes a 34nd parm.
I always thought that with Lua and its for
loops this iterations should be possible, somehow. After long searching without any success and without an idea how to perform it, I asked at several forums and got finally from User:Trappist the monk the helping hint to solve it with a control structure like:
local out = {}
for i, v in ipairs (args) do
table.insert (out, frame:expandTemplate{ title = title, args = v })
end
return table.concat (out)
The functions contained therein are from very simple, just one parameter to pass, to more complicated ones, where e.g. a pair of parameters needs kind of a flip-flop switch when always a tuple of e.g. an item and its correlated text needs to be passed.
When there are tuples, triples etc., the table.insert
occurs, when the last element is processed; this performs problems when the last group is incomplete – it should be finished with empty values to trigger the table.insert
. The check with table.maxn
seems not to work correctly?
This problem is solved differently, for the function attribs
with a primitive workaround.
Namespace lists
[edit]There are special lists for some namespaces:
- Filelist - for items of the namespace 6 (File:)
- Userlist - for items of the namespace 2 (User:)
- Linklist - for items of the namespace
0(main) — not yet - Templist - for items of the namespace
10(Template:) — not yet - Cat-list - for items of the namespace
14(Category:) — not yet - Mod-list - for items of the namespace
828(Module:) — not yet
Filelist
[edit]File list templates
[edit]The three templates {{Ifim}}
, {{Ifim1}}
and {{Ifimt}}
avoid to display the file itself as an |other version=
.
There are currently five templates creating file lists with the function:filelist
{{Other versions}}
a vertical list (without initial){{Filelist}}
a horizontal list (without initial){{Derivative versions}}
a vertical list{{Derived from}}
a vertical list{{File}}
a horizontal list
All these templates are autoreferencing, and the support also the |gallery=
option.
Other file lists
[edit]The function:svglang
creates a list of just file_names and language_codes, for:
-
{{Svg lang}}
{{Lang gallery}}
{{Multilingual SVG diagrams}}
Much more is created by the function:ownbased
for the template:
{{Own based}}
which will handle in the majority of cases just one file, but can serve an unlimited number.
This list can be controlled by the user to be displayed either horizontally or vertically.
{{Attribs}}
The template works, whether there is a user assigned for a file, or one filename follows another.
{{Emoji}}
The template displays a line of SVG emojis; Unicode characters/emojis can be displayed with the function emodis
or emotab
.
Variable iterations
[edit]A very simple iteration, usable for everything, is performed by function:iterate
- used by e.g.
{{Image extracted}}
,{{Image translated}}
,
More usable is the function:iteration
for transclusions of a template with:
- a number of positional parameters which can change at each transclusion, and
- a number of positional parameters which are the same for all transclusions.
See template {{Iterate}}
.
The function:loop
is used by {{Repeat}}
.
samefile
function
[edit]When the name of one of the files is the same as the first one, it is enough to reference it with its extension after a dot, e.g. just ".jpeg". The most standard extensions can be abbreviated, e.g. ".j" will be sufficient for ".jpg" (only for lower case!).
The function incrhx
increments a hexadecimal number (parm 1) by a decimal number (parm 2).
Valid numbers are assumed, no checking occurs!
When parameter 2 is preceded by a minus, the first number is decremented by the second one.
Userlist
[edit]- Userlist:
{{Userlist}}
with many formatting parameters
Linklist
[edit]Templist
[edit]Other iterations
[edit]- Langlist:
- Colorbox:
{{ColorString}}
and other color box templates - Legends :
{{Legtab}}
combines single{{Legend}}
s - Tleparms: the metatemplate
{{Tle}}
displays the parameter usage of a template - Navigate:
{{Navcat}}
navigates through color categories - Showname:
{{Showname}}
helper template, for parameter tests - Emodis :
{{Emoji}}
displays (one or many) Unicode characters
- The function
emodis
displays Unicode characters / emojis; it can care for newlines, while - The function
emotab
displays a table of files / emojis.
Code
-- This module contains the functions for different templates, solving their iteration problems.
local format = string.format
local p = {}
-- for Template:Ifim
function p.ifim1 (frame)
local ppar = mw.getCurrentFrame(): getParent().args;
local otab = {};
local p1 = ppar.p1 or "";
local p2 = ppar.p2 or "";
local p3 = ppar.p3 or "";
local p4 = ppar.p4 or "";
local p5 = ppar.p5 or "";
local fn = ppar.fn or "";
for _, v in ipairs(ppar) do
table.insert(otab, frame:expandTemplate{ title = "Ifim1", args = { v, p1, p2, p3, p4, p5, n= fn } });
end
return table.concat (otab)
end -- function ifim
-- for Template:Ifimc
function p.ifim2 (frame)
local ppar = mw.getCurrentFrame(): getParent().args;
local otab = {};
local p1 = ppar.p1 or "";
local p2 = ppar.p2 or "";
local p3 = ppar.p3 or "";
local p4 = ppar.p4 or "";
for _, v in ipairs(ppar) do
table.insert(otab, frame:expandTemplate{ title = "Ifim2", args = { v, p1, p2, p3, p4, v } });
end
return table.concat (otab)
end -- function ifim2
-- for Template:Ifimt (param pairs)
function p.ifimt (frame)
local ppar = mw.getCurrentFrame(): getParent().args;
local otab = {};
local v1 = "";
local p1 = ppar.p1 or "";
local p2 = ppar.p2 or "";
local p3 = ppar.p3 or "";
local p4 = ppar.p4 or "";
for _, v in ipairs(ppar) do
if v1 == "" then
v1 = mw.text.trim( v );
else
table.insert(otab, frame:expandTemplate{ title = "Ifim2", args = { v1, p1, p2, p3, p4, v } });
v1 = "";
end
end
if v1 ~= "" then
table.insert(otab, frame:expandTemplate{ title = "Ifim2", args = { v1, p1, p2, p3, p4, "" } }); -- last elem
end
return table.concat (otab)
end -- function ifimt
-------------------------------------------------------
-- helper function for: ownbased, and filelist
local function samefile ( fnam, numb, frst )
local name = mw.text.trim( fnam ) or ""
if mw.ustring.sub(name, 1, 1) == "."
then
local nsnr = tonumber( mw.title.getCurrentTitle().namespace );
local page = mw.title.getCurrentTitle().text;
local part = "Example" -- default name
if nsnr == 6 or nsnr == 7
then local parts = mw.text.split(page , '.', true)
local upTo = #parts - 1 -- copied from Module:File
part = table.concat(parts, '.', 1, math.max(upTo, 1))
end
if name == "." then name = part .. ".png";
elseif name == ".p" then name = part .. ".png";
elseif name == ".j" then name = part .. ".jpg";
elseif name == ".g" then name = part .. ".gif";
elseif name == ".s" then name = part .. ".svg";
elseif name == ".t" then name = part .. ".tif";
elseif name == ".x" then name = part .. ".xcf"; -- exotics:
elseif name == ".d" then name = part .. ".djvu";
elseif name == ".m" then name = part .. ".mid";
elseif name == ".o" then name = part .. ".ogg";
elseif name == ".v" then name = part .. ".wav";
elseif name == ".w" then name = part .. ".webp";
else name = part .. name;
end
elseif name == "" or name == "*"
then
local nsnr = tonumber( mw.title.getCurrentTitle().namespace );
local page = mw.title.getCurrentTitle().text;
if tonumber( numb ) == 1
then name = "Example.svg";
if nsnr == 6 or nsnr == 7
then name = page;
end
else name = mw.text.trim( frst );
if name == "" or name == "*"
or mw.ustring.sub(name, 1, 1) == "."
then name = "Example.svg";
if nsnr == 6 or nsnr == 7
then name = page;
end
end
end
end
return name;
end -- function samefile
---++++++++++++++++++++++++++++++++++++++++++++++++++++
-- simple iterations - without many params
function p.iterate (frame)
local trim = mw.text.trim
local insert = table.insert
local ppar = mw.getCurrentFrame():getParent().args
local expand = frame.expandTemplate
local gpar = frame.args -- global parms
local titl = gpar[1] or '' -- template name
local var1 = gpar[2] or '' -- positional p1
local var2 = gpar[3] or '' -- positional p2
local otab = {}
for _, v in ipairs(ppar) do
insert(otab, expand(frame, { title = titl, args = { trim(v), var1, var2 } }))
end
return table.concat(otab)
end -- function iterate
-- more iterations - for params, param pairs, or n-tupels
function p.iteration (frame)
local insert = table.insert
local trim = mw.text.trim
local ppar = mw.getCurrentFrame():getParent().args
local expand = frame.expandTemplate
local gpar = frame.args -- global parms
local vmax = tonumber(gpar.n) or 2 -- tuple number (default = 2)
local vnum = vmax + 1 -- additional not-changing params
local titl = '' -- template name
local ptab = {} -- parameters
for i, p in ipairs(gpar) do
p = trim(p)
if i == 1 then
titl = p
else
ptab[vnum] = p
vnum = vnum + 1
end
end
vnum = 1
local otab = {} -- output
for _, v in ipairs(ppar) do
ptab[vnum] = trim(v)
vnum = vnum + 1
if vnum > vmax then
insert(otab, expand(frame, { title = titl, args = ptab }))
vnum = 1
end
end
return table.concat(otab)
end -- function iteration
-- for different templates, for general use, e.g. Emoji
function p.parlst(frame)
local trim = mw.text.trim
local gpar = frame.args -- global parms
local template = trim(gpar.temp or '')
if template ~= '' then
local insert = table.insert
local expand = frame.expandTemplate
local ff = trim(gpar.ff or '') -- inbetween ?
if ff == '' then ff = nil end
local pf = {
pf = trim(gpar.pf or '')
}
local nocat = trim(gpar.nocat or '')
local args = {
nocat = nocat ~= '' and nocat or nil
}
for k, v in pairs(gpar) do
v = trim(v)
if v ~= '' then args[k] = v end
end
local count = tonumber(args[1] or '')
local otab = {}
for i = 1, (count or 1) do -- default: go 1× for nil
if ff then insert(otab, expand(frame, { title = ff, args = pf })) end
if count then args[1] = i - 1 end
insert(otab, expand (frame, { title = template, args = args } ))
end
return table.concat(otab)
end
end -- function parlst
-- global function for one filename
function p.filename (frame)
local gpar = frame.args -- global parm
return samefile(mw.text.trim(gpar[1] or ''), 1 )
end -- function filename
-- for Template:Own based (one filename which is '.')
function p.ownbasby (frame)
local gpar = frame.args -- global parm
return frame:expandTemplate{
title = 'F',
args = {
samefile(gpar[1] or '.', 1),
by = mw.text.trim(gpar[2] or '')
}
}
end -- function ownbasby
-- for Template:Own based (horizontal - but vertical when "b1=")
function p.ownbased (frame)
-- local lpar = parm -- local parms
-- local gpar = frame.args -- global parms
local ppar = mw.getCurrentFrame(): getParent().args;
local btab = {};
local dtab = {};
local htab = {};
local itab = {};
local ltab = {};
local ntab = {};
local otab = {};
local qtab = {};
local rtab = {};
local ttab = {};
local utab = {};
local Ctab = {};
local by0 = ppar.b or ppar.by or ppar.u or ppar.user or "";
local dis = ppar.d or ppar.dis or ppar.display or "";
local hil = ppar.h or ppar.hilite or "";
local lng = ppar.i or ppar.lang or "";
local wik = ppar.l or ppar.w or ppar.wiki or "";
local nam = ppar.n or ppar.name or "";
local opt = ppar.o or ppar.opt or ppar.option or "";
local mod = ppar.m or ppar.mod or "";
local pr4 = ppar.par4 or ppar.qpar or "";
local pr5 = ppar.par5 or ppar.rpar or "";
local max = 0;
local cor = 0;
local x = 0; -- running index, can be ~= i
local fst = 0; -- first occurrence
local plus = "";
for i, v in ipairs(ppar) do
if v == "+" then
plus = "+";
elseif v == "-" then
if plus == "" then plus = "-" end
else
x = x + 1;
if fst == 0 then fst = x end;
btab [x] = ppar ["b" .. tostring( x )] or ppar ["by" .. tostring( x )] or ppar ["u" .. tostring( x )] or "-";
dtab [x] = ppar ["d" .. tostring( x )] or "-";
htab [x] = ppar ["h" .. tostring( x )] or "-";
itab [x] = ppar ["i" .. tostring( x )] or "-";
ltab [x] = ppar ["l" .. tostring( x )] or ppar ["w" .. tostring( x )] or "-";
ntab [x] = ppar ["n" .. tostring( x )] or "-";
otab [x] = ppar ["o" .. tostring( x )] or "-";
qtab [x] = ppar ["q" .. tostring( x )] or "-";
rtab [x] = ppar ["r" .. tostring( x )] or "-";
ttab [x] = ppar ["t" .. tostring( x )] or "-";
utab [x] = ppar ["m" .. tostring( x )] or "-";
end
max = x;
if v == "x"
or v == "X"
or v == "×" then
cor = cor + 1;
end
end -- for
x = 0;
if fst > 0 then
local mnm = mw.text.trim ( ppar [fst] );
end
for _, v in ipairs(ppar) do
if v ~= "+" and v ~= "-" then
x = x + 1;
local by = by0; if btab[x] ~= "-" then by = btab[x]; end
local ds = dis; if dtab[x] ~= "-" then ds = dtab[x]; end
local hl = hil; if htab[x] ~= "-" then hl = htab[x]; end
local il = wik; if ltab[x] ~= "-" then il = ltab[x]; end
local lg = lng; if itab[x] ~= "-" then lg = itab[x]; end
local op = opt; if otab[x] ~= "-" then op = otab[x]; end
local p4 = pr4; if qtab[x] ~= "-" then p4 = qtab[x]; end
local p5 = pr5; if rtab[x] ~= "-" then p5 = rtab[x]; end
local um = mod; if utab[x] ~= "-" then um = utab[x]; end
local nm = ""; if ntab[x] ~= "-" then nm = ntab[x]; end
local tx = ""; if ttab[x] ~= "-" then tx = ttab[x]; end
local px = "";
local vv = mw.text.trim ( v );
if mw.ustring.find( vv, "/" ) == nil then
vv = samefile ( vv, x, mnm );
if x == 1 then mnm = vv; end
end
if vv ~= "" and vv ~= "×" then
if ppar.b1 == nil then -- parameter missing
px = "";
if x == 1 then
px = " "
elseif x == max then
table.insert(Ctab, frame:expandTemplate{ title = "Conj-and", args = { lang = 'int:lang' } });
else
table.insert(Ctab, frame:expandTemplate{ title = "Comma", args = { lang = 'int:lang' } });
end
else -- ppar.b1 is defined (with value, or empty)
px = "<br><span style=color:#69F>✦ </span>"; -- 'list' item
end
-- ds = mw.text.trim(ds);
if mw.ustring.sub(ds, -2) == "px" then
ds = mw.ustring.sub(ds, 1, mw.ustring.len(ds) -2);
end
if nm == "" and x == 1 then nm = nam end
if hl ~= "" then
if nm == "" then nm = vv end
nm = "<" .. hl .. ">" .. nm .. "</" .. hl .. ">"
end
-- if il ~= "" then ds = "" end -- ? (discrepancy)
if vv == "x" then ds = "" end -- this should be the last "file"
if by == "" then -- check for abbreviating "/"
local sby = mw.ustring.find( vv, "/" );
if sby ~= nil then
by = mw.ustring.sub( vv, sby+1 );
vv = mw.ustring.sub( vv, 1, sby-1 );
vv = samefile ( vv, x, mnm );
if x == 1 then mnm = vv; end
end
end
table.insert(Ctab, frame:expandTemplate{ title = "F", args = {vv, nm, ds, op, p4, p5, plus, l= il, lang= lg, p= px, by= by, u= um} });
if tx ~= "" then
table.insert(Ctab, frame:expandTemplate{ title = "=", args = { tx } } );
end
end
end
end -- for
if max - cor > 9 then
table.insert(Ctab, frame:expandTemplate{ title = "Igen/cat", args = {"Own-based with more than 9 files|" .. max} });
end
return table.concat (Ctab);
end -- function ownbased
-- horizontal file list for: Template:SVG lang, Template:Lang gallery, and others
function p.svglang (frame)
local gpar = frame.args; -- global parms
local tmpl = gpar [1] or 'Source thumb'; -- 'SVG lang', 'Lang gallery/thumb'
local ppar = mw.getCurrentFrame():getParent().args;
local file = ppar.file or '';
local p = ppar.p or '';
local trim = mw.text.trim;
local insert = table.insert;
local nl = mw.ustring.char(10);
local results = {};
for _, v in ipairs(ppar) do
local lang = trim(v) ; if lang > ' ' then
insert(results, trim(frame:expandTemplate{ title = tmpl, args = { file, lang, p = p } }));
insert(results, nl);
end
end
return table.concat(results);
end -- function svglang
-- elements count for: Template:SVG lang, Template:Lang gallery, and others
function p.elemct (frame)
local ppar = mw.getCurrentFrame():getParent().args;
local trim = mw.text.trim;
local count = 0;
for _, v in ipairs(ppar) do
local lang = trim(v) ; if lang > ' ' then
count = count + 1;
end
end
return count
end -- function elemct
-- horizontal file list for: Template:Filelist, Template:File
-- vertical file list for: Template:Other versions, Template:Derived from, Template:Derivative versions
function p.filelist (frame)
-- local lpar = frame -- local parms
local gpar = frame.args -- global parms
local ppar = mw.getCurrentFrame(): getParent().args;
local ctab = {};
local ltab = {};
local ntab = {};
local dtab = {};
local otab = {};
local ptab = {};
local qtab = {};
local rtab = {};
local vtab = {};
local ktab = {};
local itab = {};
local xtab = {};
local btab = {};
local stab = {};
local ttab = {};
local utab = {};
local loop = {};
local mnum = 0;
local dir = gpar[1] or "none"
local nam = ppar.n or ppar.name or "";
local dis = ppar.d or ppar.z or ppar.dis or ppar.display or "";
local lnk = ppar.l or ppar.lnk or ppar.link or "";
local opt = ppar.o or ppar.opt or ppar.option or "";
local pre = ppar.p or ppar.pre or ppar.pretext or "";
local mod = ppar.m or ppar.mod or "";
local pr4 = ppar.par4 or ppar.qpar or "";
local pr5 = ppar.par5 or ppar.rpar or "";
local pr6 = ppar.par6 or ppar.vpar or "";
local by0 = ppar.user or ppar.by or "";
local mod = ppar.mod or ppar.m or "";
local spa = ppar.spa or ppar.s or "-";
local wik = ppar.w or ppar.k or ppar.wiki or ppar.sisterproject or "";
local int = ppar.i or ppar.int or ppar.ind or ppar.inter or "";
local pfx = ppar.x or ppar.pfx or ppar.prefix or ""; -- 'list' item {{Comma}}
local con = ppar.conj or ppar.con or ppar.c or " ";
con = mw.ustring.sub(con, 1, 1)
if mw.ustring.sub(dis, -2) == 'px' then
dis = mw.ustring.sub(dis, 1, mw.ustring.len(dis) -2)
end
if ppar.z then
if con == " " then con = "n" end;
if opt == "" then opt = "Z" end;
if pre == "" then pre = " " end;
end
local vary = ppar.vary or ppar.v or ""; -- var pattern
local var1 = ppar.var1 or ppar.v1 or ""; -- var filling space before
local var2 = ppar.var2 or ppar.v2 or ""; -- var filling space after
if var1 == "space" then var1 = " " end;
if var2 == "space" then var2 = " " end;
if dir == "vert" and pfx == "" then
pfx = "\n* "; -- 'list' item
end
for i, v in ipairs(ppar) do
ntab [i] = ppar ["n" .. tostring( i )] or ppar ["l" .. tostring( i )] or "-";
dtab [i] = ppar ["d" .. tostring( i )] or "-";
ltab [i] = ppar ["l" .. tostring( i )] or "-";
otab [i] = ppar ["o" .. tostring( i )] or "-";
ptab [i] = ppar ["p" .. tostring( i )] or "-";
qtab [i] = ppar ["q" .. tostring( i )] or "-";
rtab [i] = ppar ["r" .. tostring( i )] or "-";
vtab [i] = ppar ["v" .. tostring( i )] or "-";
ktab [i] = ppar ["k" .. tostring( i )] or "-";
itab [i] = ppar ["i" .. tostring( i )] or "-";
xtab [i] = ppar ["x" .. tostring( i )] or "-";
stab [i] = ppar ["s" .. tostring( i )] or "~";
ttab [i] = ppar ["t" .. tostring( i )] or "-";
utab [i] = ppar ["m" .. tostring( i )] or "-";
btab [i] = ppar ["b" .. tostring( i )] or ppar ["by" .. tostring( i )] or "-";
mnum = i;
end
local lcnt = 0; -- loop count
local i = 1; -- while index
while ppar[i] ~= nil do -- for i, v in ipairs(ppar) do
local j = 1;
local vv = mw.text.trim( ppar[i] );
if vary ~= ""
and mw.ustring.byte ( vv, 1 ) == mw.ustring.byte ( '#' ) -- loop processing ?
and mw.ustring.byte ( vv, #vv ) == mw.ustring.byte ( '#' ) then
local pv = true; -- "plain"
loop = mw.text.split( vv, '#', pv );
local llow = tonumber( loop[2] ) or -1;
local lupp = tonumber( loop[3] ) or -1;
if llow >= 0 and lupp >= llow then
llow = llow + lcnt;
vv = tostring ( llow );
lcnt = lcnt + 1;
if llow < lupp
then j = 0 -- iterate this index
else lcnt = 0; -- loop ended
end;
end
end -- end loop processing
if mw.ustring.byte ( vv, 1 ) == mw.ustring.byte ( '"' ) -- text processing ?
and mw.ustring.byte ( vv, #vv ) == mw.ustring.byte ( '"' )
then table.insert(ctab, frame:expandTemplate{ title = "=", args = {mw.ustring.sub(vv, 2, #vv - 1)} });
elseif vary == "" or i > 1 then
local nm = nam; if ntab[i] ~= "-" then nm = ntab[i]; end
local ds = dis; if dtab[i] ~= "-" then ds = dtab[i]; end
local ln = lnk; if ltab[i] ~= "-" then ln = ltab[i]; end
local op = opt; if otab[i] ~= "-" then op = otab[i]; end
local pr = pre; if ptab[i] ~= "-" then pr = ptab[i]; end
local p4 = pr4; if qtab[i] ~= "-" then p4 = qtab[i]; end
local p5 = pr5; if rtab[i] ~= "-" then p5 = rtab[i]; end
local p6 = pr6; if vtab[i] ~= "-" then p6 = vtab[i]; end
local pk = wik; if ktab[i] ~= "-" then pk = ktab[i]; end
local pi = int; if itab[i] ~= "-" then pi = itab[i]; end
local px = pfx; if xtab[i] ~= "-" then px = xtab[i]; end
local sp = spa; if stab[i] ~= "~" then sp = stab[i]; end
local tx = ""; if ttab[i] ~= "-" then tx = ttab[i]; end
local by = by0; if btab[i] ~= "-" then by = btab[i]; end
local um = mod; if utab[i] ~= "-" then um = utab[i]; end
if vary ~= "" then
if sp == "+" then sp = " "
else sp = "" end;
vv = mw.ustring.gsub( ppar [1], vary, var1..sp..vv..var2 )
else
vv = samefile ( vv, i, ppar [1] )
end
if vv ~= "" and vv ~= "×" then
if dir == "hori" and con ~= "n" then -- horizontal list
px = "";
if i == 1 then
px = " "
elseif i == mnum then
table.insert(ctab, frame:expandTemplate{ title = "Conj-and", args = { lang = 'int:lang' } });
else
table.insert(ctab, frame:expandTemplate{ title = "Comma", args = { lang = 'int:lang' } });
end
else -- elseif dir == "vert"ical then
if i == 1 then
px = " "
end
end
if by == "" then -- check for abbreviating "/"
local sby = mw.ustring.find( vv, "/" );
if sby ~= nil then
by = mw.ustring.sub( vv, sby+1 )
vv = mw.ustring.sub( vv, 1, sby-1 )
end
end
if ln == "" then
table.insert(ctab, px .. frame:expandTemplate{ title = "F", args = {vv, nm, ds, op, p4, p5, p6, l= pk, lang= pi, p=pr, by= by, u= um} });
else
table.insert(ctab, px .. frame:expandTemplate{ title = "F", args = {vv, nm, ds, op, p4, p5, p6, l= pk, lang= pi, p=pr, by= by, u= um, link= ln} });
end
if tx ~= "" then
table.insert(ctab, frame:expandTemplate{ title = "=", args = { tx } } );
end
end -- if vary
end -- if vv
i = i + j; -- next in do loop
end -- while
return table.concat (ctab)
end -- function filelist
-- for Template:Attribs (param pairs; but also for single params)
function p.attribs (frame)
local ppar = mw.getCurrentFrame(): getParent().args;
local ftab = {}; -- "from" topic
local ptab = {}; -- parts
local mtab = {}; -- modification
local rtab = {}; -- work tab
local otab = {}; -- output
local fnum = 0;
local rnum = 0;
local hnum = 0;
local tp = ppar.type or "SVG"; -- needs check
local un = ppar.by or ppar.U or ppar.u or "";
local md = ppar.m or ppar.mod or "";
local tt = ppar.t or ppar.to or ""; -- "to" topic
local f = ppar.f or ppar.from or tt; -- from"
local p = ppar.p or ppar.part or "";
local s = ppar.s or ppar.style or "s"; -- default
local vx = "";
local ux = "";
local ft = "";
local um = "";
for i, v in ipairs(ppar) do
fnum = fnum + 1; -- input parm number
if fnum % 2 == 0 then -- even: should be a username
local enam = mw.text.trim ( v );
local snam = mw.ustring.lower ( mw.ustring.sub ( enam, -4 ) );
if snam == ".svg"
or snam == ".png"
or snam == ".jpg" -- a rough check: is_extension ?
or snam == ".gif"
or snam == ".pdf"
or snam == ".tif" then -- no - it's the next filename
table.insert(rtab, "" ); -- empty username inbetween
rnum = rnum + 1;
fnum = fnum + 1; -- make it odd
end
end
if fnum % 2 == 1 then -- odd (now): is a filename
hnum = fnum + 1
hnum = hnum / 2
ftab [hnum] = ppar ["f" .. tostring( hnum )] or ".";
ptab [hnum] = ppar ["p" .. tostring( hnum )] or ".";
mtab [hnum] = ppar ["m" .. tostring( hnum )] or ".";
end
-- table.maxnum (ppar) does not work
-- therefore the "rtab" workaround
table.insert(rtab, ppar[i]); -- = enam
rnum = rnum + 1
end
-- plus one item when odd number
if rnum % 2 == 1 then
table.insert( rtab, "" ); -- empty user name, to get a pair
end
--
for i, v in ipairs(rtab) do
if vx == "" then -- the 2nd 'v' can be empty
vx = mw.text.trim( v );
else
ux = mw.text.trim( v );
if ux == "" then ux = un end; -- does not work otherwise (?)
hnum = i + 0
hnum = hnum / 2
if ftab[hnum] == "." then
ft = f
else
ft = ftab[hnum]
end
if ptab[hnum] == "." then
pt = p;
else
pt = ptab[hnum]
end
if mtab[hnum] == "." then
um = md;
else
um = mtab[hnum]
end
table.insert(otab, frame:expandTemplate{ title = "Attrib", args = {vx, ux, "-", tp, "", ux, tt, ft, pt, m=um, s=s } });
vx = "";
end
end
return table.concat (otab)
end -- function attribs
-- get the user id: the (last) parameter which is prefixed by '/'
function p.byuser ( frame )
-- local gpar = frame.args-- global parms;
local ppar = mw.getCurrentFrame(): getParent().args;
local user = '';
for _, value in pairs( ppar ) do
if value ~= nil and -- user == '' and
mw.ustring.sub (value, 1, 1) == '/' then
user = mw.ustring.sub (value, 2) -- remove the "/"
end
-- test whether userID exists ...
end
return user
end -- function byuser, for template:F
-- for Template:userlist (horizontal - but vertical when dir=I/O/U/V)
function p.userlist (frame)
-- local lpar = parm -- local parms
local gpar = frame.args -- global parms (par/P,dir/V)
local ppar = mw.getCurrentFrame(): getParent().args;
local ctab = {}; -- case
local htab = {}; -- hilite
local ltab = {}; -- link option
local ntab = {}; -- 2 display name
local wtab = {}; -- 3 interwiki
local otab = {}; -- 4 +/- option
local mtab = {}; -- u_mod c/t/w/wt (aka utab, mtab, ptab)
local ttab = {}; -- translate i18n
--@ local rtab = {};
--@ local qtab = {};
local xtab = {}; -- postfix text
local Itab = {}; -- the output table
local cas = ppar.c or ppar.case or "";
local hil = ppar.h or ppar.hilite or "";
local lnk = ppar.l or ppar.link or "";
local nam = ppar.n or ppar.name or "";
local opt = ppar.o or ppar.opt or ppar.option or "";
local mod = ppar.m or ppar.mod or ppar.user or ppar.u or ppar.page or ppar.p or "";
--@ local pr4 = ppar.q or ppar.qpar or ppar.par4 or "";
--@ local pr5 = ppar.r or ppar.rpar or ppar.par5 or "";
local trl = ppar.t or ppar.i18n or ppar.translate or "";
local wik = ppar.w or ppar.wiki or ppar.lang or "";
local max = 0;
local cor = 0;
local x = 0; -- running index, can be ~= i
local y = 0; -- running index, can be ~= i
local odd = 0;
local out = 0;
local plus = ""; -- opt
local prim = ""
local prfx = ":"
local pend = ""
if gpar.dir == "O" then -- ordered list
prim = "<ol>";
prfx = "<li>";
pend = "</ol>";
end
if gpar.dir == "U" then -- unordered list
prim = "<ul>";
prfx = "<li>";
pend = "</ul>";
end
if gpar.dir == "V" then -- vertical list
prim = " ";
prfx = "<br><span style=color:#69F>✦ </span>";
end
for _, v in ipairs(ppar) do
v = mw.text.trim ( v );
if v == "+" then
plus = "+";
elseif v == "-" then
if plus == "" then plus = "-" end
else
y = y + 1;
if gpar.par == "P" -- pairs of (user, name)
and y % 2 == 0 then -- 1=user, 0=name
x = x;
else
x = x + 1;
ctab [x] = ppar ["c" .. tostring( x )] or "-";
htab [x] = ppar ["h" .. tostring( x )] or "-";
ltab [x] = ppar ["l" .. tostring( x )] or "-";
ntab [x] = ppar ["n" .. tostring( x )] or "-";
otab [x] = ppar ["o" .. tostring( x )] or "/";
mtab [x] = ppar ["m" .. tostring( x )] or ppar ["u" .. tostring( x )] or ppar ["p" .. tostring( x )] or "-";
--@ rtab [x] = ppar ["r" .. tostring( x )] or "-";
--@ qtab [x] = ppar ["q" .. tostring( x )] or "-";
ttab [x] = ppar ["t" .. tostring( x )] or "-";
wtab [x] = ppar ["w" .. tostring( x )] or "-";
xtab [x] = ppar ["x" .. tostring( x )] or "-";
end
end
max = x;
end -- for
odd = y % 2; -- 1 when last one not paired
if plus > "" and opt == "" then
opt = plus; -- discrepancy ? opt has priority
end
x = 0;
y = 0;
local vv = "";
for _, v in ipairs(ppar) do
v = mw.text.trim ( v );
if v ~= "+" and v ~= "-" then
y = y + 1;
if gpar.par == "P" -- pairs of (user, name)
and y % 2 == 1 -- 1=user, 0=name
and odd == 0 then -- last one paired
vv = v; -- userid
else
x = x + 1;
local cs = cas; if ctab[x] ~= "-" then cs = ctab[x]; end
local hl = hil; if htab[x] ~= "-" then hl = htab[x]; end
local lk = lnk; if ltab[x] ~= "-" then lk = ltab[x]; end
local nm = nam; if ntab[x] ~= "-" then nm = ntab[x]; end
local op = opt; if otab[x] ~= "/" then op = otab[x]; end
local md = mod; if mtab[x] ~= "-" then md = mtab[x]; end
--@ local p4 = pr4; if rtab[x] ~= "-" then p4 = rtab[x] end
--@ local p5 = pr5; if qtab[x] ~= "-" then p5 = qtab[x] end
local tr = trl; if ttab[x] ~= "-" then tr = ttab[x]; end
local wk = wik; if wtab[x] ~= "-" then wk = wtab[x]; end
local tx = ""; if xtab[x] ~= "-" then tx = xtab[x]; end
if gpar.par == "P" then -- y%2 = 0 (name)
if odd == 1 then -- no: last user:
vv = v; -- user
else
nm = v; -- name
end
else
vv = v;
end
if hl ~= "" then
if nm == "" then nm = vv; end
nm = "<" .. hl .. ">" .. nm .. "</" .. hl .. ">";
end
local p1 = ""; -- prefix
local p2 = ""; -- postfix
if md == "t" or md == "wt" or md == "tw" then p1 = " talk"; end
if md == "w" or md == "wt" or md == "tw" then
if wk == "" then p2 = "~commonswiki";
else p2 = "~"..wk.."wiki";
end
end
if md == "n" or md == "no" then
lk = md; -- no link
end
if vv ~= "" and vv ~= "×" then
if md == "c" then vv = "Special:Contributions/" .. vv; end
if gpar.dir == "I"
or gpar.dir == "O"
or gpar.dir == "U"
or gpar.dir == "V" then -- vertical list
if out == 0 then
table.insert(Itab, frame:expandTemplate{ title = "=", args = { prim } });
end
table.insert (Itab, frame:expandTemplate{ title = "=", args = { prfx } });
out = out + 1;
else --
if x == 1 then
x = 1 -- ??? horizontal list initializing (text)
elseif x == max then
table.insert(Itab, frame:expandTemplate{ title = "Conj-and", args = { lang = 'int:lang' } });
else
table.insert(Itab, frame:expandTemplate{ title = "Comma", args = { lang = 'int:lang' } });
end
end
if mw.ustring.sub( vv, 1, 2 ) == '{{'
or mw.ustring.sub( vv, 1, 2 ) == '[[' then
table.insert(Itab, frame:expandTemplate{ title = "=", args = { vv } }); --
else
table.insert(Itab, frame:expandTemplate{ title = "U/main", args = { vv, nm, wk, op, link=lk, par1=p1, par2=p2, case=cs, i18n=tr} });
end
if tx ~= "" then
table.insert(tab, frame:expandTemplate{ title = "=", args = { tx } } );
end
end
end
end
end -- for
if out > 0 and pend > " " then
table.insert(Itab, frame:expandTemplate{ title = "=", args = { pend } });
end
return table.concat (Itab);
end -- function userlist
-- Table for templates: Legend; Legend-line, Legend2, Legend-small ... (param pairs)
function p.legendt (frame)
local frmp = frame.args
local temp = frmp [1] or "Legend"
local parm = frmp [2] or ""
local wide = frmp [3] or ""
local cssp = "" -- dummy parm
local ppar = mw.getCurrentFrame(): getParent().args;
local ttip = ppar.tt or ppar.ttip or ppar.tooltipping or ""
local otab = {};
local lg = ppar.lang or "";
local v1 = ""
for _, v in ipairs(ppar) do
if v1 == "" then
v1 = v;
if ttip == "yes" then -- tooltip rhe colors
cssp = '"title="'..mw.ustring.upper(v1)
end
else
table.insert(otab, frame:expandTemplate{ title = temp, args = { v1, v, lang = lg, p = parm, size = wide, css = cssp } });
v1 = "";
end
end
if v1 ~= "" then -- the problem when not a last pair
table.insert(otab, frame:expandTemplate{ title = temp, args = { v1, "", lang = lg, p = parm, size = wide, css = cssp } }); -- last elem
end
return table.concat (otab)
end -- function legendt
-- for Template:ColorString (Igen/cbox - param pairs)
function p.colorbox (frame)
local ppar = mw.getCurrentFrame(): getParent().args;
local otab = {};
local lg = ppar.lang or "{{PAGELANGUAGE}}"; --
local v1 = "";
local p2 = "";
local ct = 0;
local bp = 0;
local bc = '';
local cf = '';
for i, v in ipairs(ppar) do
if i <= 2 then
p2 = v; -- either code-2 ( BCDLMST-), or color value
else
if v1 == "" then
v1 = mw.text.trim( v ); -- ( striped; border )
ct = 0; -- count of spaces
bp = 0; -- position of first space
for c = 1, #v1 do
if mw.ustring.sub( v1, c, c) == ' ' then
ct = ct + 1; -- space count
if bp == 0 then bp = c; end
end
end
bc = '';
if ct >= 3 then -- 3=border, 4=line
bc = mw.ustring.sub(v1, bp+1);
v1 = mw.ustring.sub(v1, 1, bp-1);
end
if ct == 1 then -- char or file
bc = mw.ustring.sub(v1, bp+1);
v1 = mw.ustring.sub(v1, 1, bp-1);
if mw.ustring.sub ( bc, -4, -4 ) == "." then
cf = 'file'
else
cf = 'char'
end
end
else
table.insert(otab, frame:expandTemplate{ title = "Igen/cbox", args = { v1, v, p2, ct, bc, cf, lang = lg } });
v1 = "";
end
end
end
if v1 ~= "" then
table.insert(otab, frame:expandTemplate{ title = "Igen/cbox", args = { v1, "", p2, ct, bc, cf, lang = lg } }); -- last elem
end
return table.concat (otab);
end -- function colorbox
--------------------------------------------------------------------------------
-- returns a parameter list: (replacement of «#» or «~» by «=»: not necessary)
function p.plist ( frame )
local gpar = frame.args -- global parms
local ppar = mw.getCurrentFrame(): getParent().args;
local ostr = ""
for i, v in ipairs(ppar) do
if i < 2 then
ostr = v;
else
ostr = ostr .. "|" .. v;
end
end
return ostr; -- return mw.ustring.gsub( ostr, "#", "=" ),_ not necessary
end -- function plist
-- repeats a text string
function p.loop ( frame ) -- repeat
local ppar = mw.getCurrentFrame(): getParent().args;
local pnum = 0; -- cunt
local pchr = ppar[2] or ' '; -- char
local rval = '';
pnum = pnum + tonumber(ppar[1] or 1); -- cunt
for l = 1, pnum do
rval = rval .. pchr;
end
return rval;
end -- function loop
-- Increment a hex number by a ±decimal value
function p.incrhx(frame)
local gpar = frame.args -- global parms
return format('%X', tonumber(gpar[1], 16) + gpar[2])
end -- function incrhx
-- Display inline a range of characters with their Unicode code point in tool tip, such as emojis for Template:Emoji, with optional
-- line breaks to limit lines to at most 16 characters (breaks after every code point which is the last one in a UCS column):
-- {{#invoke:Iteration|parlst |temp=Emoji |1=(nb of characters) |2=(4- to 6-digits uppercase hexadecimal code point)
-- |3=(border or 0) |4=(padding or 0) |5=(font size in px or -)
-- |6=(styles or -) |(nocat=1)
-- }}
function p.emodis(frame)
local gpar = frame.args -- global parms
local code = tonumber(gpar[1], 16) + gpar[2]
local ucod = format('%04X', code)
-- WARNING: partial HTML (see the template using this function)
-- This function can only be used after an UNTERMINATED opening HTML tag,
-- whose LAST attribute MUST BE ' title=' not followed by quotes.
-- This returned value closes the opening HTML tag of the template
-- The calling template will then append itself the closing HTML tag.
return table.concat{
'"U+', ucod, '">&#x', ucod, ';',
gpar[3] == '16' and (code % 16 == 15 and '<br />') or nil
}
end -- function emodis
-- for Template:Emoji table: {{#invoke:Iteration|emotab|prefix=1F250|par1=... | ... }}
function p.emotab(frame)
local gpar = frame.args -- global parms
local expand = frame.expandTemplate
local trim = mw.text.trim
local codp = trim(gpar.codp or '')
local part = {
'', -- file
trim(gpar.par1 or ''), -- Z
trim(gpar.par2 or ''), -- 49
trim(gpar.par3 or ''), -- b
trim(gpar.par4 or ''), -- l
trim(gpar.par5 or ''), --
link = '*',
}
for i = 2, 6 do
if part[i] == '' then part[i] = nil end
end
local sub = mw.ustring.sub
local upper = mw.ustring.upper
local lower = mw.ustring.lower
local titleNew = mw.title.new
local insert = table.insert
local otab = {}
for _, v in ipairs(gpar) do
local file = sub(v, 1, 6)
file = v .. ((file == 'Emojio' or file == 'Fxemoj' or file == 'OpenMo') and upper or lower)(codp) .. '.svg'
if titleNew(file, 6).exists then
part[1] = file
-- insert(otab, expand(frame, { title = '=', args = {' | '} } ))
insert(otab, expand(frame, { title = 'F', args = part } ))
end
end
return table.concat(otab)
end -- function emotab
-- for template: Navcat (via Navcattab)
function p.navcat ( frame )
-- local lpar = frame -- local parms
local gpar = frame.args-- global parms
local ppar = mw.getCurrentFrame(): getParent().args;
local cat1 = gpar.c1 or "";
local cat2 = gpar.c2 or "";
local span = gpar.span or "";
local otab = {};
for _, v in ipairs(ppar) do
v = mw.text.trim(v);
if v == "" or v == "nl" then
-- (( table.insert(otab, frame:expandTemplate{ title="clr", args = { "" } } );
table.insert(otab, frame:expandTemplate{ title="=", args = { "<br>" } } );
else
local itab = mw.text.split ( v, "/" );
local ctxt = itab[1]; -- requ
local ccod = itab[2]; -- opt.
local cnam = itab[3] or ccod or ctxt;
local dtxt = mw.ustring.upper(mw.ustring.sub(ctxt,1,1))..mw.ustring.sub(ctxt,2); -- ucfirst
table.insert(otab, frame:expandTemplate{ title="Navcat", args={ccod, cat1..ctxt..cat2, dtxt, cnam, span=span } } );
end
end
return table.concat (otab);
end -- function navcat
-- Template:Tle
function p.tleparm (frame)
-- local lpar = frame -- local parms
-- local gpar = frame.args-- global parms
local ppar = mw.getCurrentFrame(): getParent().args;
local par1 = "";
local par3 = ppar.f or ""; -- form feed
local par4 = ppar.style or ""; -- style for value
local par5 = ppar.style2 or ""; -- style for param
local numb = ppar.number or "";
local kybd = ppar.kbd or "";
local ctab = {}
numb = mw.text.trim( numb );
for i, v in ipairs(ppar) do
par1 = ppar ["p" .. tostring( i )] or "";
if par1 ~= "" and kybd ~= "" then
par1 = '<kbd>'..par1..'</kbd>'
end
if par1 == "" and numb ~= "" then
par1 = tostring( i )
end
if mw.text.trim(v) == "" then v = " " end
table.insert( ctab, frame:expandTemplate{ title = "Tle/parm", args = { par1, v, par3, par4, par5} } );
end
return table.concat (ctab)
end -- function tleparm
-- Template:variate
function p.variation (frame)
local ppar = mw.getCurrentFrame(): getParent().args;
local strg = ppar [1] or ""; -- sample string
local pttn = ppar.pttn or "?"; -- pattern
local var1 = ppar.var1 or ""; -- filling space before
local var2 = ppar.var2 or ""; -- filling space after
local sept = ppar.sept or "|"; -- separator
local sep2 = ppar.sep2 or ""; -- separator after
if var1 == "space" then var1 = " " end;
if var2 == "space" then var2 = " " end;
local retv = "";
strg = mw.text.trim( strg )
for i, v in ipairs(ppar) do
if i > 1 then
retv = retv .. sept .. mw.ustring.gsub( strg, pttn, var1..mw.text.trim(v)..var2 ) .. sep2
end
end
return retv
end
return p;