From Wikipedia, the free encyclopedia

local dts = require('Module:User:Anomie/deepToString').deepToString -- for debugging



local p = {}



local basicDisplayParams = {

    'small',

    'category',

    'listas',

    'class',

    'auto',

    'importance',

    'attention',

}



-- Replaces bar characters with a pseudo-random string for converting back later.

local function debar( s )

    local s = mw.ustring.gsub( s, '|', 'DEBARRED-29vuy7dsgtz87465gfbq29gr1bzj-DERRABED' )

    return s

end



-- Undoes the transformation done by debar().

local function rebar( s )

    local s = mw.ustring.gsub( s, 'DEBARRED%-29vuy7dsgtz87465gfbq29gr1bzj%-DERRABED', '|' )

    return s

end



-- Returns a table containing the numbers of the arguments that exist for the specified prefix and suffix.

local function getArgNums( t, prefix, suffix )

    if type( t ) ~= 'table' then

        return nil

    end

    prefix = type( prefix ) == 'string' and prefix or ''

    suffix = type( suffix ) == 'string' and suffix or ''

    local nums = {}

    for k, v in pairs( t ) do

        if mw.ustring.find( v, '%S' ) then

            local num = tostring( k )

            num = mw.ustring.match( num, '^' .. prefix .. '([1-9]%d*)' .. suffix .. '$' )

            if num then

                table.insert( nums , tonumber( num ) )

            end

        end

    end

    table.sort( nums )

    return nums

end



local function getAliasNames( s, t )

    if type( s ) ~= 'string' then return end

    local t = t or {}

    for tripleBraces in mw.ustring.gmatch( s, '{{%b{}}}' ) do

        tripleBraces = mw.ustring.sub( tripleBraces, 4, -4 )

        local alias, default = mw.ustring.match( tripleBraces, '^(.-)|(.*)$' )

        if not alias then

            alias = tripleBraces

        end

        table.insert( t, mw.text.trim( alias ) )

        if default then

            getAliasNames( default, t )

        end

    end    

    return t

end



-- Searches a string for the first instance of the specified template, and returns a table with the template arguments.

local function getTemplateArgs( s, templateName )

    if type( s ) ~= 'string' or type( templateName ) ~= 'string' or #templateName == 0 then

        return nil

    end

    -- Process the template name so that we can match both upper case and lower case for the first character.

    local firstLetter, lastLetters

    if #templateName == 1 then

        firstLetter, lastLetters = templateName, ''

    else

        firstLetter, lastLetters = mw.ustring.sub( templateName, 1, 1 ), mw.ustring.sub( templateName, 2, -1 )

    end

    local pattern = mw.ustring.format( '^{{%%s*[%s%s]%s%%s*[|}]', mw.ustring.lower( firstLetter ), mw.ustring.upper( firstLetter ), lastLetters )

    -- Find the template text.

    local template

    for braces in mw.ustring.gmatch( s, '{%b{}}' ) do

        if mw.ustring.match( braces, pattern ) then

            template = braces

            break

        end

    end

    if not template then

        return nil

    end

    -- Temporarily replace characters inside [[]] or {{}} with a quasi-random code. The bars that are left delineate the template's parameters.

    template = mw.ustring.sub( template, 3, -3 ) -- Strip the double braces so that debar() doesn't match the whole banner.

    template = mw.ustring.gsub( template, '{%b{}}', debar )

    template = mw.ustring.gsub( template, '%[%b[]%]', debar )

    -- Build the table of parameters.

    local params = {}

    for field in mw.ustring.gmatch( template, '|([^|]*)' ) do

        local param, value = nil, nil

        if mw.ustring.find( field, '=' ) then

            param, value = mw.ustring.match( field, '%s*([^=]-)%s*=(.*)' )

            value = value or ''

            value = mw.text.trim( value )

        else

            value = field

        end

        if param then

            paramNum = tonumber( param )

            if paramNum and paramNum >= 1 and math.floor( paramNum ) == paramNum and paramNum ~= math.huge then

                param = paramNum

            end

            param = mw.ustring.gsub( param, ' ', '_' )

            if not value then

                params mw.ustring.lower( param )  = ''

            else

                params mw.ustring.lower( param )  = value

            end

        else

            table.insert( params, value )

        end

    end

    -- Replace the quasi-random code with the bars again.

    for k, v in pairs( params ) do

        params k  = rebar( v )

    end

    return params

end



local function processRow( t, prefixTable, suffixTable, num )

    num = num and tostring( num ) or ''

    local ret = {}

    for i, prefix in ipairs( prefixTable ) do

        for j, suffix in ipairs( suffixTable ) do

            if type( prefix ) == 'string' and type( suffix ) == 'string' then

                local arg = mw.ustring.format( '%s%s%s', prefix, num, suffix )

                local val = t arg 

                if val and mw.ustring.find( val, '%S' ) then

                    local suffixTrimmed = mw.ustring.match( suffix, '^_+(.-)$' ) or suffix

                    local aliases = getAliasNames( val )

                    if #aliases >= 1 then

                        local aliasParam = suffixTrimmed == '' and 'aliases' or suffixTrimmed .. '_aliases'

                        ret aliasParam  = aliases

                    else

                        ret suffixTrimmed  = val

                    end

                end

            end

        end

    end

    return ret

end





local function processRows( t, prefixTable, suffixTable, nums )

    if type( t ) ~= 'table' then

        return nil

    end

    if type( prefixTable ) ~= 'table' or #prefixTable == 0 then

        prefixTable = { '' }

    end

    if type( suffixTable ) ~= 'table' or #suffixTable == 0 then

        suffixTable = { '' }

    end

    nums = type( nums ) == 'table' and nums

    ret = {}

    if nums then

        for i, num in ipairs( nums ) do

            if type( num ) == 'number' and num >= 1 and math.floor( num ) == num and num ~= math.huge then

                table.insert( ret, processRow( t, prefixTable, suffixTable, num ) )

            end

        end

    else

        return processRow( t, prefixTable, suffixTable, num )

    end

    return ret

end



function p.main( frame )

    local page

    if frame == mw.getCurrentFrame() then

        page = frame:getParent().args1

        if not page then

            page = frame.args1

        end

    else

        page = frame

    end

    if type( page ) ~= 'string' then return end

    local pageObject = mw.title.new( page )

    if not pageObject then return end

    local content = pageObject:getContent()

    if not content then return end

    content = mw.ustring.gsub( content, '<!%-%-.-%-%->', '' ) -- Remove html comments.

    

    local params = getTemplateArgs( content, 'WPBannerMeta' )

    local aliases = {}

    for i, param in ipairs( basicDisplayParams ) do

        local aliasNames = getAliasNames( params param  )

        aliases param  = aliasNames

    end

    local tfnums = getArgNums( params, 'tf_' )

    local tf = processRows( params, { 'tf_' }, { '', '_link', '_name', '_image', '_nested', '_text', '_quality', '_main_cat', '_assessment_cat' }, tfnums )

    do return dts( tf ) end -- for debugging

    

    local rows = {}

    for i, ptable in ipairs( params ) do

        params i ][ 2  = rebar( ptable 2  )

        if type( ptable 1  ) == 'number' then

            table.insert( rows, mw.ustring.format( '[%s] = "%s"', mw.ustring.lower( tostring( ptable 1   ) ), ptable 2   ) )

        else

            table.insert( rows, mw.ustring.format( '%s = "%s"', mw.ustring.lower( ptable 1  ), ptable 2  ) )

        end

    end

    return mw.ustring.format( 'local banner = {\n    %s\n}', table.concat( rows, ',\n    ' ) )

end



return p