Module:User:Mr. Stradivarius/BannerConvert

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, '' ) 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.args[1] if not page then page = frame.args[1] 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