Module:User:Mr. Stradivarius/BannerConvert
Appearance
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().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