Module:Extension/sandbox

local lang = mw.language.getContentLanguage --local translation = mw.getCurrentFrame:expandTemplate{ title = 'translation' } local translation = mw.getCurrentFrame:callParserFunction{name='#translation', args="1"} local addr = { GNU = '//www.gnu.org/licenses/', OSI = '//opensource.org/licenses/', CC = '//creativecommons.org/licenses/', Mozilla = '//www.mozilla.org/' } local cats = { GPL   = 'GPL licensed extensions', FDL   = 'FDL licensed extensions', LGPL  = 'LGPL licensed extensions', AGPL  = 'AGPL licensed extensions', MIT   = 'MIT licensed extensions', ISC   = 'ISC licensed extensions', BSD   = 'BSD licensed extensions', MPL   = 'MPL licensed extensions', WTFPL = 'WTFPL licensed extensions', Apache = 'Apache licensed extensions', PD    = 'Public domain licensed extensions', CC    = 'Creative Commons licensed extensions', ECL   = 'Educational Community licensed extensions', } local licenses = { ['GPL-2.0']     = { addr.GNU .. 'old-licenses/gpl-2.0-standalone.html', 'GNU General Public License 2.0', 'GPL' }, ['GPL-2.0-only'] = { addr.GNU .. 'old-licenses/gpl-2.0-standalone.html', 'GNU General Public License 2.0 only', 'GPL' }, ['GPL-2.0-or-later'] = { addr.GNU .. 'old-licenses/gpl-2.0-standalone.html', 'GNU General Public License 2.0 or later', 'GPL' }, ['GPL-3.0']     = { addr.GNU .. 'gpl-3.0-standalone.html', 'GNU General Public License 3.0', 'GPL' }, ['GPL-3.0-only'] = { addr.GNU .. 'gpl-3.0-standalone.html', 'GNU General Public License 3.0 only', 'GPL' }, ['GPL-3.0-or-later'] = { addr.GNU .. 'gpl-3.0-standalone.html', 'GNU General Public License 3.0 or later', 'GPL' }, ['AGPL-3.0']    = { addr.GNU .. 'agpl-3.0.html', 'GNU Affero General Public License 3.0', 'AGPL' }, ['LGPL-2.1']    = { addr.GNU .. 'old-licenses/lgpl-2.1-standalone.html', 'GNU Lesser General Public License 2.1', 'LGPL' }, ['LGPL-2.1-only'] = { addr.GNU .. 'old-licenses/lgpl-2.1-standalone.html', 'GNU Lesser General Public License 2.1 only', 'LGPL' }, ['LGPL-2.1-or-later'] = { addr.GNU .. 'old-licenses/lgpl-2.1-standalone.html', 'GNU Lesser General Public License 2.1 or later', 'LGPL' }, ['LGPL-3.0']    = { addr.GNU .. 'lgpl-3.0-standalone.html', 'GNU Lesser General Public License 3.0', 'LGPL' }, ['LGPL-3.0-only'] = { addr.GNU .. 'lgpl-3.0-standalone.html', 'GNU Lesser General Public License 3.0 only', 'LGPL' }, ['LGPL-3.0-or-later'] = { addr.GNU .. 'lgpl-3.0-standalone.html', 'GNU Lesser General Public License 3.0 or later', 'LGPL' }, ['FDL']         = { addr.GNU .. 'fdl.html', 'GNU Free Documentation License', 'FDL' }, ['MIT']         = { addr.OSI .. 'mit-license.php', 'MIT License', 'MIT' }, ['ISC']         = { addr.OSI .. 'ISC', 'ISC License', 'ISC' }, ['BSD-2-Clause'] = { addr.OSI .. 'BSD-2-Clause', 'BSD 2-clause "Simplified" License', 'BSD' }, ['BSD-3-Clause'] = { addr.OSI .. 'BSD-3-Clause', 'BSD 3-clause "Modified" License', 'BSD' }, ['BSD-4-Clause'] = { addr.GNU .. 'license-list.html#OriginalBSD', 'BSD 4-clause "Original" License', 'BSD' }, ['MPL-1.0']     = { addr.Mozilla .. 'MPL/1.0/', 'Mozilla Public License 1.0', 'MPL' }, ['MPL-2.0']     = { addr.Mozilla .. 'MPL/2.0/', 'Mozilla Public License 2.0', 'MPL' }, ['WTFPL']       = { 'http://www.wtfpl.net', 'WTFPL 2.0', 'WTFPL' }, ['Apache-2.0']  = { '//www.apache.org/licenses/LICENSE-2.0', 'Apache License 2.0', 'Apache' }, ['Zlib']        = { addr.OSI .. 'Zlib', 'zlib License' }, ['CC0-1.0']     = { '//creativecommons.org/publicdomain/zero/1.0/', 'Creative Commons Zero v1.0 Universal', 'PD' }, ['CC-BY-3.0']   = { addr.CC .. 'by/3.0/', 'Creative Commons Attribution 3.0', 'CC' }, ['CC-BY-SA-2.0'] = { addr.CC .. 'by-sa/2.0/', 'Creative Commons Attribution Share Alike 2.0', 'CC' }, ['CC-BY-SA-2.5'] = { addr.CC .. 'by-sa/2.5/', 'Creative Commons Attribution Share Alike 2.5', 'CC' }, ['CC-BY-NC-SA-2.5'] = { addr.CC .. 'by-nc-sa/2.5/', 'Creative Commons Attribution NonCommercial Share Alike 2.5', 'CC' }, ['CC-BY-NC-SA-3.0'] = { addr.CC .. 'by-nc-sa/3.0/', 'Creative Commons Attribution NonCommercial Share Alike 3.0', 'CC' }, ['CC-BY-NC-3.0'] = { addr.CC .. 'by-nc/3.0/', 'Creative Commons Attribution NonCommercial 3.0', 'CC' }, ['CC-BY-SA-3.0'] = { addr.CC .. 'by-sa/3.0/', 'Creative Commons Attribution Share Alike 3.0', 'CC' }, ['CC-BY-SA-4.0'] = { addr.CC .. 'by-sa/4.0/', 'Creative Commons Attribution Share Alike 4.0', 'CC' }, ['ECL-2.0']     = { '', 'Educational Community License 2.0', 'ECL' }, ['PD']          = { '', 'Public domain', 'PD' }, } local types = { ajax               = { 'Ajax',                                        'Ajax extensions' }, api                = { 'API',                                 'API extensions' }, ['beta feature']   = { 'Beta Feature',                         'Beta Feature extensions' }, contenthandler     = { 'ContentHandler',               'ContentHandler extensions' }, database           = { 'Database',                    'Database extensions' }, ['data extraction'] = { 'Data extraction',                                       'Data extraction extensions' }, example            = { 'Example',                                                'Extension examples' }, ['extended syntax'] = { 'Extended syntax',      'Extended syntax extensions' }, filerepo           = { 'File repository',                                        'File repository extensions' }, hook               = { 'Hook',                                  'Hook extensions' }, interface          = { 'User interface',                                         'User interface extensions' }, link               = { 'Link markup',           'Link markup extensions' }, media              = { 'Media',                                                  'Media handling extensions' }, mywiki             = { 'MyWiki',                      'Personalization extensions' }, notify             = { 'Notify',                                                 'Notification extensions' }, ['page action']    = { 'Page action', 'Page action extensions' }, parser             = { 'Parser extension',      'Parser extensions' }, ['parser function'] = { 'Parser function',           'Parser function extensions' }, php                = { 'PHP',                                                    'PHP extensions' }, search             = { 'Search',                                                 'Search extensions' }, skin               = { 'Skin',                                  'Skin extensions' }, ['special page']   = { 'Special page',                  'Special page extensions' }, locale             = { 'Locale',                         'Internationalization extensions' }, tag                = { 'Tag',                          'Tag extensions' }, ['user access']    = { 'User access',                        'User access extensions' }, ['user identity']  = { 'User identity',                      'User identity extensions' }, ['user rights']    = { 'User rights',                        'User rights extensions' }, ['user activity']  = { 'User activity',                      'User activity extensions' }, variable           = { 'Variable',                          'Variable extensions' }, -- DEPRECATED TYPES (as per 2007-09 taxonomy discussion) category           = { 'Category',                                               'Category extensions',  deprecated = true }, form               = { 'Form',                                                   'Form extensions',      deprecated = true }, list               = { 'List',                                                   'List extensions',      deprecated = true }, namespace          = { 'Namespace',                        'Namespace extensions', deprecated = true }, ['table']          = { 'Table',                                                  'Table extensions',     deprecated = true }, }

local typeAliases = { db = 'database', pfunc = 'parser function', special = 'special page', }

-- DEPRECATED TYPES (multiple types handled via type1,type2,...) local deprecatedTypes = { ['link, tag, special'] = { 'link', 'tag', 'special page' }, ['parser function, special'] = { 'parser function', 'special page' }, ['tag, parser function'] = { 'tag', 'parser function' }, ['tag, parser function, special'] = { 'tag', 'parser function', 'special page' }, ['tag, special'] = { 'tag', 'special page' }, ['parser, pfunc'] = { 'parser function' }, ['parser, hook, special'] = { 'tag' -- sic, 'hook', 'special page' }, }

local function setI18n( from, to, index ) for n, v in pairs( from ) do		if to[n] then to[n][index] = v		end end end

local function cat( title ) return '' end

local function tcat( title ) return cat( title .. translation ) end

local function getType( str, str2 ) local str = mw.ustring.lower( str ) if typeAliases[str] then str = typeAliases[str] end local cnf = types[str] local res if cnf then res = cnf[1] .. ''		if cnf.deprecated then res = res .. '\'\'-deprecated\'\'' .. tcat( 'Extensions with deprecated types' ) end else cnf = deprecatedTypes[str] if cnf then local dtypes = {} for _, sstr in ipairs( cnf ) do				table.insert( dtypes, getType( sstr ) ) end res = table.concat( dtypes, ', ' ) .. ' \'\'(deprecated, please use type1,type2'			if #cnf > 2 then				res = res .. ',type3'			end			res = res .. ' instead)\'\'' .. tcat( 'Extensions with deprecated types' ) elseif str == '_missing_' then res = tcat( 'Extensions with invalid or missing type' ) elseif str == '_demomode_' then if str2 then res = lang:ucfirst( str2 ) else res = "unknown" end else res = ( str or '\'\'unknown\'\'' ) .. ' (\'\'\'\'\'invalid type\'\'\'\'\')' .. tcat( 'Extensions with invalid or missing type' ) end end return res end

local function getLicenseCategory( str ) if mw.ustring.sub( str, -1 ) == '+' then str = mw.ustring.sub( str, 1, -2 ) end local cnf = licenses[str] if cnf then if #cnf > 2 then return tcat( cats[cnf[3]] ) end else return tcat( 'Extensions with unknown license' ) end end

local function getFormattedLicense( str, orlatertext ) local orlater = '' local license = str if mw.ustring.sub( str, -1 ) == '+' then license = mw.ustring.sub( str, 1, -2 ) orlater = orlatertext end local cnf = licenses[license] if cnf then return (cnf[1] ~= '' and ('[' .. cnf[1] .. ' ' .. cnf[2] .. ']') or cnf[2]) .. orlater else return str end end

local p = {}

function p.getTypes( frame ) setI18n( frame.args, types, 1 ) local args = frame:getParent.args local types = {} local params = { args.type1 or args['type'] or 'missing', args.type2, args.type3, args.type4, args.type5, args.type6, }	for _, param in ipairs( params ) do		if param == nil or mw.text.trim( param ) == '' then break end local param = mw.text.trim( param ) if args.templatemode == 'nocats' then table.insert( types, getType( '_demomode_', param ) ) else table.insert( types, getType( param ) ) end end return table.concat( types, ', ' ) end

function p.getType( frame ) setI18n( frame.args, types, 1 ) return getType( frame.args[1] ) end

function p.getLicenseCategory( frame ) return getLicenseCategory( frame.args[1] ) end

function p.getFormattedLicense( frame ) setI18n( frame.args, licenses, 2 ) return getFormattedLicense( frame.args[1] and mw.text.trim( frame.args[1] ) or nil, frame.args['+'] or ' or later' ) end

function getExtData local pg = mw.title.getCurrentTitle.rootPageTitle:partialUrl -- need to get rid of translation subpage. return mw.loadData( 'Module:ExtensionJson' )[pg] end

-- Return if the extension does schema updates -- Only answer yes. For now be silent on no or unknown, as its unclear -- if this info should be in infobox if the answer is not yes. function p.getNeedsUpdates( frame ) local data = getExtData if data ~= nil and data.Hooks ~= nil and data.Hooks.LoadExtensionSchemaUpdates ~= nil then return 'yes' end return '' end

function p.getVersion( version ) if version ~= nil and mw.text.trim(version) ~= "" then return version end local data = getExtData if data ~= nil and data.version ~= nil then return data.version end return '' end

function p.main( frame ) local args = frame:getParent.args local infobox = mw.html.create( 'table' ) local status = getStatus( args[ 'status' ] or '' ) infobox :addClass( 'tpl-infobox' ) :addClass( 'ext-infobox' ) :addClass( 'ext-status-' .. status ) local caption = mw.html.create( 'caption' ) caption :wikitext( "" .. frame:expandTemplate{ title = 'll', args = { 'Manual:Extensions', getMessage( args, 'MediaWiki extensions manual' ) } } .. "" ) infobox:node( caption )

--START HEADER WITH IMAGE, NAME, AND STATUS local row0 = mw.html.create( 'tr' ) :addClass( 'tpl-infobox-header ext-infobox-header' ) local image = ( status == 'unstable' and 'OOjs_UI_icon_alert-invert.svg' or 'OOjs UI icon advanced.svg' ) local data0_1 = mw.html.create( 'th' ) :attr( 'colspan', 2 ) :css( 'padding-top', '0.5em' ) local data0_span = mw.html.create( 'span' ) :css( 'font-size', '130%' ) :css( 'line-height', '100%' ) :wikitext( args[ 'name' ] or 'defaultName' ) data0_1 :tag( 'div' ) :addClass( 'floatleft' ) :wikitext( '') :done :node( data0_span ) :tag( 'br' ) :done :wikitext( frame:expandTemplate{ title = 'll', args = { 'Extension status', getMessage( args, 'Release status' ) } } .. ": " .. status ) --TODO: add category row0:node( data0_1 ) infobox:node( row0 ) --END HEADER --START IMAGE if ( args[ 'image' ] ) then local row1 = mw.html.create( 'tr' ) local data1_1 = mw.html.create( 'td' ) data1_1 :attr( 'colspan', 2 ) :css( 'text-align', 'center' ) :wikitext( '') row1:node( data1_1 ) infobox:node( row1 ) end --TODO: add category for no image --END IMAGE --START IMPLEMENTATION TYPE if ( args[ 'type' ] or args[ 'type1' ] ) then local row2 = mw.html.create( 'tr' ) local data2_1 = mw.html.create( 'td' ) data2_1 :wikitext( frame:expandTemplate{ title = 'll', args = { 'Template:Extension#type', getMessage( args, 'Implementation' ) } } ) local typeString = getTypeLink( args[ 'type' ] or args[ 'type1' ] ) if ( args[ 'type2' ] ) then typeString = typeString .. ', ' .. getTypeLink( args[ 'type2' ] ) end if ( args[ 'type3' ] ) then typeString = typeString .. ', ' .. getTypeLink( args[ 'type3' ] ) end if ( args[ 'type4' ] ) then typeString = typeString .. ', ' .. getTypeLink( args[ 'type4' ] ) end if ( args[ 'type5' ] ) then typeString = typeString .. ', ' .. getTypeLink( args[ 'type5' ] ) end if ( args[ 'type6' ] ) then typeString = typeString .. ', ' .. getTypeLink( args[ 'type6' ] ) end local data2_2 = mw.html.create( 'td' ) data2_2 :wikitext( typeString ) --TODO: add getTypes call --TODO: add category check --TODO: add missing getType call row2:node( data2_1 ) row2:node( data2_2 ) infobox:node( row2 ) end --END IMPLEMENTATION if ( args[ 'description' ] ) then local row3 = mw.html.create( 'tr' ) local data3_1 = mw.html.create( 'td' ) data3_1 :wikitext( frame:expandTemplate{ title = 'll', args = { 'Template:Extension#Description', getMessage( args, 'Description') } } ) local data3_2 = mw.html.create( 'td' ) data3_2 :wikitext( args[ 'description' ] ) row3:node( data3_1 ) row3:node( data3_2 ) infobox:node( row3 ) end if ( args[ 'author' ] or args[ 'username' ] ) then local row4 = mw.html.create( 'tr' ) local data4_1 = mw.html.create( 'td' ) :wikitext( frame:expandTemplate{ title = 'll', args = { 'Template:Extension#username', getMessage( args, 'Author(s)' ) } } ) local data4_2 = mw.html.create( 'td' ) :wikitext( args[ 'author' ] or args[ 'username' ] ) row4:node( data4_1 ) :node( data4_2 ) infobox:node( row4 ) end if ( args[ 'maintainer' ] ) then local row5 = mw.html.create( 'tr' ) local data5_1 = mw.html.create( 'td' ) :wikitext( frame:expandTemplate{ title = 'll', args = { 'Template:Extension#maintainer', getMessage( args, 'maintainer' ) } } ) local data5_2 = mw.html.create( 'td' ) :wikitext( args[ 'maintainer' ] ) row5:node( data5_1 ) row5:node( data5_2 ) infobox:node( row5 ) end if ( args[ 'compatibility policy' ] ) then local row6 = mw.html.create( 'tr' ) local data6_1 = mw.html.create( 'td' ) data6_1 :wikitext( frame:expandTemplate{ title = 'll', args = { 'Compatibility#mediawiki_extensions', getMessage( args, 'Compatibility policy' ) } } ) local data6_2 = mw.html.create( 'td' ) :wikitext( getCompatibilityPolicy( args, args[ 'compatibility policy' ] ) ) row6:node( data6_1 ) row6:node( data6_2 ) infobox:node( row6 ) end if ( args[ 'mediawiki' ] ) then local row7 = mw.html.create( 'tr' ) local data7_1 = mw.html.create( 'td' ) data7_1 :wikitext( frame:expandTemplate{ title = 'll', args = { 'Template:Extension#mediawiki', getMessage( args, 'mediawiki' ) } } ) local data7_2 = mw.html.create( 'td' ) :wikitext( args[ 'mediawiki' ] ) row7:node( data7_1 ) row7:node( data7_2 ) infobox:node( row7 ) end if ( args[ 'php' ] ) then local row8 = mw.html.create( 'tr' ) local data8_1 = mw.html.create( 'td' ) data8_1 :wikitext( frame:expandTemplate{ title = 'll', args = { 'Template:Extension#pbp', getMessage( args, 'PHP' ) } } ) local data8_2 = mw.html.create( 'td' ) :wikitext( args[ 'php' ] ) row8:node( data8_1 ) row8:node( data8_2 ) infobox:node( row8 ) end if ( p.getVersion( args[ 'latest release version' ] or args[ 'latest_release_version' ] or args[ 'version' ] or '' ) ) then local row9 = mw.html.create( 'tr' ) local data9_1 = mw.html.create( 'td' ) data9_1 :wikitext( frame:expandTemplate{ title = 'll', args = { 'Template:Extension#version', getMessage( args, 'Latest version' ) } } ) local data9_2 = mw.html.create( 'td' ) :wikitext( p.getVersion( args[ 'latest release version' ] or args[ 'latest_release_version' ] or args[ 'version' ] or '' ) ) row9:node( data9_1 ) row9:node( data9_2 ) infobox:node( row9 ) end if ( args[ 'latest preview version' ] or args[ 'latest_preview_version' ] or args[ 'version_preview' ] or args[ 'version preview' ] ) then local row10 = mw.html.create( 'tr' ) local data10_1 = mw.html.create( 'td' ) data10_1 :wikitext( frame:expandTemplate{ title = 'll', args = { 'Template:Extension#version', getMessage( args, 'Latest preview version' ) } } ) local data10_2 = mw.html.create( 'td' ) :wikitext( args[ 'latest preview version' ] or args[ 'latest_preview_version' ] or args[ 'version_preview' ] or args[ 'version preview' ] ) row10:node( data10_1 ) row10:node( data10_2 ) infobox:node( row10 ) end if ( args[ 'table1' ] ) then local translateable = frame:expandTemplate{ title = 'translatable' } local row20 = mw.html.create( 'tr' ) local data20_1 = mw.html.create( 'td' ) data20_1 :wikitext( frame:expandTemplate{ title = 'll', args = { 'Template:Extension#table1', getMessage( args, 'Tables' ) } } ) local data20_2 = mw.html.create( 'td' ) data20_2 :wikitext( frame:expandTemplate{ title = 'll', args = { translateable .. '/' .. args[ 'table1'] .. ' table', args[ 'table1' ] } } ) if ( args[ 'table2' ] ) then data20_2 :tag( 'br' ) :done :wikitext( frame:expandTemplate{ title = 'll', args = { translateable .. '/' .. args[ 'table2'] .. ' table', args[ 'table2' ] } } ) :done if ( args[ 'table3' ] ) then data20_2 :tag( 'br' ) :done :wikitext( frame:expandTemplate{ title = 'll', args = { translateable .. '/' .. args[ 'table3'] .. ' table', args[ 'table3' ] } } ) :done if ( args[ 'table4' ] ) then data20_2 :tag( 'br' ) :done :wikitext( frame:expandTemplate{ title = 'll', args = { translateable .. '/' .. args[ 'table4'] .. ' table', args[ 'table4' ] } } ) :done if ( args[ 'table5' ] ) then data20_2 :tag( 'br' ) :done :wikitext( frame:expandTemplate{ title = 'll', args = { translateable .. '/' .. args[ 'table5'] .. ' table', args[ 'table5' ] } } ) :done if ( args[ 'table6' ] ) then data20_2 :tag( 'br' ) :done :wikitext( frame:expandTemplate{ title = 'll', args = { translateable .. '/' .. args[ 'table6'] .. ' table', args[ 'table6' ] } } ) :done end end end end end row20:node( data20_1 ) row20:node( data20_2 ) infobox:node( row20 ) end if ( args[ 'vagrant-role' ] ) then local row101 = mw.html.create( 'tr' ) local data101_1 = mw.html.create( 'td' ) data101_1 :wikitext( frame:expandTemplate{ title = 'll', args = { 'MediaWiki-Vagrant#Using roles', getMessage( args, 'Vagrant role' ) } } ) local data101_2 = mw.html.create( 'td' ) :wikitext( '.. args[ 'vagrant-role' ..'.html ' .. args[ 'vagrant-role' ] .. ']') row101:node( data101_1 ) row101:node( data101_2 ) infobox:node( row101 ) end if ( args[ 'phabricator' ] or args[ 'bugzilla' ] ) then local phabTag = string.lower( args[ 'phabricator' ] or 'MediaWiki-extensions-' .. args[ 'buzilla' ] ) local row102 = mw.html.create( 'tr' ) local data102_1 = mw.html.create( 'td' ) data102_1 :wikitext( frame:expandTemplate{ title = 'll', args = { 'Phabricator', getMessage( args, 'Issues' ) } } ) local data102_2 = mw.html.create( 'td' ) :wikitext(  .. getMessage( args, 'Open tasks' ) ..				' · ..				phabTag .. getMessage( args, 'Report a bug' ) ..  ) row102:node( data102_1 ) row102:node( data102_2 ) infobox:node( row102 ) end if ( args[ 'github' ] ) then local row3 = mw.html.create( 'tr' ) local data103_1 = mw.html.create( 'td' ) data103_1 :wikitext( frame:expandTemplate{ title = 'll', args = { 'Gerrit/GitHub', getMessage( args, 'Issues' ) } } ) local data103_2 = mw.html.create( 'td' ) :wikitext( '.. args[ 'github' ..				'/issues' .. getMessage( args, 'Open issues' ) .. '] · ..				args[ 'github' .. '/issues/new' .. getMessage( args, 'Report a bug' ) .. ']' ) row103:node( data103_1 ) row103:node( data103_2 ) infobox:node( row103 ) end --	if ( args[ '' ] ) then		local row = mw.html.create( 'tr' )		local data_1 = mw.html.create( 'td' )		data_1			:wikitext( frame:expandTemplate{ title = 'll', args = { 'Template:Extension-- return table.concat ({ frame:extensionTag ('templatestyles', '', {src='Extension/styles.css'}), tostring( infobox ) }); end

function getMessage( args, message ) return message -- placeholder, will need args passed with translations end

function getTypeLink( typeKey ) typeKey = string.lower( typeKey ) if typeAliases[typeKey] then typeKey = typeAliases[typeKey] end return types[ typeKey ][ 1 ] end

function getCompatibilityPolicy( args, policy ) if policy == 'master' then return getMessage( args, 'master' ) elseif policy == 'rel' then return getMessage( args, 'release branches' ) else return 'error in compatibility policy' end end

function getStatus( status ) if status == nil then return 'unknown' end status = string.lower( status ) knownStatuses = { unmaintained = true, archive = true, milestone = true, unstable = true, experimental = true, beta = true, stable = true, magic = true, }	if knownStatuses[ status ] then return status else return 'unknown' end end

return p