Vorlagenprogrammierung Diskussionen Lua Test Unterseiten
Modul Deutsch English

Modul: Dokumentation

Diese Seite enthält Code in der Programmiersprache Lua. Einbindungszahl Cirrus

Weiterleitung der Diskussionsseite fehlt
Diese Seite ist eine lokale Kopie aus de.wikipedia.org und von dort zu aktualisieren.

Versionsbezeichnung auf WikiData: 2021-04-11


local Sort = { suite   = "Sort",
               sub     = "cell",
               serial  = "2021-04-11",
               item    = 90144855 }
--[=[
Sort/cell    --  support table cells sorting modules
]=]
local Failsafe = Sort



local face = function ( assign, attribute, args, apply, allow )
    -- Store preceding attribute
    -- Precondition:
    --     assign       -- table, to extend
    --     attribute    -- string, attribute name
    --     args         -- table|nil, parameters to retrieve
    --     apply        -- string|number|nil, for value
    --     allow        -- boolean, permit and request numbers >(=)0
    -- Postcondition:
    --     attributes extended
    local d, s, v
    if apply then
        d = apply
    elseif args then
        d = args[ attribute ]
    end
    s = type( d )
    if s == "string" then
        d = mw.text.trim( d )
        if d == "" then
            d = false
        end
    end
    if d then
        if allow then
            local min = 1
            if attribute == "rowspan" then
                min = 0
            end
            if s == "string" then
                s = string.format( "[%d-9]%%d*", min )
                if d:match( string.format( "^%s$", s ) ) then
                    v = d
                else
                    local p
                    s = string.format( "^(['\"]) *(%s) *%%1$", s )
                    p, s = d:match( s )
                    if s then
                        v = s
                    end
                end
            elseif s == "number"  and  d >= min then
                local k = math.floor( d )
                if d == k then
                    v = tostring( k )
                end
            end
            if not v then
                assign.scream = attribute .. "=????"
            end
        elseif s == "string" then
            local p
            p, s = d:match( "^(['\"])([^\"]*)%1$" )
            if s then
                d = mw.text.trim( s )
            end
            if d ~= "" then
                if attribute == "dir" then
                    d = d:lower()
                    if d == "ltr"  or  d == "rtl" then
                        v = d
                    end
                else
                    v = d
                end
            end
        end
    end
    if v then
        assign.props = assign.props  or  { }
        assign.props[ attribute ] = v
    end
end -- face()



local facing = function ( args, append )
    -- Prepend preceding attributes
    -- Precondition:
    --     args      -- table, parameters
    --     append    -- string|html|nil, thing to be extended
    -- Postcondition:
    --     Returns string, if append is a string or nil
    --     otherwise html is extended
    local p = args.props
    local r = append
    if p then
        if type( append ) == "table" then
            for k, v in pairs( p ) do
                if k == "class" then
                    append:addClass( v )
                elseif k == "css" then
                    append:css( v )
                else
                    append:attr( k, v )
                end
            end -- for k, v
        else
            if p.css then
                local s = ""
                for k, v in pairs( p.css ) do
                    if type( k ) == "string"  and
                       type( v ) == "string" then
                        v = mw.text.trim( v )
                        k = mw.text.trim( k )
                        if v ~= ""  and
                           k ~= "" then
                            s = string.format( "%s;%s:%s", s, k, v )
                        end
                    end
                end -- for k, v
                if s ~= "" then
                    face( args, "style", false, s:sub( 2 ) )
                end
                p.css = nil
            end
            if type( append ) == "string" then
                r = "| " .. append
            else
                r = "|"
            end
            for k, v in pairs( p ) do
                if k ~= "lang"  or  v ~= Sort.facility() then
                    r = string.format( " %s=\"%s\"%s", k, v, r )
                end
            end -- for k, v
            r = r:sub( 2 )
        end
    end
    return r
end -- facing()



local features = function ( args, assign )
    -- Parse CSS string
    -- Precondition:
    --     args      -- table, parameters
    --                  .style    -- string|nil, CSS to be parsed
    --     assign    -- table, to be extended
    -- Postcondition:
    --     args.props.css added
    if args.style then
        local s         = mw.text.trim( args.style )
        local pair, css = s:match( "^(['\"])([^\"]*)%1$" )
        if css then
            s = mw.text.trim( css )
        end
        css = mw.text.split( s, ";" )
        --    Problem: URL; not expected
        for i = 1, #css do
            pair = mw.text.split( css[ i ], ":" )
            --     Problem: URL; not expected
            if #pair == 2 then
                s = mw.text.trim( pair[ 1 ] )
                if s ~= "" then
                    assign.props          = assign.props  or  { }
                    assign.props.css      = assign.props.css  or  { }
                    assign.props.css[ s ] = mw.text.trim( pair[ 2 ] )
                end
            end
        end -- i = 1, #css
    end
end -- features()



Sort.faced = function ( args, assign )
    -- Assign a sortable value
    -- Precondition:
    --     args      -- table, to be extended
    --     assign    -- string, to be memorized
    -- Postcondition:
    --     args is extended, if meaningful
    if type( assign ) == "string" then
        local s = mw.text.trim( assign )
        if s ~= "" then
            s = mw.text.decode( s )
            s = mw.ustring.gsub( s, mw.ustring.char( 160 ), " " )
            s = mw.ustring.gsub( s, "%s+", " " )
            s = s:gsub( "\"", "" )
                 :gsub( "<", "" )
                 :gsub( ">", "" )
            s = mw.ustring.sub( s, 1, 99 )
            face( args, "data-sort-value", false, s )
        end
    end
end -- Sort.faced()



Sort.facility = function ()
    -- Retrieve page or project language
    -- Postcondition:
    --     Returns string, downcased
    if type( Sort.slang ) ~= "string" then
        Sort.contLang = Sort.contLang  or
                        mw.language.getContentLanguage()
        Sort.slang    = Sort.contLang:getCode():lower()
    end
    return Sort.slang
end -- Sort.facility()



Sort.fair = function ( args, access, assign )
    -- Assign a non-empty string
    -- Precondition:
    --     args      -- table, to be queried
    --     access    -- string, to identify a component
    --     assign    -- table, to be extended
    -- Postcondition:
    --     assign is extended, if meaningful
    if type( args[ access ] ) == "string" then
        local s = mw.text.trim( args[ access ] )
        if s ~= "" then
            assign[ access ] = s
        end
    end
end -- Sort.fair()



Sort.fault = function ( alert, args )
    -- Error occurred
    -- Parameter:
    --     alert    -- string, with message
    --     args     -- table, parameters
    --                 .elem    -- table, if mw.html
    --                 .cat     -- string|table|nil, for error category
    --                             may contain one or more mw.title
    -- Postcondition:
    --     Returns string, or expands .elem
    local r, suffix
    local e = mw.html.create( "span" )
                     :addClass( "error" )
                     :wikitext( alert )
    if args.cat then
        local s = type( args.cat )
        local c
        if s == "string" then
            s = mw.text.trim( args.cat )
            if s ~= "" then
                c = { }
                table.insert( c, s )
            end
        elseif s == "table" then
            if type( args.cat.baseText ) == "string" then
                c = { }
                table.insert( c, args.cat.text )
            else
                local v
                for i = 1, #args.cat do
                    v = args.cat[ i ]
                    s = type( v )
                    if s == "string" then
                        s = mw.text.trim( v )
                        if s ~= "" then
                            c = c or { }
                            table.insert( c, s )
                        end
                    elseif s == "table"  and
                           type( v.baseText ) == "string" then
                        c = c or { }
                        table.insert( c, v.text )
                    end
                end -- i = 1, #args.cat
            end
        end
        if c then
            suffix = ""
            for i = 1, #c do
                suffix = string.format( "%s[[Category:%s]]",
                                        suffix, c[ i ] )
            end -- i = 1, #c
        end
    end
    if args.elem then
        if suffix then
            e:wikitext( suffix )
        end
        args.elem:node( e )
    else
        r = tostring( e )
        if suffix then
            r = r .. suffix
        end
    end
    return r
end -- Sort.fault()



Sort.feature = function ( args, access, assign )
    -- Retrieve or set CSS property
    -- Precondition:
    --     args      -- table, parameters
    --     access    -- string, property name
    --     assign    -- string|nil, value to be set
    -- Postcondition:
    --     Returns string, or not, if not assigned
    local r
    if assign then
        args.props               = args.props  or  { }
        args.props.css           = args.props.css  or  { }
        args.props.css[ access ] = assign
    elseif args.props  and
       args.props.css  and
       args.props.css[ access ] then
        r = args.props.css[ access ]
    end
    return r
end -- Sort.feature()



Sort.finalize = function ( args, append )
    -- Complete table cell
    -- Parameter:
    --     args      -- table, parameters
    --                  .props     -- table, if present
    --                  .cell      -- true, if mandatory table syntax
    --                  .elem      -- table, if mw.html
    --                  .scream    -- string|nil, with error message
    --     append    -- string|nil, with content
    -- Postcondition:
    --     Returns string, or expands .elem, or nil
    local r
    if args.props then
        if args.elem then
            facing( args, args.elem )
            if append then
                args.elem:wikitext( append )
            end
        elseif append  and  not args.cell then
            local e = mw.html.create( "span" )
                             :wikitext( append )
            facing( args, e )
            r = tostring( e )
        else
            r = facing( args, append )
        end
    elseif args.elem and append then
        args.elem:wikitext( append )
    else
        r = append
    end
    if args.scream then
        if args.elem then
            Sort.fault( args.scream, args )
        else
            r = r or ""
            r = r .. Sort.fault( args.scream, args )
        end
    end
    return r
end -- Sort.finalize()



Sort.first = function ( args, always )
    -- Initialize table cell start
    -- Parameter:
    --     args    -- table, parameters
    --                .cell       -- string|boolean|table, enforce sort
    --                .rowspan    -- number|string, for cell attribute
    --                .colspan    -- number|string, for cell attribute
    --                .class      -- string, for cell attribute
    --                .style      -- string|table, for cell attribute
    --                .id         -- string, for cell attribute
    --                .lang       -- string, for cell attribute
    --                .dir        -- string, for cell attribute
    --                .frame      -- object, if present
    --     always    -- true, if mandatory table syntax
    -- Postcondition:
    --     Returns table with consolidated parameters
    local r = { }
    local s = type( args.style )
    if s == "string" then
        features( args, r )
    elseif s == "table" then
        r.props     = { }
        r.props.css = args.style
    end
    s = type( args.cell )
    if s == "string" then
        r.cell = ( args.cell == "1" )
    elseif s == "table"  and
           type( args.cell.node ) == "function" then
        r.elem = args.cell
        r.cell = true
    elseif s == "boolean" then
        r.cell = args.cell
    else
        r.cell = always
    end
    if r.cell then
        face( r, "rowspan", args, false, true )
        face( r, "colspan", args, false, true )
    end
    face( r, "class", args )
    face( r, "id", args )
    face( r, "lang", args )
    face( r, "dir", args )
    if type( args.frame ) == "table" then
        r.frame = args.frame
    end
    return r
end -- Sort.first()



Sort.following = function ()
    -- Retrieve text order
    -- Postcondition:
    --     Returns true, if left-to-right
    if type( Sort.ltr ) ~= "boolean" then
        Sort.contLang = Sort.contLang  or
                        mw.language.getContentLanguage()
        Sort.ltr = not Sort.contLang:isRTL()
    end
    return Sort.ltr
end -- Sort.following()



Sort.formatDate = function ( align, at )
    -- Format local date and time
    --     align    -- string, with format
    --     at       -- string|nil, with timestamp
    -- Postcondition:
    --     Returns string
    Sort.contLang = Sort.contLang  or
                    mw.language.getContentLanguage()
    return Sort.contLang:formatDate( align, at, true )
end -- Sort.following()



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
    -- 2019-10-15
    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()



-- Export
local p = { }

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.Sort = function ()
    -- Module interface
    return Sort
end

return p