Module:Parmlist

From Wikimedia Commons, the free media repository
Jump to navigation Jump to search
Lua

CodeDiscussionEditHistoryLinksLink count Subpages:DocumentationTestsResultsSandboxLive code All modules

Code

local p = {}  --


--------------------------------------------------------------------------------
--------------------------------------------------------------------------------




-- g function test1 P
function p.test1( frame )	
	local gpar = frame.args	-- global parms
	local ilen = #gpar[1];
	gpar[1] = mw.ustring.gsub ( gpar[1], 'r', '' );
	if ilen > #gpar[1] then		-- ~=
		return 'R'..gpar[1];
	else
		return gpar[1];
	end
end -- function test1


-- g function:  number of pos. parm, default value when missing
function p.pospar ( frame )	-- default for empty positional param
	local gpar = frame.args	-- global parms
	local ppar = mw.getCurrentFrame(): getParent().args;
	 local pnm = gpar[1]			-- g: positional number
	 local pdf = gpar[2] or ''		-- g: default value
	 local pvl = ppar[pnum] or ''	-- p: defined value	
--	if  ppar [ gpar[1] ] ~= '' then	-- was <nil>
--		return ppar [ gpar[1] ]		-- defined value
--	else
--		return  gpar[2]				-- default value
--	end
	return  'num='.. pnm.. ', val='..pvl..', def='..pdf 
end -- function pospar

--------------
-- global function check when 1 space   for Igen/cbox
function p.space1 ( frame )
	local gpar = frame.args;
	local spos = 0;
	local retv = "";
	for i = 1, #gpar[1] do
		if  mw.ustring.sub ( gpar[1], i, i ) == " " then
			spos = i
		end
	end
	if spos > 0 then
		retv = mw.ustring.sub ( gpar[1], spos+1, #gpar[1] )
		if  mw.ustring.sub ( retv, -4, -4 ) == "." then
			return  'file='..retv
		else
			return  'char='..retv
		end
	else
		return ''
	end
end -- function space1

--------------
function p.wellcome ( frame )
	local fnam = mw.title.getCurrentTitle().text;
	if mw.ustring.sub( fnam, -4 ) == '.jpg'
		then fnam = mw.ustring.sub( fnam, 1, #fnam-4 );
		local posf = mw.ustring.find( fnam, ' Wellcome' );
		if posf
			then fnam = mw.ustring.sub( fnam, 1, posf-1 );
			end
	elseif mw.ustring.sub( fnam, -4, -4 ) == '.'
		then fnam = mw.ustring.sub( fnam, 1, #fnam-4 );
	elseif mw.ustring.sub( fnam, -5, -5 ) == '.'
		then fnam = mw.ustring.sub( fnam, 1, #fnam-5 );
	end
	return fnam;
end --  function filename without "Wellcome ..."

-- hex to decimal value (0 ... FFFFFFFFFFF)
function p.h2d ( frame )
	local gprm = frame.args-- global parms
	return tonumber ( gprm[1], 16 )
end --  function h2d
-- hex to decimal value (0 ...  17592186044415)
function p.d2h ( frame )
	local gprm = frame.args-- global parms
	return mw.ustring.format ( "%X", gprm[1] )
end --  function d2h

-- strip removes from a string(1) all characters specified by a pattern(2). 
-- default for pattern is the space; pattern can be e.g. "[€.,-%s]". 
-- e.g {{#invoke:..|strip|12,3334.556666 $|[$€.,-%s]}} will remove ",. $"
p.strip = function(frame)
	return mw.ustring.gsub( frame.args[1] or " ", frame.args[2] or " ", '' ),_
end --  function: remove from string (by pattern) 

-- test decimal 
function p.dtest ( frame )
	local gprm = frame.args-- global parms
	return tonumber ( mw.text.trim (gprm[1]) )
end --  function dtest

-- global function with 1 parm   for template:F
function p.remprf ( frame )
	local gpar = frame.args;
	if  mw.ustring.sub (gpar[1], 1, 2) == '()'
	 or mw.ustring.sub (gpar[1], 1, 2) == '<>'
	 or mw.ustring.sub (gpar[1], 1, 2) == '[]'
	 or mw.ustring.sub (gpar[1], 1, 2) == '{}'
	 or mw.ustring.sub (gpar[1], 1, 1) == mw.ustring.sub (gpar[1], 2, 2) 
	and mw.ustring.sub (gpar[1], 1, 2) ~= '[['
	and mw.ustring.sub (gpar[1], 1, 2) ~= '{{' then
		if mw.ustring.sub (gpar[1], 1, 2) == '!!' then
			return "''"..mw.ustring.sub (gpar[1],3).."''"	--  replace that prefix
		else	
			return mw.ustring.sub (gpar[1], 3 )				--  remove that prefix
		end
	else
		return gpar[1]
	end
end -- function remprf

-- global with 2 parms: count occurencies of pattern in string
function p.count ( frame ) 
	local gprm = frame.args; -- global parms
	local strg = gprm[1] or '';
	local pttn = gprm[2] or ' ';
	local addp = #pttn - 1;
	local cunt = 0;
    for i = 1, #strg-addp do
		cunt = cunt + 100	-- count of loops
    	if mw.ustring.sub( strg, i, i+addp) == pttn
    		then cunt = cunt + 1;
    	end
	end
	return cunt		-- number of occurrencies
end	-- function count

-- global with 2 parms: return left part of string
function p.leftp ( frame ) 
	local gprm = frame.args; -- global parms
	local strg = gprm[1] or ' ';
	local pttn = gprm[2] or ' ';
	local retv = '';
    for i = 1, #strg do
    	if mw.ustring.sub( strg, i, i) == pttn
    		then retv = mw.ustring.sub( strg, 1, i-1);
				break;
    	end
	end
	return retv		-- string
end	-- function leftp

-- global with 2 parms: return right part of string
function p.rigtp ( frame ) 
	local gprm = frame.args; -- global parms
	local strg = gprm[1] or ' ';
	local pttn = gprm[2] or ' ';
	local retv = '';
    for i = 1, #strg do
    	if mw.ustring.sub( strg, i, i) == pttn
			then retv = mw.ustring.sub( strg, i+1, #strg);
				break;
    	end
	end
	return retv		-- string
end	-- function rigtp


function p.coord ( frame )	-- without any check for erroneous input !
	local gpar = frame.args	-- global parms
	local ppar = mw.getCurrentFrame(): getParent().args;
	local lang = gpar.lang  or "en"
	local scal = gpar.scale or "18"
	local view = gpar.view  or "o"
	local lon, lat = 0, 0;
	local prl, prb = "", "";
	if ppar[2] == nil then		-- one parm,  e.g. 49°13′39.3″N 09°12′19.3″E
		local inp = ppar[1];
		local inx = 0;
		local num = "";
		for i = 1, #inp do
			local tmp = mw.ustring.sub( inp, i, i)
			if	tmp == "0" or tmp == "1" or tmp == "2" or tmp == "3" or tmp == "4" or
				tmp == "5" or tmp == "6" or tmp == "7" or tmp == "8" or tmp == "9" or
				tmp == "."	then
				num = num..tmp
			else
				if num ~= "" then 
					inx = inx + 1;
					ppar[inx] = num;
					num = "";
				end
				tmp = mw.ustring.upper(tmp);
				if tmp == "N" or tmp == "S" or tmp == "E" or tmp == "W" then
					inx = inx + 1;
					ppar[inx] = tmp;
				end	-- NSEW 
			end	-- tmp
		end	-- for
	end	-- dms

	if ppar[8] == nil then		-- two parms, lon and lat (decimal)
		lat = tonumber(ppar[1])
		lon = tonumber(ppar[2])
	else						-- 8 parms, d+m+s + NSEW 
		lat = tonumber(ppar[1]) + tonumber(ppar[2])/60 + tonumber(ppar[3])/3600
		lon = tonumber(ppar[5]) + tonumber(ppar[6])/60 + tonumber(ppar[7])/3600
		if mw.ustring.upper(ppar[4]) == "S" then prl = "-" end 
		if mw.ustring.upper(ppar[8]) == "W" then prb = "-" end 
	end

	local out = {}
	if view == "osm" then
		out[1] = "https://www.openstreetmap.org/?mlat="..prl..lat.."&mlon="..prb..lon.."&zoom="..scal
	else
		out[1] = "http://wikimapia.org/#lang="..lang.."&lat="..prl..lat.."&lon="..prb..lon.."&z="..scal.."&m="..view
	end
	out[2] = prl..mw.ustring.sub(lat, 1, 6).." / "..prb..mw.ustring.sub(lon, 1, 6)	-- shorten output
	return mw.getCurrentFrame():expandTemplate{ title = "Plainlinks", args = out }
end	-- function coord 

function p.test (frame)
	local otab = {};
	local argtab = {};
	local titl = "F";	
	argtab[1] = "No free image woman.svg";
	argtab['d'] = "64";
	argtab[2] = "b";
--	argtab[3] =
	argtab['lang'] = "es";
	argtab['by']=Sarang;
	table.insert(otab, frame:expandTemplate { title=titl, args=argtab } );
	return table.concat (otab);
end --  function test

function p.catsalso (frame)
	local pprm = frame.args			-- global parms
	local slct = pprm[1] or ''		-- 'o' if only 'of', 'f' when only 'from'
	local titl = mw.title.getCurrentTitle()
	local nspc = titl.nsText		-- category
	local part = {}
	local outt = {}
	local alts = {}
	alts[1] = 'Seals'
	alts[2] = 'Flags'
	alts[3] = 'Symbols'
	alts[4] = 'Coats of arms'

	part = mw.text.split( titl.text, ' of ', true)
	if	part[1] == 'Coats' then 
		part[2] = part[3]
		part[1] = alts[4]
	end
	if part[1] ~= nil and part[2] ~= nil then
		if slct == '*' then slct = 'o' end
		for i = 1, 4 do
			if alts[i] ~= part[1] then
				local namt = alts[i]..' of '..part[2]
				if slct ~= 'f' then 	-- not only 'from' ?
					local test = mw.title.new( namt, nspc )
					if test.exists then table.insert( outt, namt );  end
				end
			end
			local namt = alts[i]..' from '..part[2]
			if slct ~= 'o' then 	-- not only 'of' ?
				local test = mw.title.new( namt, nspc )	
				if test.exists then table.insert( outt, namt );  end
			end
		end
	end
--
	part = mw.text.split( titl.text, ' from ', true)
	if part[1] ~= nil and part[2] ~= nil then
		if slct == '*' then slct = 'f' end
		for i = 1, 4 do
			if alts[i] ~= part[1] then
				local namt = alts[i]..' from '..part[2]
				if slct ~= 'o' then 	-- not only 'of' ?
					local test = mw.title.new( namt, nspc )
					if test.exists then table.insert( outt, namt );  end
				end
			end
			local namt = alts[i]..' of '..part[2]
			if slct ~= 'f' then 	-- not only 'from' ?
				local test = mw.title.new( namt, nspc )
				if test.exists then table.insert( outt, namt );  end
			end
		end
	end

	if outt[1] ~= nil then
		return mw.getCurrentFrame():expandTemplate{ title = 'Cat see also', args = outt }	
	end
end	-- function catsalso


function p.catexis (frame)
	local titl = mw.title.getCurrentTitle()
	local nspc = titl.nsText		-- category
	local part = {}
	part = mw.text.split( titl.text, ' of the ', true)
	if part[1] ~= nil and part[2] ~= nil then
		local outt = {}
		local alts = {}
		alts[1] = 'Seals'
		alts[2] = 'Flags'
		alts[3] = 'Symbols'
		alts[4] = 'Coats of arms'
--		alts[5] = 'Icons'
--		for i = 1, 4 do
			if alts[1] ~= part[1] then
				local namt = alts[1]..' of the '..part[2]
				test = mw.title.new( namt, nspc )
				if test.exists then table.insert( outt, namt );  end
			end
--		end
	end
	return '"'..titl.text..'" '..nspc..part[1]..'-' ..part[2] -- ..' "'..alts[1]..'"'..namt
end	-- function catexis 


-- local/global function
local function convdec ( color )
--	local gpar = frame.args
--	local hex = ''
--	if  gpar then
--		hex   =  gpar[1] or 'glo'
--	elseif  frame then
--		hex  =  frame   or 'loc'
--	else hex  = '#0F0'   --  parameter missing
--	end

	local hex  =  color or '#010';
    if  mw.ustring.sub ( hex, 1,  1) ~= '#' then 
        error ('value "' .. hex .. '" cannot be converted to decimal')
	end  
	local dec  =  {};
	if #hex == 7 then
		dec [1] = hexdec ( string.byte (hex, 2)) * 16 + hexdec (string.byte (hex, 3))
		dec [2] = hexdec ( string.byte (hex, 4)) * 16 + hexdec (string.byte (hex, 5))
		dec [3] = hexdec ( string.byte (hex, 6)) * 16 + hexdec (string.byte (hex, 7))
	else
		dec [1] = hexdec ( string.byte (hex, 2)) * 16 + hexdec (string.byte (hex, 2))
		dec [2] = hexdec ( string.byte (hex, 3)) * 16 + hexdec (string.byte (hex, 3))
		dec [3] = hexdec ( string.byte (hex, 4)) * 16 + hexdec (string.byte (hex, 4))
	end
	dec [4] = '000'
	if dec [1] * 3 + dec [2] * 10 < 1568 then 
		dec [4] = 'FFF'   -- this calculation is nonsense - not useful !
	end
	return dec;
end	-- function convdec
--
local function draw(color, ss, tc, pf, gt)
	return mw.getCurrentFrame():expandTemplate{ title = 'Tincture/draw' .. ss, args = { color, gt, tc = tc, pf = pf } }
end	-- function draw
--
local function category(colors, ss, tc, cat, no_error_cat)
	return mw.getCurrentFrame():expandTemplate{ title = 'Tincture/cat' .. ss, args = { table.concat(colors, '/'), tc = tc, cat = cat, ['no error cat'] = no_error_cat and '1' or nil } }
end	-- function category


----------------------------------------------------------
-- global help/test function "umoji" (Unicode emojis) invoked from  Emoji/doc
function p.umoji ( frame )
	local gprm = frame.args-- global parms
	local rval = "wrong page"
	local tab1, tab2 = {}
	if mw.ustring.sub (gprm[1], 1, 8) == "Unicode " then 
		local tab1 = mw.text.split(gprm[1], ' ', true)
		local tab2 = mw.text.split(tab1[2], '-', true)
		local val1 = tonumber ( tab2[1], 16 )
		local val2 = tonumber ( tab2[2], 16 )
		if val2 > val1 then 
			local cunt = 1 + val2 - val1
			rval = "{{#invoke:Iteration|parlst|temp=Emoji|"..cunt.."|"..tab2[1].."|1px solid #ccc|8px 0|40}}"
		end
	end
	return rval -- display only 
end --  function umoji
----------------------------------------------------------

-- test parameter input
function p.partest ( frame )
	local gprm = frame.args-- global parms;
--	local tabl = {};
	local outp = "";
	for index, value in  pairs( gprm ) do 
--		table.insert( tabl, value );
		outp = outp.." "..tostring(index).."="..value;
	end
	return outp
end --  function partest 


-- get the user id which is prefixed by '/'
function p.byuser ( frame )
--	local gprm = frame.args-- global parms;
	local pprm = mw.getCurrentFrame(): getParent().args;
	local user = '';
	for _, value in  pairs( pprm ) do
		if value ~= nil and
		   mw.ustring.sub  (value, 1, 1) == '/' then
			user = mw.ustring.sub (value, 2)
		end
-- 		test whether userID exists ...
	end
	return user
end --  function byuser 


-- function returns contrast color
function p.titcolor ( frame )
	local gpar = frame.args
	decval =  convdec ( gpar[1] );
	return decval[4] 
end -- function titcolor 

-- function converts '#rrggbb' or '#rgb' and returns 'ddd ddd ddd'
function p.convhd (parm)
	local gpar = parm.args
	decval =  convdec ( gpar[1] );
	return decval[1]..' '..decval[2]..' '..decval[3]
end -- function convhd

-- function converts  'ddd ddd ddd and returns ''#rrggbb' (or '#rgb')
function p.convdh (parm)
	local gpar = parm.args -- separated by either pipe, space or comma 
	local dect = parm.args
	local hext = {}
	local numb = {}
	local same = true
	if gpar [2] == nil then 
		gpar[1] = mw.ustring.gsub (gpar[1], '-', '/', 3) -- split-pattern: REGEXP won't work
		gpar[1] = mw.ustring.gsub (gpar[1], ',', '/', 3)
		gpar[1] = mw.ustring.gsub (gpar[1], ' ', '/', 3)
		dect = mw.text.split(gpar[1] or '0 0 0', '/')
	end
	for i = 1, 3 do
		numb[i] = tonumber( dect[i] )
		if numb[i] == nil or numb[i] > 255 then
			error ('value "' .. dect[i] .. '" cannot be converted to hexadecimal')
--				..dect[1]..','..dect[2]..','..dect[3]..'.'..i)
		end
		hext[i] = mw.ustring.format ("%X", math.floor (numb[i] / 16) ) .. mw.ustring.format ("%X", math.floor (numb[i] % 16) )
		if string.byte ( hext [i], 1 )  ~= string.byte ( hext[i], 2 )  then
			same = false
		end
	end
	if same then 
		hext[1] = mw.ustring.sub (hext[1], 2)
		hext[2] = mw.ustring.sub (hext[2], 2)
		hext[3] = mw.ustring.sub (hext[3], 2)
	end
	return ' #'..hext[1]..hext[2]..hext[3]
end -- function convdh

-- function converts '#rrggbb' or '#rgb' to 'ddd ddd ddd'
function p.tinctgpl (parm)
	local gpar = parm.args
	local dtab = {}
	local decval = convdec ( gpar[1] );
	local l = '' -- '{{#tag:span|&nbsp;&nbsp;&nbsp;&nbsp;|style="width:2en;background:'..gpar[1]..'"}}'
	local f = ''
	local x = ' '
	for i = 1, 3 do
		dtab [i] = ' \\A0' .. tostring (decval [i])
		if decval[i] < 100 then
			dtab [i] = "&nbsp;" .. dtab [i]
			if decval[i] < 10 then 
				dtab [i] = "&nbsp;" .. dtab [i]
			end
		end
	end
--  checks the contrast color (000 or FFF) when any
	if gpar[2] ~= nil and gpar[2] ~= decval[4] then f = '⋅' end
	if #gpar[1] == 4 then x = '\\A0\\20\\A0\\20' end
	return dtab[1] .. dtab[2] .. dtab[2] .. l .. gpar[1] .. x .. gpar[3] .. f
end -- function tinctgpl


-- hex n' dec   with 3 parms
function p.hexndec ( frame )
	local gpar = frame.args;
	local hcode = mw.ustring.trim ( convdh ( gpar[1], gpar[2], gpar[3] ) );
	return p.decode ( hcode ) ..  p.convhd ( hcode );
end	-- function hexndec


--  main function tincture
--nction p.main (frame)
function p.tinc (frame)
	local getArgs = require( 'Module:Arguments' ).getArgs
	local args = getArgs(frame)
	local ss = args.ss  or '0'
	if ss == '≈' then ss = '0' end
	local tc = args.tc
	local pf = args.pf
	local gt = args.gpltab or ""
	local align = 'tincturebox-left'
	local error_cat = true
	local InFi = (args['+'] == '+')
	local cols = args
	local colors = {}
	local box = {}
	local tab = {}
	local out = {}
	if gt == "" then 
		if mw.title.getCurrentTitle().namespace == 4 then gt = '3' 
		else gt = '1'
		end
	end
	if gt == "2" or gt == "3" then
		InFi = true
		error_cat = false
	end

	ss = mw.ustring.upper( ss )
	if type(args[1]) == 'string' and args[1]:sub(1, 6) == '<table' then
		return args[1]
	end

	if args[2] == nil  then
		cols = mw.text.split(args[1] or '', '%s*/%s*')
	end
	for _, v in ipairs(cols) do
		if not v or v == '' then
			break
		elseif v == '-' then
			error_cat = false
		elseif v == '+' then
			InFi = true
		else  --if mw.ustring.sub( v, 1, 3 ) ~= 'ss=' then
			table.insert(colors, v)
		end
	end
	
--  0) headline
	if gt == "2" or gt =="3" then
		table.insert(out, frame:expandTemplate{title='=', args={'<h4>GPLtab '..draw('gpltabnam',ss,'','','tab')..'</h4>'}})
	end

	for i, v in ipairs(colors) do
		box[i] = draw(v, ss, tc, pf, 'box')
	end

-- 1) cat
	if error_cat == true then
		table.insert(box, category(colors, ss, tc, args.cat, no_error_cat))
	end

-- 2) box
	if gt == "1" or gt =="3" then
		if args.align == 'right' or args.align == 'center' then
			align = 'tincturebox-' .. align
		end
		local frame = mw.getCurrentFrame()
		text = frame:extensionTag('templatestyles', '', { src = 'Tincture/styles.css' }) ..
			'<div class="tincturebox ' .. align .. '">' .. table.concat(box) .. '</div>'
		if InFi then
			local name = mw.getContentLanguage():ucfirst(frame:expandTemplate{ title = 'I18n/COA', args = { 'tincture' } })
			local link = ' ([[Template:Tincture/draw'..ss..'|'..ss..']])'
			if ss ~= '' and ss ~= '0' then name = name .. link end 
			table.insert(out, frame:expandTemplate{ title = 'InFi', args = { name, text } })
		else
			table.insert(out, text )
		end
	end
	
-- 3) tab
	if gt == "2" or gt =="3" then
		table.insert(out, frame:expandTemplate{ title = '=', args = { "<big>GIMP Palette</big><br>'''Name:''' "..ss.."<br>&#35;<br>"} })
		for i, v in ipairs(colors) do
			table.insert(out, draw( v, ss, tc, pf, 'tab') )
		end
		table.insert(out, frame:expandTemplate{ title = '=', args = { "<br><br>" } })
	end
	return table.concat(out)
end -- function main / tincture 

--		update module:Iteration
-- get extension text (uppercased) 
function p.exttext ( )
	local page = mw.title.getCurrentTitle().text;
	local ptab = mw.text.split(page , '.', true)
	return		 mw.ustring.upper( table.concat(ptab, '', #ptab  ) )
end -- end function extText

-- simple iterations - for param pairs 
function p.iterat2 (frame) 
	local gpar = frame.args			-- global parms
	local v1   = "";				-- 1st of pair
	local titl = gpar [1] or "";	-- template name
	local var1 = gpar [2] or "";	-- positional p1
	local var2 = gpar [3] or "";	-- positional p2
	local ppar = mw.getCurrentFrame(): getParent().args;
	local otab = {};
	for _, v in ipairs(ppar) do
		if v1 == "" then   
			v1 = mw.text.trim( v );
		else
			table.insert(otab, frame:expandTemplate{ title = titl, args = { v1, mw.text.trim(v), var1, var2 } });
			v1 = "";
		end
	end
	return  table.concat (otab)
end -- function iterat2

-- check whether it is a new Inkscape file
function p.inkscape ( frame )
	local otab = {}
	if p.exttext () == "SVG" then
		local cat = "Unspec New SVG created with Inkscape"
		local key = "{{padleft:{{#expr:{{CURRENTYEAR}}  -{{REVISIONYEAR}}}}|2|0}}"
		key = key .."{{padleft:{{#expr:{{CURRENTMONTH2}}-{{REVISIONMONTH}}}}|2|0}}"
		key = key .."{{padleft:{{#expr:{{CURRENTDAY2}}  -{{REVISIONDAY2}}}}|2|0}}"
		table.insert(otab, frame:expandTemplate{ title = "Igen/cat", args = {cat, key } });
		return  table.concat (otab);
	else 
		return  "";
	end
end -- end function inkscape

-- 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 = "&#32;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



return p; --