Jump to content

Module:Formatting: Difference between revisions

From The Petit Planet Wiki
No edit summary
No edit summary
 
Line 1: Line 1:
-- Source: https://genshin-impact.fandom.com/wiki/Module:Formatting
local p = {}
local p = {}
local lib = require('Module:Feature')
local lib = require('Module:Feature')
local search = lib.inArray
local search = lib.inArray
local nw = mw.text.nowiki


function p.main(frame)
function p.main(frame)
Line 10: Line 9:
removeBlanks = false
removeBlanks = false
})
})
local main = args['text'] or args[1]
local label = args['label'] or args[2] or ''
-- helper function to parse params
local r_s,r_e,b,i,u_s,u_e,v_s,v_e = '','','','','','','',''
function FP(arr, val, def, noBlk)
if main == nil then error('A value must be given') end
local param = nil
local nw = mw.text.nowiki
for _, v in ipairs(arr) do
local out = mw.html.create(lib.ternary(args.NC,'span','code'))
if param == nil and args[v]~=nil then
if args.block then
param = val and args[v] or v
out:addClass('code-block' .. lib.ternary(main:find('Infobox'),'-table',''))
end
if not noBlk then
args[v]=nil
end
end
return param or def
end
end


--check what to add, leave variable blank if option wasn't enabled
-- Define variables
if (args['ref'] or args['r']) then
local main = args[1]; assert(main, 'A value must be given'); main = {main, main}
r_s = '<ref>'
local label = FP({'label', 2}, true, '', true); label = {label, label}
r_e = '</ref>'
end
local mode = FP({'link', 'l', 'external-link', 'el', 'template', 't'}) or 'plain'
if (args['bold'] or args['b']) then
local ret  = FP({'_Ybr_', '_Yn_', '_Y_'}) or 'none'
b = "'''"
local spc  = FP({'block'}) or 'inline'
end
local lprs = FP({'let_parse'}) ~= nil
if (args['italic'] or args['i']) then
local code = FP({'NC'}) == nil
i = "''"
local var  = FP({'variable', 'v'}) ~= nil
end
local esc  = FP({'nowiki', 'nw'}) and nw or (function(a)return a end)
if (args['underline'] or args['u']) then
local infobox = FP({'_infobox'}) ~= nil or main[1]:find('Infobox')
u_s = '<u>'
local content -- for actual render storage
u_e = '</u>'
local final = mw.html.create()
end
local out  = final:tag('span')
if (args['variable'] or args['v']) then
:addClass(table.concat({
main = tostring(mw.html.create():tag("span"):addClass('variable'):wikitext(nw(main)))
'custom-formatting-code',
end
code and '' or 'custom-formatting-plain',
if lib.isNotEmpty(label) and (args['variable-label'] or args['vl']) then
spc=='block' and ('code-block' .. lib.ternary(infobox,'-table','')) or ''
label = tostring(mw.html.create():tag("span"):addClass('variable'):wikitext(nw(label)))
}, ' '))
end
-- Define defaults
local _d = {
['pipe'] = '|',
['open'] = ({
['link'] = '[[', ['l'] = '[[',
['external-link'] = '[', ['el'] = '[',
['template'] = '{{', ['t'] = '{{',
['plain'] = ''
})[mode],
['close'] = ({
['link'] = ']]', ['l'] = ']]',
['external-link'] = ']', ['el'] = ']',
['template'] = '}}', ['t'] = '}}',
['plain'] = ''
})[mode],
['join'] = ((
FP({'no_joint'}) or
((mode=='t' or mode=='template') and infobox)
) and '')
or ({
['_Ybr_'] = ' yields:<br>',
['_Yn_'] = ' yields:\n',
['_Y_'] = ' yields: ',
['none'] = ''
})[ret],
ref = FP({'ref', 'r'}) and {'<ref>', '</ref>'} or {'',''},
bold = FP({'bold', 'b'}) and {'<b>', '</b>'} or {'',''},
italic = FP({'italic', 'i'}) and {'<i>', '</i>'} or {'',''},
under = FP({'underline', 'u'}) and {'<u>', '</u>'} or {'',''},
}
_d.prefix = table.concat({ FP({'prefix'},true,''), _d.ref[1], _d.bold[1], _d.italic[1], _d.under[1] }):gsub('{_SP_}', ' '):gsub('{_NL_}', '\n')
_d.suffix = table.concat({ _d.under[2], _d.italic[2], _d.bold[2], _d.ref[2], FP({'suffix'},true,''), }):gsub('{_SP_}', ' '):gsub('{_NL_}', '\n')


local prefix = r_s .. b .. i .. u_s
-- Variable formatting
local suffix = u_e .. i .. b .. r_e
if var then main[2] = '(('..main[2]..'))' end
if FP({'variable-label', 'vl'})~=nil and lib.isNotEmpty(label[2]) then label[2] = '(('..label[2]..'))' end
local joint = ' yields: '
--create result as plain text
if args['no_joint'] then joint = ' ' end
if mode == 'plain' then
out:wikitext(
if args['_Ybr_'] then
nw(_d.prefix),
joint = joint .. '<br />'
esc(main[2]),
elseif args['_Yn_'] then
nw(_d.suffix)
joint = joint .. '\n'
)
end
if ret ~= 'none' or not code then
 
content = frame:preprocess(table.concat({
--create result as internal link
_d.prefix,
if (args['link'] or args['l']) then
main[1],
if lib.isNotEmpty(label) then
_d.suffix
out
}))
:wikitext(nw(prefix),nw('[['),p.variableFormat(main),nw('|'),p.variableFormat(label),nw(']]'),nw(suffix))
else
out
:wikitext(nw(prefix),nw('[['),p.variableFormat(main),nw(']]'),nw(suffix))
end
end
if (args['_Ybr_'] or args['_Y_'] or args['_Yn_']) then
local content = b .. i .. u_s  .. '[[' .. main .. '|' .. (lib.isNotEmpty(label) and label) or main .. ']]' .. u_e .. i .. b
--create result as wiki link
if (args['ref'] or args['r']) then
elseif search({'link', 'l'}, mode) then
return tostring(out) .. joint .. frame:extensionTag{ name = 'ref', content = content}
out:wikitext(
else
nw(_d.prefix),
return tostring(out) .. joint .. content
nw(_d['open']),
end
esc(main[2]),
lib.isEmpty(label[2]) and '' or
(nw(_d.pipe) .. esc(label[2])),
nw(_d['close']),
nw(_d.suffix)
)
if ret ~= 'none' or not code then
content = frame:preprocess(table.concat({
_d.prefix,
main[1],
(
label[1]=='' and ''
or (_d.pipe .. label[1])
),
_d.suffix
}))
end
end


--create result as external link
--create result as external link
elseif (args['external-link'] or args['el']) then
elseif search({'external-link', 'el'}, mode) then
if lib.isNotEmpty(label) then
out:wikitext(
out
nw(_d.prefix),
:wikitext(nw(prefix),nw('['),p.variableFormat(nw(mw.text.unstrip(main))),' ',p.variableFormat(label),nw(']'),nw(suffix))
nw(_d['open']),
else
nw(main[2]),
out
lib.isEmpty(label[2]) and '' or
:wikitext(nw(prefix),nw('['),p.variableFormat(nw(mw.text.unstrip(main))),nw(']'),nw(suffix))
(' ' .. esc(label[2])),
nw(_d['close']),
nw(_d.suffix)
)
if ret ~= 'none' or not code then
content = frame:preprocess(table.concat({
_d.prefix,
main[1],
(
label[1]=='' and ''
or (' ' .. label[1])
),
_d.suffix
}))
end
end
if (args['_Ybr_'] or args['_Y_'] or args['_Yn_']) then
elseif search({'template', 't'}, mode) then
local content = b .. i .. u_s  .. '[' .. main .. ' ' .. label .. ']' .. u_e .. i .. b
if (args['ref'] or args['r']) then
return tostring(out) .. joint .. frame:extensionTag{ name = 'ref', content = content}
else
return tostring(out) .. joint .. content
end
end
 
elseif (args['template'] or args['t']) then
local SPECIAL = {'_Y_','_Ybr_','_Yn_','let_parse','block','t','template','NC','ref','r','b','boid','i','italic','u','underline','v','variable'}
local yieldargs = {}
local yieldargs = {}
local pre = main
local pre = main[1]
if not main:find('User:') then
local t_prefix = lib.split(pre, ':')[1]
pre = 'Template:' .. main
if not lib.inArray({'User', 'U', 'Project', 'Genshin Impact Wiki'}, t_prefix) then
pre = 'Template:' .. pre
end
end
main = '[[' .. pre .. '|' .. main:gsub(' ','&nbsp;') .. ']]'
out:wikitext(
 
nw(_d.prefix),
nw(_d['open']),
'[[', pre, '|', main[2]:gsub(' ','&nbsp;'), ']]'
)
--template call with params
--template call with params
if p.checkParams(args,SPECIAL) then
if p.checkParams(args) then
--open fake template call
out
:wikitext(nw(prefix),nw('{{'),main)
local param = 1
local param = 1
while (args['v'..param] or args['P' .. param] or args['p' .. param] or args[param+1]) do
while (args['V'..param] or args['v'..param] or args['P' .. param] or args['p' .. param] or args[param+1]) do
--variable input format
local _p = FP({'V'..param, 'v'..param, 'P' .. param, 'p' .. param, param+1}, nil, nil, true)
if args['v'..param] then
local _v = FP({'V'..param, 'v'..param, 'P' .. param, 'p' .. param, param+1}, true)
local parse = p.parseParam(args['v'..param])
local sett = {
 
p     = _p,
if args.block then
v      = _v,
out:wikitext('<br />')
cmmt  = FP({_p..'_comment'}, true),
end
prefix = FP({_p..'_pref'}, true) or (spc=='block' and '<br>') or '',
 
suffix = FP({_p..'_suff'}, true) or '',
--named param format
parse  = lprs or search({'V', 'P'}, (tostring(_p):sub(1,1))),
if parse.value then
var    = var or search({'V', 'v'}, (tostring(_p):sub(1,1))),
out
param = p.parseParam(_v, _p)
:wikitext(nw('|'),'<b>',p.variableFormat(nw(parse.name)),'</b>',string.rep('&nbsp;',parse.spacing),'= ',tostring(mw.html.create():tag("span"):addClass('variable'):wikitext(p.NewLineAllow(parse.value, args.let_parse))))
}
 
out:wikitext(sett.prefix)
--unnamed param format
if sett.cmmt then
else
out:wikitext('<br>((!-- ', nw(sett.cmmt), ' --))<br>')
out
end
:wikitext(nw('|'),tostring(mw.html.create():tag("span"):addClass('variable'):wikitext(p.NewLineAllow(parse.name, args.let_parse))))
out:wikitext(nw(_d.pipe))
end
--named param only
args['v' .. param] = nil
if type(sett.param.name) == 'string' and sett.param.name ~= sett.p then
 
out
--fixed input format
:tag('b'):wikitext(nw(sett.param.name)):done()
elseif (args['p' .. param] or args[param+1]) then
:wikitext(string.rep('&nbsp;',sett.param.spacing),'=&nbsp;')
local value = args['p' .. param] or args[param+1]
local parse = p.parseParam(value)
 
if args.block then
out:wikitext('<br />')
end
 
--named param format
if parse.value then
yieldargs[parse.name] = mw.text.unstrip(parse.value)
out
:wikitext(nw('|'),'<b>',p.variableFormat(nw(parse.name)),'</b>',string.rep('&nbsp;',parse.spacing),'= ',p.NewLineAllow(p.variableFormat(parse.value), args.let_parse))
 
--unnamed param format
else
yieldargs[param] = mw.text.unstrip(parse.name)
out
:wikitext(nw('|'),p.NewLineAllow(p.variableFormat(parse.name), args.let_parse))
end
--set values to nil for yield to ignore them
if args['p' .. param] then args['p' .. param] = nil end
if args[param+1] then args[param+1] = nil end
--fixed input format, default let parse
elseif args['P' .. param] then
local value = args['P' .. param]
local parse = p.parseParam(value)
 
if args.block then
out:wikitext('<br />')
end
 
--named param format
if parse.value then
yieldargs[parse.name] = mw.text.unstrip(parse.value)
out
:wikitext(nw('|'),'<b>',p.variableFormat(nw(parse.name)),'</b>',string.rep('&nbsp;',parse.spacing), '= ', p.NewLineAllow(p.variableFormat(parse.value), true))
 
--unnamed param format
else
yieldargs[param] = mw.text.unstrip(parse.name)
out
:wikitext(nw('|'),p.NewLineAllow(p.variableFormat(parse.name), true))
end
--set values to nil for yield to ignore them
args['P' .. param] = nil
end
end
 
out:wikitext(
sett.var and '((' or '',
p.NewLineAllow(sett.param.value, sett.parse),
sett.var and '))' or ''
)
out:wikitext(sett.suffix)
-- store param value
yieldargs[sett.param.name] = mw.text.unstrip(sett.param.value)
--increase count for the next 'while' loop
--increase count for the next 'while' loop
param = param + 1
param = param + 1
Line 183: Line 198:
for n,v in pairs(args) do
for n,v in pairs(args) do
if (n ~= 1 and not search(SPECIAL,n)) then
if (n ~= 1) then
out:wikitext(
(spc=='block' and '<br>') or '',
nw(_d.pipe),'<b>',nw(n),'</b> = ',
p.NewLineAllow(v, lprs)
)
yieldargs[n] = mw.text.unstrip(v)
yieldargs[n] = mw.text.unstrip(v)
if args.block then
out:wikitext('<br />')
end
out:wikitext(nw('|'),'<b>',p.variableFormat(nw(n)),'</b> = ',p.NewLineAllow(p.variableFormat(v),args.let_parse))
end
end
end
end
if args.block then
out:wikitext('<br />')
end
--close fake template call and all the selected items
out
:wikitext(nw('}}'),nw(suffix))
--template call without params
else
out
:wikitext(nw(prefix),nw('{{'),main,nw('}}'),nw(suffix))
end
end
out:wikitext((spc=='block' and '<br>') or '', nw(_d['close']), nw(_d.suffix))


--auto fake template usage for examples
-- auto template result for examples
if (args['_Ybr_'] or args['_Y_'] or args['_Yn_']) then
if ret~='none' or not code then
frame = frame or mw.getCurrentFrame()
content = _d.prefix .. frame:expandTemplate{title = main[1], args = yieldargs} .. _d.suffix
local param = 1
local content = b .. i .. u_s .. frame:expandTemplate{title = (args['text'] or args[1]),args = yieldargs} .. u_e .. i .. b
if args.block then
joint = '<br />' .. joint
end
if (args['ref'] or args['r']) then
return tostring(out) .. joint .. frame:extensionTag{ name = 'ref', content = content}
else
if main:find('Infobox') then
return content .. tostring(out)
else
return tostring(out) .. joint .. content
end
end
end
end
 
end
--create plain text result
else
if content and (ret ~= 'none' or not code) then
if (args['nowiki'] or args['nw']) then
if content:find('<ref') then
out
local c_p,c_r,c_s = string.match(content, '^(.-)<ref>(.-)</ref>(.-)$')
:wikitext(nw(prefix),p.variableFormat(nw(main)),nw(suffix))
content = c_p .. frame:extensionTag{ name = 'ref', content = c_r } .. c_s
else
out
:wikitext(nw(prefix),p.variableFormat(main),nw(suffix))
end
end
if (args['_Ybr_'] or args['_Y_'] or args['_Yn_']) then
if ret ~= 'none' then
local content = b .. i .. u_s  .. main .. u_e .. i .. b
if infobox then
if (args['ref'] or args['r']) then
final = mw.html.create()
return tostring(out) .. joint .. frame:extensionTag{ name = 'ref', content = content}
:wikitext(content)
:node(final)
else
else
return tostring(out) .. joint .. content
final:wikitext(
(spc=='block' and '<br>' or ' '),
_d.join,
content
)
end
end
elseif not code then
out:addClass('custom-formatting-nested')
final:tag('span'):addClass('custom-formatting-resulting'):wikitext(content)
end
end
end
end
 
--return completed result
-- Parse keywords
return tostring(out)
final = tostring(final):gsub('{_SP_}', ' '):gsub('{_NL_}', '\n')
 
final = p.variableFormat(final)
return final
end
end


function p.parseParam(param)
function p.parseParam(param, pName)
    local tmp = param
local tmp = param
    local name, value, spacing = '','',' '
local name, value, spacing = '','',1
 
    -- the parameter's name is anything to the left of the first equals sign;
-- the parameter's name is anything to the left of the first equals sign;
    -- the equals sign can be escaped, for wikis that don't have [[Template:=]]
-- the equals sign can be escaped, for wikis that don't have [[Template:=]]
    if tmp:find('=') then
if tmp:find('=') then
        name, spacing, value = string.match(tmp,'^(.-)(%s*)=%s*(.-)$')
name, spacing, value = string.match(tmp,'^(.-)(%s*)=%s*(.-)$')
        if string.len(spacing) == 0 then spacing = 1 else spacing = string.len(spacing) end
if string.len(spacing) == 0 then spacing = 1 else spacing = string.len(spacing) end
    else
else
    name = tmp
name = type(pName)=='number'
    value = false
and (pName-1)
    end
or tonumber((pName:gsub('[^%d]+', '')))
    return {
value = tmp
    name = name,
end
    value = value,
return {
    spacing = spacing
name = name,
    }
value = value,
spacing = spacing
}
end
end


Line 272: Line 271:
while (textin:find('%(%(') and textin:find('%)%)')) do
while (textin:find('%(%(') and textin:find('%)%)')) do
local textrp = string.match(textin,'%(%((.-)%)%)')
local textrp = string.match(textin,'%(%((.-)%)%)')
textin = textin:gsub('%(%(.-%)%)',tostring(mw.html.create():tag("span"):addClass('variable'):wikitext(mw.text.nowiki(textrp))),1)
textin = textin:gsub('%(%(.-%)%)',tostring(mw.html.create():tag("span"):addClass('variable'):wikitext(textrp)),1)
end
end
return textin
return textin
end
end


function p.checkParams(args,SPECIAL)
function p.checkParams(args)
for n,v in pairs(args) do
for n,v in pairs(args) do
if (n ~= 1 and not search(SPECIAL,n)) then
if (n ~= 1 and v~=nil) then
return true
return true
end
end
Line 287: Line 286:


--helper function to allow new line format in template calls in block format, as directly allowing makes the <code> container break
--helper function to allow new line format in template calls in block format, as directly allowing makes the <code> container break
function p.NewLineAllow(str,parse)
function p.NewLineAllow(str, parse)
local container = mw.html.create()
local container = mw.html.create()
local nw = mw.text.nowiki
local nw = mw.text.nowiki
if str:find('[\n\r]') then
if str:find('[\n\r]') then
str = str:gsub('[\n\r]', '¤¤¤')
str = str:gsub('[\n\r]', '¤¤¤'):gsub('¤¤¤$', '')
local splitstr = mw.text.split(str, '¤¤¤', true )
local splitstr = mw.text.split(str, '¤¤¤', true )
for i,v in ipairs(splitstr) do
for i,v in ipairs(splitstr) do
Line 298: Line 297:
container:wikitext(v)
container:wikitext(v)
if i ~= #splitstr then
if i ~= #splitstr then
container:wikitext('<br />')
container:wikitext('<br>')
end
end
end
end

Latest revision as of 12:46, 10 November 2025

Documentation for this module may be created at Module:Formatting/doc

local p = {}
local lib = require('Module:Feature')
local search = lib.inArray
local nw = mw.text.nowiki

function p.main(frame)
	local args = require('Module:Arguments').getArgs(frame, {
		parentFirst = true,
		removeBlanks = false
	})
	
	-- helper function to parse params
	function FP(arr, val, def, noBlk)
		local param = nil
		for _, v in ipairs(arr) do
			if param == nil and args[v]~=nil then
				param = val and args[v] or v
			end
			if not noBlk then
				args[v]=nil
			end
		end
		return param or def
	end

	-- Define variables
	local main = args[1]; assert(main, 'A value must be given'); main = {main, main}
	local label = FP({'label', 2}, true, '', true); label = {label, label}
		
	local mode = FP({'link', 'l', 'external-link', 'el', 'template', 't'}) or 'plain'
	local ret  = FP({'_Ybr_', '_Yn_', '_Y_'}) or 'none'
	local spc  = FP({'block'}) or 'inline'
	local lprs = FP({'let_parse'}) ~= nil
	local code = FP({'NC'}) == nil
	local var  = FP({'variable', 'v'}) ~= nil
	local esc  = FP({'nowiki', 'nw'}) and nw or (function(a)return a end)
	local infobox = FP({'_infobox'}) ~= nil or main[1]:find('Infobox')
	local content -- for actual render storage
	local final = mw.html.create()
	local out  = final:tag('span')
		:addClass(table.concat({
			'custom-formatting-code',
			code and '' or 'custom-formatting-plain',
			spc=='block' and ('code-block' .. lib.ternary(infobox,'-table','')) or ''
		}, ' '))
	
	-- Define defaults
	local _d = {
		['pipe'] = '|',
		['open'] = ({
			['link'] = '[[', ['l'] = '[[',
			['external-link'] = '[', ['el'] = '[',
			['template'] = '{{', ['t'] = '{{',
			['plain'] = ''
		})[mode],
		['close'] = ({
			['link'] = ']]', ['l'] = ']]',
			['external-link'] = ']', ['el'] = ']',
			['template'] = '}}', ['t'] = '}}',
			['plain'] = ''
		})[mode],
		['join'] = ((
				FP({'no_joint'}) or
				((mode=='t' or mode=='template') and infobox)
			) and '')
			or ({
				['_Ybr_'] = ' yields:<br>',
				['_Yn_'] = ' yields:\n',
				['_Y_'] = ' yields: ',
				['none'] = ''
			})[ret],
		ref = FP({'ref', 'r'}) and {'<ref>', '</ref>'} or {'',''},
		bold = FP({'bold', 'b'}) and {'<b>', '</b>'} or {'',''},
		italic = FP({'italic', 'i'}) and {'<i>', '</i>'} or {'',''},
		under = FP({'underline', 'u'}) and {'<u>', '</u>'} or {'',''},
	}
	_d.prefix = table.concat({ FP({'prefix'},true,''), _d.ref[1], _d.bold[1], _d.italic[1], _d.under[1] }):gsub('{_SP_}', ' '):gsub('{_NL_}', '\n')
	_d.suffix = table.concat({ _d.under[2], _d.italic[2], _d.bold[2], _d.ref[2], FP({'suffix'},true,''), }):gsub('{_SP_}', ' '):gsub('{_NL_}', '\n')

	-- Variable formatting
	if var then main[2] = '(('..main[2]..'))' end
	if FP({'variable-label', 'vl'})~=nil and lib.isNotEmpty(label[2]) then label[2] = '(('..label[2]..'))' end
	
	--create result as plain text
	if mode == 'plain' then
		out:wikitext(
			nw(_d.prefix),
			esc(main[2]),
			nw(_d.suffix)
		)
		if ret ~= 'none' or not code then
			content = frame:preprocess(table.concat({
				_d.prefix,
				main[1],
				_d.suffix
			}))
		end
		
	--create result as wiki link
	elseif search({'link', 'l'}, mode) then
		out:wikitext(
			nw(_d.prefix),
			nw(_d['open']),
			esc(main[2]),
				lib.isEmpty(label[2]) and '' or
				(nw(_d.pipe) .. esc(label[2])),
			nw(_d['close']),
			nw(_d.suffix)
		)
		if ret ~= 'none' or not code then
			content = frame:preprocess(table.concat({
				_d.prefix,
				main[1],
				(
					label[1]=='' and ''
					or (_d.pipe .. label[1])
				),
				_d.suffix
			}))
		end

	--create result as external link
	elseif search({'external-link', 'el'}, mode) then
		out:wikitext(
			nw(_d.prefix),
			nw(_d['open']),
			nw(main[2]),
				lib.isEmpty(label[2]) and '' or
				(' ' .. esc(label[2])),
			nw(_d['close']),
			nw(_d.suffix)
		)
		if ret ~= 'none' or not code then
			content = frame:preprocess(table.concat({
				_d.prefix,
				main[1],
				(
					label[1]=='' and ''
					or (' ' .. label[1])
				),
				_d.suffix
			}))
		end
	elseif search({'template', 't'}, mode) then
		local yieldargs = {}
		local pre = main[1]
		local t_prefix = lib.split(pre, ':')[1]
		if not lib.inArray({'User', 'U', 'Project', 'Genshin Impact Wiki'}, t_prefix) then
			pre = 'Template:' .. pre
		end
		out:wikitext(
			nw(_d.prefix),
			nw(_d['open']),
			'[[', pre, '|', main[2]:gsub(' ','&nbsp;'), ']]'
		)
		
		--template call with params
		if p.checkParams(args) then
			local param = 1
			while (args['V'..param] or args['v'..param] or args['P' .. param] or args['p' .. param] or args[param+1]) do
				local _p = FP({'V'..param, 'v'..param, 'P' .. param, 'p' .. param, param+1}, nil, nil, true)
				local _v = FP({'V'..param, 'v'..param, 'P' .. param, 'p' .. param, param+1}, true)
				local sett = {
					p      = _p,
					v      = _v,
					cmmt   = FP({_p..'_comment'}, true),
					prefix = FP({_p..'_pref'}, true) or (spc=='block' and '<br>') or '',
					suffix = FP({_p..'_suff'}, true) or '',
					parse  = lprs or search({'V', 'P'}, (tostring(_p):sub(1,1))),
					var    = var or search({'V', 'v'}, (tostring(_p):sub(1,1))),
					param  = p.parseParam(_v, _p)
				}
				out:wikitext(sett.prefix)
				if sett.cmmt then
					out:wikitext('<br>((!-- ', nw(sett.cmmt), ' --))<br>')
				end
				out:wikitext(nw(_d.pipe))
				--named param only
				if type(sett.param.name) == 'string' and sett.param.name ~= sett.p then
					out
						:tag('b'):wikitext(nw(sett.param.name)):done()
						:wikitext(string.rep('&nbsp;',sett.param.spacing),'=&nbsp;')
				end
				out:wikitext(
					sett.var and '((' or '',
					p.NewLineAllow(sett.param.value, sett.parse),
					sett.var and '))' or ''
				)
				out:wikitext(sett.suffix)
				
				-- store param value
				yieldargs[sett.param.name] = mw.text.unstrip(sett.param.value)
				
				
				--increase count for the next 'while' loop
				param = param + 1
			end
			
			for n,v in pairs(args) do
				if (n ~= 1) then
					out:wikitext(
						(spc=='block' and '<br>') or '',
						nw(_d.pipe),'<b>',nw(n),'</b> = ',
						p.NewLineAllow(v, lprs)
					)
					yieldargs[n] = mw.text.unstrip(v)
				end
			end
		end
		out:wikitext((spc=='block' and '<br>') or '', nw(_d['close']), nw(_d.suffix))

		-- auto template result for examples
		if ret~='none' or not code then
			content = _d.prefix .. frame:expandTemplate{title = main[1], args = yieldargs} .. _d.suffix
		end
	end
	
	if content and (ret ~= 'none' or not code) then
		if content:find('<ref') then
			local c_p,c_r,c_s = string.match(content, '^(.-)<ref>(.-)</ref>(.-)$')
			content = c_p .. frame:extensionTag{ name = 'ref', content = c_r } .. c_s
		end
		if ret ~= 'none' then
			if infobox then
				final = mw.html.create()
					:wikitext(content)
					:node(final)
			else
				final:wikitext(
					(spc=='block' and '<br>' or ' '),
					_d.join,
					content
				)
			end
		elseif not code then
			out:addClass('custom-formatting-nested')
			final:tag('span'):addClass('custom-formatting-resulting'):wikitext(content)
		end
	end
	
	-- Parse keywords
	final = tostring(final):gsub('{_SP_}', ' '):gsub('{_NL_}', '\n')
	final = p.variableFormat(final)
	
	return final
end

function p.parseParam(param, pName)
	local tmp = param
	local name, value, spacing = '','',1
	
	-- the parameter's name is anything to the left of the first equals sign;
	-- the equals sign can be escaped, for wikis that don't have [[Template:=]]
	if tmp:find('=') then
		name, spacing, value = string.match(tmp,'^(.-)(%s*)=%s*(.-)$')
		if string.len(spacing) == 0 then spacing = 1 else spacing = string.len(spacing) end
	else
		name = type(pName)=='number'
			and (pName-1)
			or tonumber((pName:gsub('[^%d]+', '')))
		value = tmp
	end
	return {
		name = name,
		value = value,
		spacing = spacing
	}
end

function p.variableFormat(textin)
	while (textin:find('%(%(') and textin:find('%)%)')) do
		local textrp = string.match(textin,'%(%((.-)%)%)')
		textin = textin:gsub('%(%(.-%)%)',tostring(mw.html.create():tag("span"):addClass('variable'):wikitext(textrp)),1)
	end
	return textin
end

function p.checkParams(args)
	for n,v in pairs(args) do
		if (n ~= 1 and v~=nil) then
			return true
		end
	end
	return false
end

--helper function to allow new line format in template calls in block format, as directly allowing makes the <code> container break
function p.NewLineAllow(str, parse)
	local container = mw.html.create()
	local nw = mw.text.nowiki
	
	if str:find('[\n\r]') then
		str = str:gsub('[\n\r]', '¤¤¤'):gsub('¤¤¤$', '')
		local splitstr = mw.text.split(str, '¤¤¤', true )
		for i,v in ipairs(splitstr) do
			if not parse then v = nw(v) end
			container:wikitext(v)
			if i ~= #splitstr then
				container:wikitext('<br>')
			end
		end
		return tostring(container)
	else
		if not parse then str = nw(str) end
		return str
	end
end

return p