Modul:TemplUtl: Unterschied zwischen den Versionen
K
Änderungen von Felix Koenig~dewiki (Diskussion) auf die letzte Version von PerfektesChaos zurückgesetzt
K (Änderungen von PerfektesChaos (Diskussion) auf die letzte Version von Mabschaaf zurückgesetzt) |
K (Änderungen von Felix Koenig~dewiki (Diskussion) auf die letzte Version von PerfektesChaos zurückgesetzt) |
||
Zeile 1: | Zeile 1: | ||
local TemplUtl = { suite = "TemplUtl", | |||
TemplUtl | serial = "2019-02-17" }; | ||
Zeile 11: | Zeile 10: | ||
-- Postcondition: | -- Postcondition: | ||
-- Returns string with pattern | -- Returns string with pattern | ||
local start = mw.ustring.sub( accept, 1, 1 ); | |||
local r; | local r; | ||
if mw.ustring.match( start, "%a" ) then | if mw.ustring.match( start, "%a" ) then | ||
r = string.format( "[%s%s]%s", | r = string.format( "[%s%s]%s", | ||
Zeile 23: | Zeile 22: | ||
if r:match( " " ) then | if r:match( " " ) then | ||
r = r:gsub( "%", "%%" ) | r = r:gsub( "%", "%%" ) | ||
:gsub( "[^.?+*()$] | :gsub( "[%-^.?+*()$]", "%$1" ) | ||
:gsub( "_", " " ) | :gsub( "_", " " ) | ||
:gsub( "%s+", "[%s_]+" ); | :gsub( "%s+", "[%s_]+" ); | ||
Zeile 32: | Zeile 31: | ||
local TemplUtl = { }; | local framing = function ( frame ) | ||
if not TemplUtl.frame then | |||
if type( frame ) == "table" then | |||
TemplUtl.frame = frame; | |||
else | |||
TemplUtl.frame = mw.getCurrentFrame(); | |||
end | |||
end | |||
return TemplUtl.frame; | |||
end -- framing() | |||
TemplUtl.faculty = function ( analyze, another ) | |||
-- Test template arg for boolean | |||
-- analyze -- string, boolean, number or nil | |||
-- another -- fallback: string, boolean, or nil | |||
-- Returns boolean | |||
local s = type( analyze ); | |||
local r; | |||
if s == "string" then | |||
r = mw.text.trim( analyze ); | |||
if r == "" then | |||
r = TemplUtl.faculty( another, nil ); | |||
elseif r:find( "1", 1, true ) and | |||
r:match( "^[0%-]*1[01%-]*$") then | |||
r = true; | |||
elseif r:match( "^[0%-]+$") then | |||
r = false; | |||
else | |||
r = r:lower(); | |||
if r == "y" or r == "yes" or r == "true" then | |||
r = true; | |||
elseif r == "n" or r == "no" or r == "false" then | |||
r = false; | |||
else | |||
if not TemplUtl.L10N then | |||
local lucky; | |||
s = string.format( "Module:%s/local", | |||
TemplUtl.suite ); | |||
lucky, TemplUtl.L10N = pcall( mw.loadData, s ); | |||
end | |||
if type( TemplUtl.L10N ) == "table" then | |||
local entry; | |||
if not TemplUtl.lang then | |||
-- TODO: page language | |||
TemplUtl.lang = | |||
mw.language.getContentLanguage():getCode(); | |||
end | |||
entry = TemplUtl.L10N[ TemplUtl.lang ]; | |||
if type( entry ) == "table" then | |||
s = entry[ r ]; | |||
if type( s ) == "boolean" then | |||
r = s; | |||
end | |||
end | |||
else | |||
TemplUtl.L10N = true; | |||
end | |||
if type( r ) ~= "boolean" then | |||
if type( another ) ~= "nil" then | |||
r = TemplUtl.faculty( another ); | |||
else | |||
r = true; | |||
end | |||
end | |||
end | |||
end | |||
elseif s == "boolean" then | |||
r = analyze; | |||
elseif s == "number" then | |||
r = ( analyze ~= 0 ); | |||
else | |||
r = false; | |||
end | |||
return r; | |||
end -- TemplUtl.faculty() | |||
TemplUtl.failsafe = function ( assert ) | |||
local r | |||
if not assert or assert <= TemplUtl.serial then | |||
r = TemplUtl.serial | |||
else | |||
r = false | |||
end | |||
return r | |||
end -- TemplUtl.failsafe() | |||
TemplUtl.failure = function ( alert, always, addClass, frame ) | |||
-- Format error message, mostly hidden | |||
-- alert -- string: message | |||
-- always -- boolean, or nil: do not hide | |||
-- addClass -- string, or nil: add classes to element | |||
-- frame -- object, or nil | |||
-- Returns string | |||
local err = mw.html.create( "span" ) | |||
:addClass( "error" ) | |||
:wikitext( alert ); | |||
local live = ( framing( frame ):preprocess( "{{REVISIONID}}" ) | |||
== "" ); | |||
if type( addClass ) == "string" then | |||
err:addClass( addClass ) | |||
end | |||
if live then | |||
local max = 1000000000; | |||
local id = math.floor( os.clock() * max ); | |||
local sign = string.format( "error_%d", id ); | |||
local btn = mw.html.create( "span" ); | |||
local top = mw.html.create( "div" ); | |||
err:attr( "id", sign ); | |||
-- TODO: LTR | |||
btn:css( { ["background"] = "#FFFF00", | |||
["border"] = "#FF0000 3px solid", | |||
["font-weight"] = "bold", | |||
["padding"] = "2px", | |||
["text-decoration"] = "none" } ) | |||
:wikitext( ">>>" ); | |||
sign = string.format( "[[#%s|%s]]", sign, tostring( btn ) ); | |||
top:wikitext( sign, " ", alert ); | |||
mw.addWarning( tostring( top:attr( "role", "alert" ) ) ); | |||
elseif not always then | |||
err:css( { ["display"] = "none" } ); | |||
-- err:css( { ["display"] = "inline-block", | |||
-- ["line-height"] = "0", | |||
-- ["max-height"] = "0", | |||
-- ["max-width"] = "0", | |||
-- ["visibility"] = "hidden" } ); | |||
end | |||
return tostring( err ); | |||
end -- TemplUtl.failure() | |||
TemplUtl.fake = function ( access, frame ) | |||
-- Simulation of template transclusion | |||
-- Precondition: | |||
-- access -- string, or nil; page name (template) | |||
-- frame -- object, or nil | |||
local s; | |||
if type( access ) == "string" then | |||
s = mw.text.trim( access ); | |||
if s == "" then | |||
s = false; | |||
end | |||
end | |||
if not s then | |||
local cnf, lucky; | |||
s = string.format( "Module:%s/self", TemplUtl.suite ); | |||
lucky, cnf = pcall( mw.loadData, s ); | |||
if type( cnf ) == "table" and | |||
cnf.loop == true then | |||
s = mw.title.getCurrentTitle().text; | |||
else | |||
s = false; | |||
end | |||
end | |||
if s then | |||
local f = function () | |||
framing( frame ):expandTemplate{ title = s }; | |||
end | |||
pcall( f ); | |||
end | |||
end -- TemplUtl.fake() | |||
TemplUtl.fakes = function ( array, frame, ahead ) | |||
-- Simulation of template transclusions | |||
-- Precondition: | |||
-- array -- table, with template title strings | |||
-- frame -- object, or nil | |||
-- ahead -- string, or nil, with common prefix | |||
local e = framing( frame ); | |||
local f = function ( a ) | |||
e:expandTemplate{ title = a }; | |||
end | |||
local s = ahead or ""; | |||
for k, v in pairs( array ) do | |||
if type( k ) == "number" and | |||
type( v ) == "string" then | |||
v = mw.text.trim( v ); | |||
pcall( f, s .. v ); | |||
end | |||
end -- for k, v | |||
end -- TemplUtl.fakes() | |||
Zeile 208: | Zeile 395: | ||
-- at -- optional number; byte position in area of "{{" | -- at -- optional number; byte position in area of "{{" | ||
-- Postcondition: | -- Postcondition: | ||
-- Returns | -- Returns | ||
-- [0] template, page, parser function name | -- -- table | ||
-- [0] -- template, page, parser function name | |||
-- [1] -- unnamed parameter | |||
-- ["name"] -- named parameter | |||
-- -- string; error message, if any, else nil | |||
local n = 0; | local n = 0; | ||
local j, k, p, r, r2, s, v; | local j, k, p, r, r2, s, v; | ||
Zeile 305: | Zeile 496: | ||
-- Requires: | -- Requires: | ||
-- fiatTitleRegExp() | -- fiatTitleRegExp() | ||
local scan = string.format( "{{%s%s%s", | local scan = string.format( "{{%s%s%s", | ||
"([%w_%s:]*)%s*", | "([%w_%s:]*)%s*", | ||
fiatTitleRegExp( access ), | fiatTitleRegExp( access ), | ||
"%s*([|}<]!?)" ); | "%s*([|}<]!?)" ); | ||
local r, space, start, suffix; | |||
if type( at ) == "number" then | if type( at ) == "number" then | ||
r = at; | r = at; | ||
Zeile 361: | Zeile 552: | ||
return r; | return r; | ||
end -- TemplUtl.find() | end -- TemplUtl.find() | ||
-- finder() | |||
-- 1 page name | |||
-- 2 template title / page name | |||
-- 3 4 5 6 | |||
-- more like 2 | |||
TemplUtl.flat = function ( area ) | |||
-- Remove syntax elements that hide effective syntax only | |||
-- Precondition: | |||
-- area -- string; wikitext to be reduced | |||
-- Postcondition: | |||
-- Returns cleared wikitext | |||
local delimiters = { { "<%s*NOWIKI%s*>", "<%s*/%s*NOWIKI%s*>" }, | |||
{ "<!--", "-->", true }, | |||
{ "<%s*PRE%s*>", "<%s*/%s*PRE%s*>" }, | |||
{ "<%s*SYNTAXHIGHLIGHT[^<>]*>", | |||
"<%s*/%s*SYNTAXHIGHLIGHT%s*>" } }; | |||
local i = 1; | |||
local r = area; | |||
local k, m, n; | |||
if not TemplUtl.Delimiters then | |||
local c, sD, sP; | |||
TemplUtl.Delimiters = { }; | |||
for j = 1, #delimiters do | |||
table.insert( TemplUtl.Delimiters, { } ); | |||
for ji = 1, 2 do | |||
sD = delimiters[ j ][ ji ]; | |||
sP = ""; | |||
for js = 1, #sD, 1 do | |||
c = sD:byte( js, js ); | |||
if c >= 65 and c <= 90 then | |||
sP = string.format( "%s[%c%c]", | |||
sP, c, c + 32 ); | |||
else | |||
sP = sP .. string.char( c ); | |||
end | |||
end -- for js | |||
table.insert( TemplUtl.Delimiters[ j ], sP ); | |||
end -- for ji | |||
end -- for j | |||
end | |||
while ( true ) do | |||
k = false; | |||
for j = 1, #delimiters do | |||
m = r:find( TemplUtl.Delimiters[ j ][ 1 ], | |||
i, | |||
TemplUtl.Delimiters[ j ][ 3 ] ); | |||
if m and ( not k or m < k ) then | |||
k = m; | |||
n = j; | |||
end | |||
end -- for j | |||
if k then | |||
local s | |||
if k > 1 then | |||
i = k - 1; | |||
s = r:sub( 1, i ); | |||
else | |||
s = ""; | |||
end | |||
j, m = r:find( TemplUtl.Delimiters[ n ][ 2 ], | |||
k + 1, | |||
TemplUtl.Delimiters[ n ][ 3 ] ); | |||
if m then | |||
r = s .. r:sub( m + 1 ); | |||
else | |||
r = s; | |||
break; -- while true | |||
end | |||
else | |||
break; -- while true | |||
end | |||
end -- while true | |||
return r; | |||
end -- TemplUtl.flat() | |||
Zeile 366: | Zeile 636: | ||
-- Export | -- Export | ||
local p = { }; | local p = { }; | ||
function p.faculty( frame ) | |||
return TemplUtl.faculty( frame.args[ 1 ], | |||
frame.args[ 2 ] ) and "1" | |||
or ""; | |||
end -- p.faculty | |||
function p.failure( frame ) | |||
local scream = mw.text.trim( frame.args[ 1 ] or "" ); | |||
local loud = frame.args[ 2 ]; | |||
local select = frame.args.class; | |||
if scream == "" then | |||
scream = "?????????"; | |||
end | |||
if loud then | |||
loud = TemplUtl.faculty( loud, nil ); | |||
end | |||
return TemplUtl.failure( scream, loud, select, frame ); | |||
end -- p.failure | |||
function p.fake( frame ) | |||
TemplUtl.fake( frame.args[ 1 ] or "", frame ); | |||
return ""; | |||
end -- p.fake | |||
function p.fakes( frame ) | |||
TemplUtl.fakes( frame.args, frame, frame.args.prefix ); | |||
return ""; | |||
end -- p.fakes | |||
function p.isRedirect() | |||
return mw.title.getCurrentTitle().isRedirect and "1" or ""; | |||
end -- p.isRedirect | |||
p.failsafe = function ( frame ) | |||
-- Versioning interface | |||
local s = type( frame ) | |||
local since | |||
if s == "table" then | |||
since = frame.args[ 1 ] | |||
elseif s == "string" then | |||
since = frame | |||
end | |||
if since then | |||
since = mw.text.trim( since ) | |||
if since == "" then | |||
since = false | |||
end | |||
end | |||
return TemplUtl.failsafe( since ) or "" | |||
end -- p.failsafe() | |||
p.TemplUtl = function () | p.TemplUtl = function () | ||
return TemplUtl; | return TemplUtl; | ||
end | end -- p.TemplUtl() | ||
return p; | return p; |