Aktuelle Version |
Dein Text |
Zeile 1: |
Zeile 1: |
| local TemplUtl = { suite = "TemplUtl", | | local TemplUtl = { suite = "TemplUtl", |
| serial = "2019-11-20", | | serial = "2016-02-28" }; |
| item = 52364930 };
| | local Delimiters; |
| local Failsafe = TemplUtl; | |
| | |
| | |
| | |
| local fallible = function ( adjust, ahead )
| |
| -- Check for leading character disturbing syntax
| |
| -- Precondition:
| |
| -- adjust -- string; trimmed wikitext
| |
| -- ahead -- true, if leading syntax shall start on new line
| |
| -- Postcondition:
| |
| -- Returns string, modified if necessary
| |
| local r = adjust;
| |
| local c = r:byte( 1, 1 );
| |
| if c <= 59 and
| |
| ( c==35 or c==42 or c==58 or c==59 ) then
| |
| if ahead then
| |
| r = "\n" .. r;
| |
| else
| |
| r = mw.text.nowiki( r:sub( 1, 1 ) ) .. r:sub( 2 );
| |
| end
| |
| elseif ahead then
| |
| local c2 = r:byte( 2, 1 );
| |
| if ( c==123 and c2==124 ) or
| |
| ( c==124 and c2==45 ) then
| |
| r = "\n" .. r;
| |
| end
| |
| end
| |
| return r;
| |
| end -- fallible()
| |
|
| |
|
|
| |
|
Zeile 39: |
Zeile 10: |
| -- accept -- string; trimmed title | | -- accept -- string; trimmed title |
| -- Postcondition: | | -- Postcondition: |
| -- Returns string with pattern | | -- Returns string with pattern |
| local start = mw.ustring.sub( accept, 1, 1 ); | | local start = mw.ustring.sub( accept, 1, 1 ); |
| local r; | | local r; |
Zeile 52: |
Zeile 23: |
| if r:match( " " ) then | | if r:match( " " ) then |
| r = r:gsub( "%", "%%" ) | | r = r:gsub( "%", "%%" ) |
| :gsub( "[%-^.?+*()$]", "%$1" ) | | :gsub( "[^.?+*()$]+", "%$1" ) |
| :gsub( "_", " " ) | | :gsub( "_", " " ) |
| :gsub( "%s+", "[%s_]+" ); | | :gsub( "%s+", "[%s_]+" ); |
Zeile 58: |
Zeile 29: |
| return r; | | return r; |
| end -- fiatTitleRegExp() | | end -- fiatTitleRegExp() |
|
| |
|
| |
|
| |
| 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" or
| |
| r == "on" then
| |
| r = true;
| |
| elseif r == "n" or
| |
| r == "no" or
| |
| r == "false" or
| |
| r == "off" then
| |
| r = false;
| |
| else
| |
| if not TemplUtl.boolang then
| |
| -- TODO: page language
| |
| local l, d = pcall( mw.ext.data.get, "i18n/01.tab" );
| |
| if type( d ) == "table" and
| |
| type( d.data ) == "table" then
| |
| local f = function ( at )
| |
| local e = d.data[ at ];
| |
| l = e[ 1 ];
| |
| s = e[ 2 ];
| |
| if type( l ) == "boolean" and
| |
| type( s ) == "string" then
| |
| s = mw.text.split( s, "|" );
| |
| for i = 1, #s do
| |
| TemplUtl.boolang[ s[ i ] ] = l;
| |
| end -- for i
| |
| end
| |
| end
| |
| TemplUtl.boolang = { };
| |
| f( 1 );
| |
| f( 2 );
| |
| else
| |
| TemplUtl.boolang = true;
| |
| end
| |
| end
| |
| if type( TemplUtl.boolang ) == "table" then
| |
| s = TemplUtl.boolang[ r ];
| |
| if type( s ) == "boolean" then
| |
| r = s;
| |
| end
| |
| end
| |
| if type( r ) ~= "boolean" then
| |
| s = type( another );
| |
| if s == "nil" then
| |
| r = true;
| |
| elseif s == "boolean" then
| |
| r = another;
| |
| else
| |
| r = TemplUtl.faculty( another );
| |
| 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.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 )
| |
| -- Simulation of template transclusion
| |
| -- Precondition:
| |
| -- access -- string; page name (template)
| |
| if type( access ) == "string" then
| |
| local s = mw.text.trim( access );
| |
| if s ~= "" then
| |
| local t = mw.title.new( s, 10 );
| |
| if not mw.title.equals( mw.title.getCurrentTitle(), t ) and
| |
| t.exists then
| |
| t:getContent();
| |
| end
| |
| end
| |
| end
| |
| end -- TemplUtl.fake()
| |
|
| |
|
| |
|
| |
| TemplUtl.fakes = function ( array, frame, ahead, answer )
| |
| -- Simulation of template transclusions
| |
| -- Precondition:
| |
| -- array -- table, with template title strings
| |
| -- frame -- object, or nil
| |
| -- ahead -- string, or nil, with common prefix
| |
| -- answer -- true, or nil, for list creation
| |
| -- Postcondition:
| |
| -- Returns string, if answer requested
| |
| local e = framing( frame );
| |
| local f = function ( a )
| |
| e:expandTemplate{ title = a };
| |
| end
| |
| local s = ahead or "";
| |
| local r;
| |
| for k, v in pairs( array ) do
| |
| if type( k ) == "number" and
| |
| type( v ) == "string" then
| |
| v = s .. mw.text.trim( v );
| |
| pcall( f, v );
| |
| if answer then
| |
| if r then
| |
| r = r .. "\n";
| |
| else
| |
| r = "";
| |
| end
| |
| r = string.format( "%s* [[Template:%s|%s]]", r, v, v );
| |
| end
| |
| end
| |
| end -- for k, v
| |
| return r;
| |
| end -- TemplUtl.fakes()
| |
|
| |
|
|
| |
|
Zeile 260: |
Zeile 37: |
| -- address -- string; what to inspect, URL presumed | | -- address -- string; what to inspect, URL presumed |
| -- Postcondition: | | -- Postcondition: |
| -- Returns true, if URL beginning | | -- Returns true, if URL beginning |
| local start, r = address:match( "^%s*((%a*:?)//)" ); | | local start, r = address:match( "^%s*((%a*:?)//)" ); |
| if start then | | if start then |
Zeile 290: |
Zeile 67: |
| -- after -- true, if only to search for "}}" | | -- after -- true, if only to search for "}}" |
| -- Postcondition: | | -- Postcondition: |
| -- Returns | | -- Returns |
| -- -- number; byte position in area | | -- -- number; byte position in area |
| -- -- before "|" or "}}", may be at end | | -- -- before "|" or "}}", may be at end |
Zeile 427: |
Zeile 204: |
| -- at -- optional number; byte position in area of "{{" | | -- at -- optional number; byte position in area of "{{" |
| -- Postcondition: | | -- Postcondition: |
| -- Returns | | -- Returns |
| -- -- table | | -- -- table |
| -- [0] -- template, page, parser function name | | -- [0] -- template, page, parser function name |
Zeile 494: |
Zeile 271: |
| -- ask -- string; parameter name | | -- ask -- string; parameter name |
| -- Postcondition: | | -- Postcondition: |
| -- Returns string with trimmed parameter value, or nil | | -- Returns string with trimmed parameter value, or nil |
| -- Does not return value if template inside | | -- Does not return value if template inside |
| local r; | | local r; |
Zeile 525: |
Zeile 302: |
| -- no colon (:) | | -- no colon (:) |
| -- Postcondition: | | -- Postcondition: |
| -- Returns ustring position of "{{" in area, or false | | -- Returns ustring position of "{{" in area, or false |
| -- Requires: | | -- Requires: |
| -- fiatTitleRegExp() | | -- fiatTitleRegExp() |
Zeile 591: |
Zeile 368: |
| -- 3 4 5 6 | | -- 3 4 5 6 |
| -- more like 2 | | -- more like 2 |
|
| |
|
| |
|
| |
| TemplUtl.firstbreak = function ( adjust )
| |
| -- Precede leading character with newline if specific syntax
| |
| -- Precondition:
| |
| -- adjust -- string; trimmed wikitext
| |
| -- Postcondition:
| |
| -- Returns string, modified if necessary
| |
| return fallible( adjust, true );
| |
| end -- TemplUtl.firstbreak()
| |
|
| |
|
|
| |
|
Zeile 608: |
Zeile 374: |
| -- Remove syntax elements that hide effective syntax only | | -- Remove syntax elements that hide effective syntax only |
| -- Precondition: | | -- Precondition: |
| -- area -- string; unparsed wikitext to be reduced | | -- area -- string; wikitext to be reduced |
| -- Postcondition: | | -- Postcondition: |
| -- Returns cleared wikitext | | -- Returns cleared wikitext |
| local delimiters = { { "<%s*NOWIKI%s*>", "<%s*/%s*NOWIKI%s*>" }, | | local delimiters = { { "<%s*NOWIKI%s*>", "<%s*/%s*NOWIKI%s*>" }, |
| { "<!--", "-->", true }, | | { "<!--", "-->", true }, |
Zeile 619: |
Zeile 385: |
| local r = area; | | local r = area; |
| local k, m, n; | | local k, m, n; |
| if not TemplUtl.Delimiters then | | if not Delimiters then |
| local c, sD, sP; | | local c, sD, sP; |
| TemplUtl.Delimiters = { }; | | Delimiters = { }; |
| for j = 1, #delimiters do | | for j = 1, #delimiters do |
| table.insert( TemplUtl.Delimiters, { } ); | | table.insert( Delimiters, { } ); |
| for ji = 1, 2 do | | for ji = 1, 2 do |
| sD = delimiters[ j ][ ji ]; | | sD = delimiters[ j ][ ji ]; |
Zeile 636: |
Zeile 402: |
| end | | end |
| end -- for js | | end -- for js |
| table.insert( TemplUtl.Delimiters[ j ], sP ); | | table.insert( Delimiters[ j ], sP ); |
| end -- for ji | | end -- for ji |
| end -- for j | | end -- for j |
Zeile 643: |
Zeile 409: |
| k = false; | | k = false; |
| for j = 1, #delimiters do | | for j = 1, #delimiters do |
| m = r:find( TemplUtl.Delimiters[ j ][ 1 ], | | m = r:find( Delimiters[ j ][ 1 ], |
| i, | | i, |
| TemplUtl.Delimiters[ j ][ 3 ] ); | | Delimiters[ j ][ 3 ] ); |
| if m and ( not k or m < k ) then | | if m and ( not k or m < k ) then |
| k = m; | | k = m; |
Zeile 659: |
Zeile 425: |
| s = ""; | | s = ""; |
| end | | end |
| j, m = r:find( TemplUtl.Delimiters[ n ][ 2 ], | | j, m = r:find( Delimiters[ n ][ 2 ], |
| k + 1, | | k + 1, |
| TemplUtl.Delimiters[ n ][ 3 ] ); | | Delimiters[ n ][ 3 ] ); |
| if m then | | if m then |
| r = s .. r:sub( m + 1 ); | | r = s .. r:sub( m + 1 ); |
Zeile 674: |
Zeile 440: |
| return r; | | return r; |
| end -- TemplUtl.flat() | | end -- TemplUtl.flat() |
|
| |
|
| |
|
| |
| TemplUtl.nowiki1 = function ( adjust )
| |
| -- HTML-escape leading character if disturbing syntax
| |
| -- Precondition:
| |
| -- adjust -- string; trimmed wikitext
| |
| -- Postcondition:
| |
| -- Returns string, modified if necessary
| |
| return fallible( adjust, false );
| |
| end -- TemplUtl.nowiki1()
| |
|
| |
|
| |
|
| |
| Failsafe.failsafe = function ( atleast )
| |
| -- Retrieve versioning and check for compliance
| |
| -- Precondition:
| |
| -- atleast -- string, with required version or "wikidata" or "~"
| |
| -- or false
| |
| -- Postcondition:
| |
| -- Returns string -- with queried version, also if problem
| |
| -- false -- if appropriate
| |
| local last = ( atleast == "~" )
| |
| local since = atleast
| |
| local r
| |
| if last or since == "wikidata" then
| |
| local item = Failsafe.item
| |
| since = false
| |
| if type( item ) == "number" and item > 0 then
| |
| local entity = mw.wikibase.getEntity( string.format( "Q%d",
| |
| item ) )
| |
| if type( entity ) == "table" then
| |
| local seek = Failsafe.serialProperty or "P348"
| |
| local vsn = entity:formatPropertyValues( seek )
| |
| if type( vsn ) == "table" and
| |
| type( vsn.value ) == "string" and
| |
| vsn.value ~= "" then
| |
| if last and vsn.value == Failsafe.serial then
| |
| r = false
| |
| else
| |
| r = vsn.value
| |
| end
| |
| end
| |
| end
| |
| end
| |
| end
| |
| if type( r ) == "nil" then
| |
| if not since or since <= Failsafe.serial then
| |
| r = Failsafe.serial
| |
| else
| |
| r = false
| |
| end
| |
| end
| |
| return r
| |
| end -- Failsafe.failsafe()
| |
|
| |
|
|
| |
|
Zeile 735: |
Zeile 446: |
| local p = { }; | | local p = { }; |
|
| |
|
| function p.faculty( frame ) | | function p.failsafe() |
| return TemplUtl.faculty( frame.args[ 1 ],
| | return TemplUtl.serial |
| frame.args[ 2 ] ) and "1"
| | end |
| 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 )
| |
| local list = ( frame.args.list == "1" );
| |
| local r = TemplUtl.fakes( frame.args,
| |
| frame,
| |
| frame.args.prefix,
| |
| list );
| |
| return r or "";
| |
| end -- p.fakes
| |
| | |
| function p.firstbreak( frame )
| |
| local r = ( frame.args[ 1 ] );
| |
| if r then
| |
| r = mw.text.trim( r );
| |
| if r ~= "" then
| |
| r = TemplUtl.firstbreak( r );
| |
| end
| |
| end
| |
| return r or "";
| |
| end -- p.firstbreak
| |
| | |
| function p.from( frame )
| |
| local r = frame:getParent():getTitle();
| |
| if r then
| |
| r = string.format( "{{%s}}", r );
| |
| end
| |
| return r or "";
| |
| end -- p.from
| |
| | |
| function p.isRedirect()
| |
| return mw.title.getCurrentTitle().isRedirect and "1" or "";
| |
| end -- p.isRedirect
| |
| | |
| function p.nowiki1( frame )
| |
| local r = ( frame.args[ 1 ] );
| |
| if r then
| |
| r = mw.text.trim( r );
| |
| if r ~= "" then
| |
| r = TemplUtl.nowiki1( r );
| |
| end
| |
| end
| |
| return r or "";
| |
| end -- p.nowiki1
| |
| | |
| 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 Failsafe.failsafe( since ) or ""
| |
| end -- p.failsafe
| |
|
| |
|
| p.TemplUtl = function () | | p.TemplUtl = function () |
| return TemplUtl; | | return TemplUtl; |
| end -- p.TemplUtl() | | end |
|
| |
|
| return p; | | return p; |