мНет описания правки |
м (oops) |
||
Строка 441: | Строка 441: | ||
end-- tabletrim |
end-- tabletrim |
||
− | function p. |
+ | function p.tlm (frame) |
--template:tlocmission |
--template:tlocmission |
||
Версия от 22:30, 13 июля 2019
Для документации этого модуля может быть создана страница Модуль:Nutils/doc
--<syntaxhighlight lang="lua">
--local hasc = require('Dev:Pageinfo')
--local getArgs = require("Dev:Arguments").getArgs
local p = {}
function p.hello( frame )
local nt = ''
nt = nt .. '<div contenteditable="true" id="el1" tabindex="0">element1</div>'
return nt --"Hello, world!"
end --hello
function p.tst (frame)
local args = frame.args or frame
return p.hasbit(3, p.bit(1))
end --tst
function p.tst2 (frame)
local arg1 = frame.args[1]
local ns = ''
local ns1 = ''
--ns = '[[' .. args[1] .. ']]'
--ns = arg1
--ns = frame:newParserValue(ns):expand()
--ns = frame:preprocess(ns)
for i = 1, mw.ustring.len(ns) do
ns1 = ns1..'_'..mw.ustring.sub(ns, i, i)
end
ns = ns .. ns1
return ns
end --tst2
function p.rainbow (frame)
-- draws rainbow text
if not frame or not frame.args then return end
-- debug console defence
-- get frame.args if arg[1] or frame:parent.args
local args = frame.args
if not args['1'] or not args[1] then
args = (frame.getParent and frame:getParent() or frame).args
end
local text = args['1'] or args[1]
if not text then return '' end
local ret = {}-- table is fastest way to deal with strings
local linkIndex, _, linkHead, linkLink, linkAlias, linkTail = text:find('(.-)%[%[([^]]-)|([^]]+)%]%](.*)', 1, false)
if linkIndex then
table.insert(ret, linkHead or '')
table.insert(ret, '[[')
table.insert(ret, linkLink)
table.insert(ret, '|')
table.insert(ret, rainbowize(linkAlias))
table.insert(ret, ']]')
table.insert(ret, linkTail or '')
else
return rainbowize(text)
end
return table.concat(ret)
end-- rainbow
function rainbowize (text)
-- rainbowize the text
if not text then return '' end
-- color array: red, orange, yellow, greenyellow, cyan, deepskyblue, violet
local rainbow = {'#ff0000', '#ffa500', '#ffff00', '#adff2f', '#00ffff', '#00bfff', '#ee82ee'}
local spanHead = '<span style="color:'
local spanHeadC = '">'
local spanTail = '</span>'
local ret = {}-- table is fastest way to deal with strings
for index, character in ipairs(mw.text.split(text, '')) do
local pos = math.fmod(index, #rainbow)
-- if pos == 0 (last element of the table) then return last el
pos = pos ~= 0 and pos or #rainbow
table.insert(ret, spanHead)-- open span
table.insert(ret, rainbow[pos])-- add color
table.insert(ret, spanHeadC)-- close opening
table.insert(ret, character)-- add character
table.insert(ret, spanTail)-- close span
end
return table.concat(ret)
end-- rainbowize
function p.setCatLocation (frame)
--set category by location
--1: location: location
--2: prefix: prefix
--3: postfix: postfix
local args = frame.args or frame
local location = args.location or args['1'] or args[1]
if (not location) or (#location == 0) then return end
local prefix = args.prefix or args['2'] or args[2] or ''
local postfix = args.postfix or args['3'] or args[3] or ''
--only 1 location permitted is
local s = mw.ustring.find(location, ',') or mw.ustring.find(location, '%]%].+%]%]')
if s then return end
--remove []
location = mw.ustring.match(location, '%[*([^%]|]+)%]*')
if not location then return end
location = '[[category:' .. prefix .. location .. postfix .. ']]'
return frame.preprocess and frame:preprocess(location) or location
end--setcatlocation
function p.getInterwiki (frame)
--returns interwiki link for lang
--format: lang:(link or default)|alias
--1: lang; 2: alias; 3: default link
local title = mw.title.getCurrentTitle()
local content = title:getContent()
local args = frame.args
local lang = args['1'] or args[1]
local alias = args['2'] or args[2]
local default = args['3'] or args[3]
if not lang then return '' end
local s, re, c1st, mtch
c1st = mw.ustring.sub(lang, 1, 1)
re = '%[%[[' .. mw.ustring.upper(c1st) .. mw.ustring.lower(c1st) .. ']' .. mw.ustring.lower(mw.ustring.sub(lang, 2)) .. ':([^|]-)%]%]'
mtch = mw.ustring.match(content, re)
if #mw.text.trim(alias or '') == 0 then
alias = mtch
end
s = '[[:' .. lang .. ':' .. (mtch or default) .. '|' .. (alias or default) .. ']]'
return s
end --getinterwiki
function p.hasInterwiki (frame)
--returns link if page has lang interwiki
--1: lang
local title = mw.title.getCurrentTitle()
local content = title:getContent()
local args = frame.args
local lang = args['1'] or args[1]
if not lang then return end
local re, c1st
c1st = mw.ustring.sub(lang, 1, 1)
re = '%[%[[' .. mw.ustring.upper(c1st) .. mw.ustring.lower(c1st) .. ']' .. mw.ustring.lower(mw.ustring.sub(lang, 2)) .. ':([^|]-)%]%]'
return mw.ustring.match(content, re)
end --hasinterwiki
function p.ifex (frame)
--returns: {{template:name|p1|p2|p3}} or [[page]] or [[:category:name]] or pa1
--opt is a bitwise container
--name/1: pagename, opt: options
local args = frame.args or frame
local name = args['name'] or args['1'] or args[1] or ''
local ns = args['ns'] or '' --namespace
local nsn = '' --namespaced name
local alt = args['alt'] or '' --alt text
local tail = args['tail'] or '' --tail
if tail ~= '' then
tail = ' ' .. tail
end
--opt: 1: do not search for category; 2: do not return {{{1}}}; 3: both
local opt = tonumber(args['opt']) or 0
--parent args
local parent
if frame and frame.getParent then
parent = frame:getParent()
else
parent = frame
end
--local parent = p.iif(frame.getParent, frame:getParent(), frame)
local pargs = parent.args or parent
local pa1, pa2, pa3 = pargs['1'] or pargs[1] or '', pargs['2'] or pargs[2] or '', pargs['3'] or pargs[3] or ''
-- [[{{san|pa1}}|{{san|pa1|2}}]] {{san|pa1|3}} --nothing found, make red link
local ret = name .. tail
--'{{ifexistc|{{san|1=' .. pa1 .. '}}|[[:Категория:{{san|1=' .. pa1 .. '}}|{{san|1=' .. pa1 .. '|2=2}}]] {{san|1=' .. pa1 .. '|2=3}}|' .. pa1 .. '}}'
--params
local p1, p2, p3 = args['p1'] or '', args['p2'] or '', args['p3'] or ''
--local ret = isfalse
if p.hasbit(opt, p.bit(2)) then --do not return {{{1}}}
ret = ''
end
if name ~= '' then
--capitalize name
name = mw.ustring.upper(mw.ustring.sub(name, 1, 1)) .. mw.ustring.sub(name, 2)
--normalize
name = mw.ustring.gsub(name, '_', ' ')
if ns ~= '' then nsn = mw.ustring.upper(mw.ustring.sub(ns, 1, 1)) .. mw.ustring.sub(ns, 2) .. ':' .. name end
local data = mw.loadData('module:Nbigbigdatabig')
if nsn ~= '' and data[nsn] then
if ns == 'Шаблон' or ns == 'Template' then -- template
--ret = {{nsn|{{{1|}}}|{{{2|}}}|{{{3|}}}}}
ret = '{{' .. nsn .. '|1=' .. p1 .. '|2=' .. p2 .. '|3=' .. p3 .. '}}' .. tail
else
ret = '[[' .. nsn .. p.iif(alt~='', '|' .. alt, '') .. ']]' .. tail
end
elseif data[name] then --page in ns:0
--ret = '[[{{san|{{{1}}}}}|{{san|{{{1}}}|2}}]] {{san|{{{1}}}|3}}'
--ret = '[[{{san|1=' .. pa1 .. '}}|{{san|1=' .. pa1 .. '|2=2}}]] {{san|1=' .. pa1 ..'|2=3}}'
ret = '[[' .. name .. p.iif(alt~='', '|' .. alt, '') .. ']]' .. tail
elseif not p.hasbit(opt, p.bit(1)) then --category
local scat = p.ifexc({[1]=name, [2]=alt, [3]=tail, ['opt']=1})
if scat ~= '' then
ret = scat
end
end
end
if frame and frame.preprocess then
return frame:preprocess(ret)
else
return ret
end
end --ifex
function p.ifexc (frame)
--ifexist for category
--opt is a bitwise container
--returns [[:category:name|alt]] tail or name or '' if opt:1
--or [[catefory:name|alt]] tail if opt:2
local args = frame.args or frame
local name = args['name'] or args['1'] or args[1] or ''
local alt = args['alt'] or args['2'] or args[2] or ''
local tail = args['tail'] or args['3'] or args[3] or ''
if tail ~= '' then
tail = ' ' .. tail
end
--opt: 1: do not return {{{1}}}; 2: set cat [[cat:...]]
local opt = tonumber(args['opt']) or 0
local ret = ''
if p.hasbit(opt, p.bit(1)) then
ret = ''
else
if p.hasbit(opt, p.bit(2)) then
ret = 'Категория:' .. name .. tail
else
ret = name .. tail
end
end
if name ~= '' then
--capitalize name
name = mw.ustring.upper(mw.ustring.sub(name, 1, 1)) .. mw.ustring.sub(name, 2)
--normalize
name = mw.ustring.gsub(name, '_', ' ')
local data = mw.loadData('module:nbigdatacat')
if data[name] then
if p.hasbit(opt, p.bit(2)) then
ret = '[[Категория:' .. name .. p.iif(alt~='', '|' .. alt, '') .. ']]' .. tail
else
ret = '[[:Категория:' .. name .. p.iif(alt~='', '|' .. alt, '') .. ']]' .. tail
end
end
end
if frame and frame.preprocess then
return frame:preprocess(ret)
else
return ret
end
end
function p.th (frame)
--transclude header
--according to template:th --excepts 1st param (t) -> params shifted
local args = frame.args
local ns, ncontent, npattern = ''
local ncount = tonumber(args['c'] or args[3]) or 0
local ntitle = args['d'] or args[1]
--ncount = tonumber(ncount)
--if type(args['t']) ~= 'nil' then ns=args['t'] elseif type(args[1]) ~= 'nil' then ns=args[1] end
if ((args['bylink'] or args[5] or '1') == '0') then
ncontent = (ntitle)
else
ncontent = frame:expandTemplate{ title=':' .. ntitle }
end
npattern = (args['h'] or args[2] or 'Описание')
if ncount == 0 then
npattern = '=+' .. npattern .. '=+(.-)=='
else
npattern = '=+' .. npattern .. '.-%.-=*(' .. mw.ustring.rep('[%w%s,:;%-%+%<%>]+[%<%>%.%?%!%C]+', ncount) .. ')'
end
ncontent = mw.ustring.match(ncontent, npattern)
if type(ncontent) == 'nil' then
ns = ns .. '[[Категория:th - Ошибка поиска]]' .. (args['def'] or args[4] or '')
else
ns = ns .. mw.ustring.gsub(ncontent, '<[^>]*>', '')
end
ns = frame:preprocess(ns)
return ns
end --th
function p.th2 (frame)
--faster (x5-x7), but uses expensive parser function (title*)
--transclude header
--according to template:th --excepts 1st param (t) -> params shifted
local args = frame.args or frame
local ns, ncontent, npattern = '', ''
local pname = args['d'] or args['1'] or args[1]
local pheader = args['h'] or args['2'] or args[2] or 'Описание'
local pcount = tonumber(args['c'] or args['3'] or args[3]) or 0
local pdef = args['def'] or args['4'] or args[4] or ''
local pbylink = (args['bylink'] or args['5'] or args[5] or '1') ~= '0'
local ntitle
if not pbylink then
ncontent = pname
else
ntitle = mw.title.new(pname)
if type(ntitle) ~= 'nil' then
ncontent = ntitle:getContent()
else
ncontent = frame:expandTemplate{ title=':' .. pname }
end
end
npattern = pheader
if pcount == 0 then
npattern = '=+' .. npattern .. '=+(.-)=='
else
npattern = '=+' .. npattern .. '.-%.-=*(' .. mw.ustring.rep('[%w%s,:;%-%+%<%>]+[%<%>%.%?%!%C]+', pcount) .. ')'
end
ncontent = mw.ustring.match(ncontent, npattern)
if type(ncontent) == 'nil' then
ns = ns .. '[[Категория:th - Ошибка поиска]]' .. pdef
else
ns = ns .. mw.ustring.gsub(ncontent, '<[^>]*>', '')
end
if frame.preprocess then
ns = frame:preprocess(ns)
end
--ns=mw.ustring.gsub(ns, '%z', '') --remove zero-char's
return ns --frame:preprocess(ns)
end --th2
function p.th3 (frame) --tst
local args = frame.args
local ns, ncontent, npattern = '', ''
local ncount = tonumber(args['c'] or args[3]) or 0
local ntitle
--ncount = tonumber(ncount)
--if type(args['t']) ~= 'nil' then ns=args['t'] elseif type(args[1]) ~= 'nil' then ns=args[1] end
if ((args['bylink'] or args[5] or '1') == '0') then
ncontent=(args['d'] or args[1])
else
ntitle=mw.title.new(args['d'] or args[1])
if type(ntitle) ~= 'nil' then
ncontent = ntitle:getContent()
else
ncontent = frame:expandTemplate{ title=':' .. (args['d'] or args[1]) }
end
end
npattern = (args['h'] or args[2] or 'Описание')
if ncount == 0 then
npattern = '=+' .. npattern .. '=+(.-)=='
else
npattern = '=+' .. npattern .. '=+' .. '(' .. mw.ustring.rep('.-[%.%?%!]+%s+', ncount) .. ')[=$]*'
end
ncontent = mw.ustring.match(ncontent, npattern)
if type(ncontent) == 'nil' then
ns = ns .. '[[Категория:th - Ошибка поиска]]' .. (args['def'] or args[4] or '')
else
ns = ns .. mw.ustring.gsub(ncontent, '<[^>]*>', '')
end
ns = frame:preprocess(ns)
--ns=mw.ustring.gsub(ns, '%z', '') --remove zero-char's
return ns --frame:preprocess(ns)
end --th3
function p.setcat (frame)
--set category by content
--1: page; 2,3: text; 4: cat if found; 5: cat if not found
local args = frame.args
local t1, t2 = args[2], args[3]
local nh = ''
local ptitle = mw.title.new(args[1])
local pcontent = mw.getCurrentFrame():preprocess('{{:'..ptitle.prefixedText..'}}')
--nh=mw.ustring.len(pcontent)
if type(args[3]) == 'nil' then t2 = t1 end
if mw.ustring.find(pcontent, t2, 1, true) or mw.ustring.find(pcontent, t3, 1, true) then
nh = args[4]
else
nh = args[5]
end
--nh=(ptitle.prefixedText or 'nil')
--nh=#pcontent
--nh = hasc.hascat(frame)
--nh = select('#', args)
return nh--..','..args[1]..','..(args[2] or 'nil')..','..(args[3] or 'nil')..','..(args[4] or 'nil')
end --setcat
function p.cats (frame)
--has category
local hasc = require('Dev:Pageinfo')
local args = frame.args
local nh
nh = hasc.hascat(frame)
--nh = select('#', args)
return args[1]..','..(nh or 'nil')
end --cats
function parseLinks(data, part)
-- returns {links} w\o [[]]
-- part: which part of [[link|title]] to return: link, title
-- part == table: {link: link, title: title}
if not data then return {} end
local links = {}
local patLink = '%[%[([^]]*)%]%]'-- link pattern
part = part or ''
function splitLink(link)
local al = mw.text.split(link, '|')
if part == 'link' then
link = (#al > 0 and #mw.text.trim(al[1]) > 0) and al[1] or nil
elseif part == 'title' then
link = #al > 1 and table.concat(al, '|', 2) or (#mw.text.trim(al[1]) > 0 and al[1] or nil)
elseif part == 'table' then
if #al > 0 and #mw.text.trim(al[1]) > 0 then
link = {
link = al[1],
title = #al > 1 and table.concat(al, '|', 2) or al[1]
}
else
link = nil
end
end
return link
end-- splitlink
for l in data:gmatch(patLink) do
l = splitLink(l)
if l then table.insert(links, l) end
end
if #links == 0 then
-- no links (loc w\o [[]]: sanctuary instead of [[sanctuary]])
data = splitLink(data)
table.insert(links, data)
end
return links
end-- parselinks
function tableTrim(tab)
-- removes zero/empty values from the table
if #(tab or {}) == 0 then return tab end
local i = 1
repeat
if #(tab[i] or {}) == 0 or #mw.text.trim(tab[i]) == 0 then
table.remove(tab, i)
else
i = i + 1
end
until i > #tab
return tab
end-- tabletrim
function p.tlm (frame)
--template:tlocmission
local args = frame.args
local tfull = args['1'] or args[1] or 'В этом разделе указаны задания, связанные с данной локацией. В разделе "Выдаются" указаны задания, которые берут начало в этой локации; а в разделе "Выполняются" находятся задания, для которых данная локация служит промежуточной или конечной.'
local tin = args['2'] or args[2] or 'В этом разделе указаны задания, которые берут начало в этой локации.'
local tout = args['3'] or args[3] or 'В этом разделе указаны задания, для которых данная локация служит промежуточной или конечной.'
local nret = args['4'] or args[4] or tfull -- default
local ntitle = mw.title.new((args.p and #args.p > 0) and args.p or mw.title.getCurrentTitle().text)
local mode = args.mode or '' -- auto для автосписка миссий
local game = mw.text.trim(args.game or '') -- игра
game = #game > 0 and game or nil
if mode == 'auto' then
-- автоматический список миссий
local nret1 = {}
local dplText = '{{#dpl:namespace=|uses=template:Задание|linksto=%PAGENAME1%|include={Задание}::Локация взятия:Локация выполнения:Игра|includematch=/%PAGENAME2%/s|includetrim=true|mode=userformat|tablerow=~~%PAGE%,~%%,~%%,~%%|noresultsheader=|noresultsfooter=|suppresserrors=true|allowcachedresults=true}}'
local tnoresult = 'В этом разделе были бы указаны задания, связанные с данной локацией. Если бы их удалось найти.'
local there = ' (выполняется здесь же)'
-- дополнительные миссии (которые невозможно найти автоматически)
-- формат: миссия1~~миссия2
local addStart = tableTrim(mw.text.split(args.astart or '', '~~'))
local addEnd = tableTrim(mw.text.split(args.aend or '', '~~'))
-- миссии, которые начинаются\заканчиваются здесь
local mstart = addStart
local mend = addEnd
-- defend dpl against stupid chars in the title (<>)
-- вызов всегда должен быть через mw.ustring, чтобы получить ustring вместо string
-- баг?: ustring должен быть на каждой строке по дефолту
local linksto = mw.ustring.gsub(ntitle.text, '[«<>»]', '%')
local includematch = mw.ustring.gsub(ntitle.text, '([()])', '\\%1')
includematch = mw.ustring.gsub(includematch, '[«<>»]', '.*?')
includematch = mw.ustring.gsub(includematch, '[ _]', '[ _]')
dplText = mw.ustring.gsub(dplText, '%%PAGENAME1%%', linksto)
dplText = mw.ustring.gsub(dplText, '%%PAGENAME2%%', includematch)
local dplResult = frame:preprocess(dplText)
--if 1 then return frame:preprocess('<pre>'..#dplText..dplText..'\n\n'..#dplResult..dplResult..'</pre>')end
nret = tnoresult
if dplResult and #dplResult > 0 then
-- do stuff
-- parse dpl output
-- ~~title (mission)|~loc1|~loc2|~game
local dplLines = mw.text.split(dplResult, '~~')
-- remove 1st empty row (cuz ~~data -> {, data})
table.remove(dplLines, 1)
function findLoc(locs, loc)
-- find loc in locs
-- returns loc index or nil
for i, v in ipairs(locs) do
if v.link == loc.link then
return i
end
end
return nil
end--findloc
for _, line in ipairs(dplLines) do
local mis, loc1, loc2, gam = line:match('^[%s%c~]*(.-)[%s%c]*|~(.-)[%s%c]*|~(.-)[%s%c]*|~(.-)[%s%c]*$')
-- фильтр по игре
if gam and #gam ~= 0 then
gam = mw.text.trim(parseLinks(gam, 'link')[1])-- only 1 game expected is
if #gam == 0 then gam = nil end
else
gam = nil
end
if (not gam or not game) or (gam and game and gam == game) then
loc1 = parseLinks(loc1, 'table')
loc2 = parseLinks(loc2, 'table')
-- локация выполнения
for i, v in ipairs(loc2) do
local isInLoc1 = findLoc(loc1, v)
-- миссия ссылается на текущую страницу?
if v.link == ntitle.text then
if isInLoc1 then
-- лока сдачи совпадает с локой взятия
loc1[isInLoc1].here = true
table.remove(loc2, i)
break
end
table.insert(mend, '[[' .. mis .. ']]')
end
end-- for loc2
-- если лока сдачи не указана, то = локе взятия
-- здесь нельзя определить конкретную локу из списка, потому - первая
if #(loc2 or {}) == 0 then loc1[1].here = true end
-- локация взятия
for i, v in ipairs(loc1) do
-- миссия ссылается на текущую страницу?
if v.link == ntitle.text then
table.insert(mstart, '[[' .. mis .. ']]' .. (v.here and there or ''))
break
end
end-- for loc1
end-- if gam==game
end
end-- if dplresult
-- process (sort etc) tables here
table.sort(mstart)
table.sort(mend)
-- strip empty values
table.insert(mstart, 1, '\n*Выдаются:')
table.insert(mend, 1, '\n*Выполняются:')
mstart = #mstart > 1 and table.concat(mstart, '\n**') or nil
mend = #mend > 1 and table.concat(mend, '\n**') or nil
-- какую надпись показать?
if mstart then
nret = mend and tfull or tin
else
nret = mend and tout or tnoresult
end
table.insert(nret1, nret)
--table.insert(nret1, dplText)
--table.insert(nret1, dplResult)
table.insert(nret1, mstart)
table.insert(nret1, mend)
--return frame:preprocess('<pre>' .. table.concat(nret1, '\n----') .. '</pre>')
return table.concat(nret1)
else
-- заполнено вручную
local ncontent = ntitle:getContent()
local npattern = '==Задания==.-'
local findresult1, findresult2 = nil, nil
findresult1 = mw.ustring.find(ncontent, npattern..'\n%*Выдаются', 1, false)
findresult2 = mw.ustring.find(ncontent, npattern..'\n%*Выполняются', 1, false)
if (findresult1 and findresult2) then
nret = tfull
elseif findresult1 then
nret = tin
elseif findresult2 then
nret = tout
end
return nret
end-- if mode==auto
end-- tlm
function p.getParent (f)
--returns top parent frame
if f.getParent and f:getParent() then return p.getParent(f:getParent()) else return f end
end
function p.printarg (frame)
--returns arg=value; order is not guaranteed
local f = p.getParent(frame)
local args = f.args
local exclude = mw.text.split(frame.args.exclude or '', ',')
local s = ''
if exclude and #exclude == 1 and #exclude[1] == 0 then exclude = {} end
function excluded (name)
--returns true if param should be excluded
if #exclude == 0 then return false end
for i, v in pairs(exclude) do
if v == name then return true end
end
return false
end--excluded
for i, v in pairs(args) do
if not excluded(i) then
--do not add = to unnamed and 1=
s = s .. (tonumber(i) and '' or (i .. '=')) .. v
end
end
return s
end--printarg
function p.dexname (frame)
--return ext name
local src = frame.args[1] or frame.args['src'] or ''
local ext = nil
if src == '' then
return
end
if mw.ustring.find(src, '\'\"\`UNIQ.-\-(.-)\-.-QINU\`\"\'', 1, false) then
ext = mw.ustring.gsub(mw.ustring.gsub(src, '\'\"\`UNIQ.-\-(.-)\-.-QINU\`\"\'', '%1'),'^([%s%c]*)(.-)([%c%s]*)$','%2')
end
return ext
end --dexname
function p.iif (cond, t, f)
if cond then
return t
else
return f
end
end
function p.bit (b)
return 2 ^ (b - 1) -- 1-based indexing
end
-- Typical call: if hasbit(x, bit(3)) then ...
function p.hasbit (x, b)
return x % (b + b) >= b
end
function p.setbit (x, b)
return hasbit(x, b) and x or x + b
end
function p.clearbit (x, b)
return hasbit(x, b) and x - b or x
end
function p_trim( s )
if s and not(s:match('^%s*$')) then
return mw.text.trim( s ); -- If not nil nor empty.
end
end
return p
--</syntaxhighlight>