Modul:TemplUtl: Unterschied zwischen den Versionen

11.862 Bytes hinzugefügt ,  3. Juli 2020
K
21 Versionen importiert: Doku-Vorlage
(2015-02-12)
K (21 Versionen importiert: Doku-Vorlage)
 
(19 dazwischenliegende Versionen von 5 Benutzern werden nicht angezeigt)
Zeile 1: Zeile 1:
local TemplUtl = { suite  = "TemplUtl",
local TemplUtl = { suite  = "TemplUtl",
                   serial = "2015-02-12" };
                   serial = "2019-11-20",
local Delimiters;
                  item  = 52364930 };
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 10: Zeile 39:
     --    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 23: Zeile 52:
     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 29: Zeile 58:
     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( "&gt;&gt;&gt;" );
        sign = string.format( "[[#%s|%s]]",  sign,  tostring( btn ) );
        top:wikitext( sign, "&#160;", 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 37: Zeile 260:
     --    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 67: Zeile 290:
     --    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 204: Zeile 427:
     --    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 271: Zeile 494:
     --    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 302: Zeile 525:
     --                                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 368: Zeile 591:
--      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 374: Zeile 608:
     -- Remove syntax elements that hide effective syntax only
     -- Remove syntax elements that hide effective syntax only
     -- Precondition:
     -- Precondition:
     --    area  -- string; wikitext to be reduced
     --    area  -- string; unparsed 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 },
                         { "<%s*PRE%s*>", "<%s*/%s*PRE%s*>" },
                         { "<%s*PRE%s*>", "<%s*/%s*PRE%s*>" },
                         { "<%s*SYNTAXHIGHLIGHT[^<>]*>",
                         { "<%s*SYNTAXHIGHLIGHT[^<>]*>",
Zeile 385: Zeile 619:
     local r          = area;
     local r          = area;
     local k, m, n;
     local k, m, n;
     if not Delimiters then
     if not TemplUtl.Delimiters then
         local c, sD, sP;
         local c, sD, sP;
         Delimiters = { };
         TemplUtl.Delimiters = { };
         for j = 1, #delimiters do
         for j = 1, #delimiters do
             table.insert( Delimiters, { } );
             table.insert( TemplUtl.Delimiters, { } );
             for ji = 1, 2 do
             for ji = 1, 2 do
                 sD = delimiters[ j ][ ji ];
                 sD = delimiters[ j ][ ji ];
Zeile 402: Zeile 636:
                     end
                     end
                 end -- for js
                 end -- for js
                 table.insert( Delimiters[ j ], sP );
                 table.insert( TemplUtl.Delimiters[ j ], sP );
             end -- for ji
             end -- for ji
         end -- for j
         end -- for j
Zeile 409: Zeile 643:
         k = false;
         k = false;
         for j = 1, #delimiters do
         for j = 1, #delimiters do
             m = r:find( Delimiters[ j ][ 1 ], i );
             m = r:find( TemplUtl.Delimiters[ j ][ 1 ],
             if m  and  ( not k  or  m > k ) then
                        i,
                        TemplUtl.Delimiters[ j ][ 3 ] );
             if m  and  ( not k  or  m < k ) then
                 k = m;
                 k = m;
                 n = j;
                 n = j;
Zeile 418: Zeile 654:
             local s
             local s
             if k > 1 then
             if k > 1 then
                 s = r:sub( 1, k - 1 );
                i = k - 1;
                 s = r:sub( 1, i );
             else
             else
                 s = "";
                 s = "";
             end
             end
             j, m  =  r:find( Delimiters[ n ][ 2 ], k + 1 );
             j, m  =  r:find( TemplUtl.Delimiters[ n ][ 2 ],
                            k + 1,
                            TemplUtl.Delimiters[ n ][ 3 ] );
             if m then
             if m then
                 r = s  ..  r:sub( m + 1 );
                 r = s  ..  r:sub( m + 1 );
Zeile 435: Zeile 674:
     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 440: Zeile 734:
-- 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 )
    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( "&#123;&#123;%s&#125;&#125;", 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
end -- p.TemplUtl()


return p;
return p;