Module:Extension/sandbox

From MediaWiki.org
Jump to navigation Jump to search
Module documentation
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']      = { '', '[[wikipedia:Educational Community License|Educational Community License 2.0]]', 'ECL' },
	['PD']           = { '', '[[wikipedia:Public domain|Public domain]]', 'PD' },
}
local types = {
	ajax                = { '[[w:AJAX|Ajax]]',                                        'Ajax extensions' },
	api                 = { '[[API:Action API|API]]',                                 'API extensions' },
	['beta feature']    = { '[[Beta Features|Beta Feature]]',                         'Beta Feature extensions' },
	contenthandler      = { '[[Manual:ContentHandler|ContentHandler]]',               'ContentHandler extensions' },
	database            = { '[[Manual:Database layout|Database]]',                    'Database extensions' },
	['data extraction'] = { 'Data extraction',                                        'Data extraction extensions' },
	example             = { 'Example',                                                'Extension examples' },
	['extended syntax'] = { '[[Manual:Extending wiki markup|Extended syntax]]',       'Extended syntax extensions' },
	filerepo            = { 'File repository',                                        'File repository extensions' },
	hook                = { '[[Manual:Hooks|Hook]]',                                  'Hook extensions' },
	interface           = { 'User interface',                                         'User interface extensions' },
	link                = { '[[Manual:Extending wiki markup|Link markup]]',           'Link markup extensions' },
	media               = { 'Media',                                                  'Media handling extensions' },
	mywiki              = { '[[Manual:Personalization|MyWiki]]',                      'Personalization extensions' },
	notify              = { 'Notify',                                                 'Notification extensions' },
	['page action']     = { '[[Manual:Parameters to index.php#Actions|Page action]]', 'Page action extensions' },
	parser              = { '[[Manual:Extending wiki markup|Parser extension]]',      'Parser extensions' },
	['parser function'] = { '[[Manual:Parser functions|Parser function]]',            'Parser function extensions' },
	php                 = { 'PHP',                                                    'PHP extensions' },
	search              = { 'Search',                                                 'Search extensions' },
	skin                = { '[[Manual:Skins|Skin]]',                                  'Skin extensions' },
	['special page']    = { '[[Manual:Special pages|Special page]]',                  'Special page extensions' },
	locale              = { '[[Manual:Localization|Locale]]',                         'Internationalization extensions' },
	tag                 = { '[[Manual:Tag extensions|Tag]]',                          'Tag extensions' },
	['user access']     = { '[[Manual:Security|User access]]',                        'User access extensions' },
	['user identity']   = { '[[Manual:Security|User identity]]',                      'User identity extensions' },
	['user rights']     = { '[[Manual:Security|User rights]]',                        'User rights extensions' },
	['user activity']   = { '[[Manual:Security|User activity]]',                      'User activity extensions' },
	variable            = { '[[Manual:Variables|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           = { '[[Manual:Namespaces|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 '[[Category:' .. title .. ']]'
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] .. '[[Category:' .. cnf[2] .. translation .. ']]'
		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, ', ' ) ..
				'<br />\'\'(deprecated, please use [[Special:MyLanguage/Template:Extension/doc#type|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\'\'' ) ..
				' [[Special:MyLanguage/Template:Extension/doc#type|(\'\'\'\'\'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( '[[File:' .. image .. '|link=Special:MyLanguage/Template:Extension#Content|40px]]')
			: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( '[[File:' .. args[ 'image' ] .. '|' .. ( args[ 'imagesize' ] or 300 ) .. 'px]]')
		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#php', 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 ( args[ 'needs-updatephp' ] or getNeedsUpdates() ) then
		local row9 = mw.html.create( 'tr' )
		local data9_1 = mw.html.create( 'td' )
		data9_1
			:wikitext( frame:expandTemplate{ title = 'll', args = { 'Template:Extension#needs-updatephp',
				frame:preprocess( '<abbr title="' .. getMessage( args, 'Needs update' ) .. '">' ) .. getMessage( args, 'Database changes' ) } } )
		local data9_2 = mw.html.create( 'td' )
			:wikitext( args[ 'needs-updatephp' ] or getNeedsUpdates() )
		row9:node( data9_1 )
		row9:node( data9_2 )
		infobox:node( row9 )
	end
	if ( p.getVersion( args[ 'latest release version' ] or args[ 'latest_release_version' ] or args[ 'version' ] or '' ) ) then
		local row14 = mw.html.create( 'tr' )
		local data14_1 = mw.html.create( 'td' )
		data14_1
			:wikitext( frame:expandTemplate{ title = 'll', args = { 'Template:Extension#version', getMessage( args, 'Latest version' ) } } )
		local data14_2 = mw.html.create( 'td' )
			:wikitext( p.getVersion( args[ 'latest release version' ] or args[ 'latest_release_version' ] or args[ 'version' ] or '' ) )
		row14:node( data14_1 )
		row14:node( data14_2 )
		infobox:node( row14 )
	end
	if ( args[ 'latest preview version' ] or args[ 'latest_preview_version' ] or args[ 'version_preview' ] or args[ 'version preview' ] ) then
		local row15 = mw.html.create( 'tr' )
		local data15_1 = mw.html.create( 'td' )
		data15_1
			:wikitext( frame:expandTemplate{ title = 'll', args = { 'Template:Extension#version', getMessage( args, 'Latest preview version' ) } } )
		local data15_2 = mw.html.create( 'td' )
			:wikitext( args[ 'latest preview version' ] or args[ 'latest_preview_version' ] or args[ 'version_preview' ] or args[ 'version preview' ] )
		row15:node( data15_1 )
		row15:node( data15_2 )
		infobox:node( row15 )
	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( '[https://doc.wikimedia.org/mediawiki-vagrant/puppet_classes/role_3A_3A' .. 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( '[[phab:tag/' .. phabTag .. '|' .. getMessage( args, 'Open tasks' ) ..
				']] · [https://phabricator.wikimedia.org/maniphest/task/create/?projects=' ..
				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( '[https://www.github.com/' .. args[ 'github' ] ..
				'/issues' .. getMessage( args, 'Open issues' ) .. '] · [https://www.github.com/' ..
				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#', getMessage( args, 'Message' ) } } )
		local data_2 = mw.html.create( 'td' )
		
		row:node( data_1 )
		row:node( data_2 )
		infobox:node( row )
	end
	]]--
	local topPhabTag = frame:expandTemplate{ title = 'Ptag', args = { string.lower( args[ 'phabricator' ] or 'MediaWiki-extensions-' .. args[ 'buzilla' ] ) or '' } };
	local templatestyles = frame:extensionTag ('templatestyles', '', {src='Extension/styles.css'});
	return table.concat ({ topPhabTag, templatestyles, 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