Modul:TemplUtl
Die Dokumentation für dieses Modul kann unter Modul:TemplUtl/Doku erstellt werden
--[=[ 2014-11-20
TemplUtl
]=]
local fiatTitleRegExp = function ( accept )
-- Create pattern to detect page name
-- Precondition:
-- accept -- string; trimmed title
-- Postcondition:
-- Returns string with pattern
local r;
local start = mw.ustring.sub( accept, 1, 1 );
if mw.ustring.match( start, "%a" ) then
r = string.format( "[%s%s]%s",
mw.ustring.lower( start ),
mw.ustring.upper( start ),
mw.ustring.sub( accept, 2 ) );
else
r = accept;
end
if r:match( " " ) then
r = r:gsub( "%", "%%" )
:gsub( "[^.?+*()$]+", "%$1" )
:gsub( "_", " " )
:gsub( "%s+", "[%s_]+" );
end
return r;
end -- fiatTitleRegExp()
local TemplUtl = { };
TemplUtl.feasible = function ( address )
-- Does this describe an URL beginning?
-- Precondition:
-- address -- string; template transclusion
-- Postcondition:
-- Returns true, if URL beginning
local start, r = address:match( "^%s*((%a*:?)//)" );
if start then
if r == "" then
r = true;
elseif r:sub( -1, -1 ) == ":" then
local schemes = ":ftp:ftps:http:https:";
r = ":" .. r:lower();
if schemes:find( r, 1, true ) then
r = true;
else
r = false;
end
else
r = false;
end
end
return r;
end -- TemplUtl.feasible()
TemplUtl.feed = function ( area, ahead, at, after )
-- Detect next free "|" or "}}"
-- Precondition:
-- area -- string; template transclusion
-- ahead -- string; opening element, or false
-- at -- number; byte position in area where to start
-- after -- true, if only to search for "}}"
-- Postcondition:
-- Returns
-- -- number; byte position in area
-- -- before "|" or "}}", may be at end
-- -- to continue search; ahead has been closed
-- -- true, if to be continued at number
local j = at;
local loop = true;
local c, k, r, s, seek;
if after then
seek = "[{}<]";
else
seek = "[%[%]|{}<:]";
end
while loop do
j = area:find( seek, j );
if j then
c = area:byte( j, j );
if c == 123 then -- {
k = j + 1;
if area:byte( k, k ) == 123 then
k = k + 1;
if area:byte( k, k ) == 123 then
j, loop = TemplUtl.feed( area, "{{{", k, after );
else
k = k - 1;
j, loop = TemplUtl.feed( area, "{{", k, after );
end
if not loop then
r = j;
end
end
elseif c == 125 then -- }
k = j + 1;
if area:byte( k, k ) == 125 then
if ahead == "{{" then
r = k;
break; -- while loop;
elseif ahead == "{{{" then
k = k + 1;
if area:byte( k, k ) == 125 then
r = k;
break; -- while loop;
end
elseif not ahead then
r = j - 1;
loop = false;
end
end
elseif c == 60 then -- <
k = j + 3;
if area:sub( j, k ) == "<!--" then
k = area:find( "-->", k );
if k then
j = k + 2;
end
else
local skip;
s = area:sub( j + 1 ):lower();
skip = s:match( "^%s*nowiki%s*>" );
if skip then
local n = skip:len();
n, k = s:find( "<%s*/%s*nowiki%s*>", n );
if k then
j = j + k;
else
loop = false;
end
end
end
elseif c == 124 then -- |
if not r then
r = j - 1;
end
if not ahead then
loop = false;
end
elseif c == 91 then -- [
k = j + 1;
if area:byte( k, k ) == 91 then
k = k + 1;
j, loop = TemplUtl.feed( area, "[[", k, after );
elseif TemplUtl.feasible( area:sub( k ) ) then
k = k + 3;
j, loop = TemplUtl.feed( area, "[", k, after );
end
if not loop then
r = j;
end
elseif c == 93 then -- ]
if ahead == "[" then
r = j;
break; -- while loop
elseif ahead == "[[" then
k = j + 1;
if area:byte( k, k ) == 93 then
r = k;
break; -- while loop
end
end
elseif c == 58 then -- :
s = area:sub( j + 1, j + 2 );
if s == "//" then
s = " " .. area:sub( 1, j + 2 );
s = s:match( "%s(%a+://)$" );
if s and TemplUtl.feasible( s ) then
s = area .. " ";
s = s:match( "(%S+)%s", j );
if s then
k = s:find( "}}" );
if k then
j = j + k + 1;
else
j = j + s:len();
end
end
end
end
end
j = j + 1;
else
loop = false;
end
end -- while loop
if not r then
r = area:len();
end
return r, loop;
end -- TemplUtl.feed()
TemplUtl.fetch = function ( area, ask )
-- Find assignment of a named template parameter
-- Precondition:
-- area -- string; template transclusion
-- ask -- string; parameter name
-- Postcondition:
-- Returns string with trimmed parameter value, or nil
-- Does not return value if template inside
local r;
local scan = string.format( "%s%s%s",
"|%s*", ask, "%s*=(.+)$" );
r = mw.ustring.match( area, scan );
if r then
local j = TemplUtl.feed( r, false, 1 );
r = r:sub( 1, j );
if r then
r = mw.text.trim( r );
if r == "" then
r = nil;
end
end
end
return r;
end -- TemplUtl.fetch()
TemplUtl.find = function ( area, access, at, alter )
-- Find next occurrence of a template
-- Precondition:
-- area -- string; where to search
-- access -- string; trimmed (template) title
-- at -- optional number; ustring position in area, if not 1
-- alter -- optional string; lowercase namespace pattern
-- "" for article
-- Postcondition:
-- Returns ustring position of "{{" in area, or false
-- Requires:
-- fiatTitleRegExp()
local r, space, start, suffix;
local scan = string.format( "{{%s%s%s",
"([%w_%s:]*)%s*",
fiatTitleRegExp( access ),
"%s*([|}<]!?)" );
if type( at ) == "number" then
r = at;
else
r = 1;
end
while true do
r = mw.ustring.find( area, scan, r );
if r then
start, suffix = mw.ustring.match( area, scan, r );
if start then
start = mw.text.trim( start );
if start == "" then
break; -- while true
elseif alter then
if not space then
space = string.format( "^:?%s:$", alter );
end
start = mw.ustring.lower( start );
if mw.ustring.match( start, space ) then
break; -- while true
end
else
start = start:match( "^:?(.+):$" );
if start then
start = mw.ustring.lower( start );
if start == "template" then
break; -- while true
else
if not space then
space = mw.site.namespaces[ 10 ].name;
space = mw.ustring.lower( space );
end
start = start:gsub( "_", " " )
:gsub( "%s+", " " );
if start == space then
break; -- while true
end
end
end
end
else
break; -- while true
end
r = r + 2;
else
r = false;
break; -- while true
end
end -- while true
return r;
end -- TemplUtl.find()
-- Export
local p = { };
p.TemplUtl = function ()
return TemplUtl;
end
return p;