Module:Edit table

Jump to navigation Jump to search

This module implements {{Edit table}}, see template's document for usages.

[view] [edit] [history] [refresh]The above documentation is transcluded from Module:Edit table/doc.
local p = {}

local i18n = {
	countsrc = '{{Special:Editcount/%s/%s}}',
	datadesc = 'Edit table',
	errormsg = '<span class="error" style="font-weight: bold;">[[Template:Edit table]]: %s</span>',
	error_nogrp = 'At least one user and their namespace(s) is/are required.',
	error_nons = 'At least one namespace is required.',
	error_nouser = 'Must provide username.',
	rownsname = mw.getCurrentFrame():callParserFunction( 'int:editcount namespace' ),
	rowcount = mw.getCurrentFrame():callParserFunction( 'int:editcount edits' ),
	type_multiuser = 'multiuser',
	type_special = 'special',
	usercontrib = 'Contributions of [[User:%s|%s]]:',
	userlink = '[[User:%s|%s]]',
}

local function fetchElements( tbl, index, collapsed )
	if not tbl or type( tbl ) ~= 'table' then
		return nil
	end

	index = index or 0
	if type( index ) ~= 'number' then
		return nil
	end

	local result_pre = {}
	local keys_anon = {}
	local keys_name = {}
	if index == 0 then
		result_pre = tbl
	else
		for k, v in pairs( tbl ) do
			if type( k ) == 'number' then
				if k > index then
					result_pre[ k - index ] = v
					table.insert( keys_anon, k - index )
				end
			else
				result_pre[ k ] = v
				table.insert( keys_name, k )
			end
		end
	end

	if not collapsed then
		if #keys_anon == 0 and #keys_name == 0 then
			return nil
		else
			return result_pre
		end
	end

	local result = {}
	table.sort( keys_anon )
	for _, v in pairs( keys_anon ) do
		table.insert( result, result_pre[ v ] )
	end
	for _, v in pairs( keys_name ) do
		result[ v ] = result_pre[ v ]
	end
	if #keys_anon == 0 and #keys_name == 0 then
		return nil
	else
		return result
	end
end

local function getNSName( namespace )
	if not namespace then
		return nil
	end

	if namespace:lower() == 'main' then
		return mw.site.namespaces[ 0 ].displayName
	else
		return mw.site.namespaces[ namespace ].name
	end
end

local function getSingle( username, namespaces, sortable, showname, requireNS )
	if not username then
		return i18n.errormsg:format( i18n.error_nouser )
	end
	if not namespaces and requireNS then
		return i18n.errormsg:format( i18n.error_nons )
	end

	if not namespaces then
		namespaces = { 'main', 'talk', 'user', 'user talk', 'file', 'module', 'template', 'category', 'project', 'mediawiki', 'mcl', 'mcd', 'mce', 'mcsm', 'forum', 'tutorial', 'movie' }
	end

	local result = mw.html.create( 'table' ):addClass( 'wikitable' ):attr( 'data-description', i18n.datadesc )
	if #namespaces > 1 and sortable then
		result:addClass( 'sortable' )
	end
	if showname then
		result:tag( 'div' ):css{ [ 'line-height' ] = 1, [ 'font-weight' ] = 'bold' }:wikitext( i18n.usercontrib:format( username, username ) ):done()
	end

	local tableHeader = mw.html.create( 'tr' )
	tableHeader:tag( 'th' ):wikitext( i18n.rownsname ):done()
	tableHeader:tag( 'th' ):wikitext( i18n.rowcount ):done()
	result:node( tableHeader )

	for k, v in pairs( namespaces ) do
		if type( k ) == 'number' then
			local tableRow = mw.html.create( 'tr' ):css{ [ 'text-align' ] = 'center' }
			tableRow:tag( 'td' ):wikitext( getNSName( v ) ):done()
			tableRow:tag( 'td' ):wikitext( mw.getCurrentFrame():preprocess( i18n.countsrc:format( username, v ) ) ):done()
			result:node( tableRow )
		end
	end

	return tostring( result )
end

local function getMultiple( groups )
	if not groups then
		return i18n.errormsg:format( i18n.error_nogrp )
	end

	local result = mw.html.create( 'table' ):addClass( 'wikitable' )

	local tableHeader = mw.html.create( 'tr' )
	tableHeader:tag( 'th' ):wikitext( i18n.rownsname ):done()
	tableHeader:tag( 'th' ):wikitext( i18n.rowcount ):done()
	result:node( tableHeader )

	for k, group in pairs( groups ) do
		if type( k ) == 'number' then
			local splits = {}
			for v in mw.text.gsplit( mw.text.trim( group ), ',', true ) do
				table.insert( splits, mw.text.trim( v ) )
			end

			local username = splits[ 1 ]
			local color = nil
			-- Check if the username contains a color
			if username:find("<") and username:find(">") then
				color = username:match("<(.-)>")
				username = username:gsub("<.->", "")
			end
			
			if not username then
				return i18n.errormsg:format( i18n.error_nouser )
			end

			local namespaces = fetchElements( splits, 1, false )
			if not namespaces then
				return i18n.errormsg:format( i18n.error_nons )
			end

			local tableRowUser = mw.html.create( 'tr' )
			tableRowUser:tag( 'th' ):attr( 'colspan', 2 ):wikitext( i18n.userlink:format( username, username ) )
			if color then
				tableRowUser:css{ ['background-color'] = color }
			end
			tableRowUser:done()
			result:node( tableRowUser )

			for _, namespace in pairs( namespaces ) do
				local tableRowEdit = mw.html.create( 'tr' ):css{ [ 'text-align' ] = 'center' }
				if color then
					tableRowEdit:css{ ['background-color'] = color }
				end
				tableRowEdit:tag( 'td' ):wikitext( getNSName( namespace ) ):done()
				tableRowEdit:tag( 'td' ):wikitext( mw.getCurrentFrame():preprocess( i18n.countsrc:format( username, namespace ) ) ):done()
				result:node( tableRowEdit )
			end
		end
	end

	return tostring( result )
end

function p.main( f )
	local args = f
	if f == mw.getCurrentFrame() then
		args = require( 'Module:ProcessArgs' ).merge( true )
	end

	if args[ 1 ] then
		if args[ 1 ]:lower() == i18n.type_special then
			return getSingle( args[ 2 ], fetchElements( args, 2, true ), not args.nosort, args.showname, true )
		elseif args[ 1 ]:lower() == i18n.type_multiuser then
			return getMultiple( fetchElements( args, 1, true ) )
		else
			return getSingle( args[ 1 ], nil, not args.nosort, args.showname, false )
		end
	else
		return nil
	end
end

return p