Bu modul uchun Modul:WikiProject/doc nomli hujjat sahifasini yaratishingiz mumkin

require( 'strict' )
local p = {}

local yesno = require( 'Modul:Yesno' )
local getArgs = require( 'Modul:Arguments' ).getArgs

local module_styles_page = 'Modul:WikiProject/styles.css'

local templatestyles_page = 'Andoza:WPBannerMeta/styles.css'
local templatestyles_class = 'ts-WPBannerMeta-ratings '

local hiddencat = '__HIDDENCAT__'

local class_info = {
	['tm'] = {
		category = '%s loyihasi tanlangan maqolalari',
		class = 'level-fa',
		image = '[[Fayl:Cscr-featured.svg|14px|baseline|link=|Tanlangan maqola]]',
		shortname = 'TM',
		sortKey = ' 0'
	},
	['tr'] = {
		category = '%s loyihasi tanlangan roʻyxatlari',
		class = 'level-fl',
		image = '[[Fayl:Symbol list class.svg|14px|baseline|link=|Tanlangan roʻyxat]]',
		shortname = 'TR',
		sortKey = ' 1'
	},
	['ym'] = {
		category = '%s loyihasi yaxshi maqolalari',
		class = 'level-ga',
		image = '[[Fayl:Symbol support vote.svg|14px|baseline|link=|Yaxshi maqola]]',
		shortname = 'YM',
		sortKey = ' 2'
	},
	['xm'] = {
		category = '%s loyihasi xushsifat maqolalari',
		class = 'level-aa',
		image = '[[Fayl:Crystal Clear action bookmark Silver approved.svg|baseline|14px|link=|Xushsifat maqola]]',
		shortname = 'XM',
		sortKey = ' 3'
	},
	['i'] = {
		category = '%s loyihasining I darajali maqolalari',
		class = 'level-1',
		shortname = 'I',
		sortKey = ' 4'
	},
	['ii'] = {
		category = '%s loyihasining II darajali maqolalari',
		class = 'level-2',
		shortname = 'II',
		sortKey = ' 5'
	},
	['iii'] = {
		category = '%s loyihasining III darajali maqolalari',
		class = 'level-3',
		shortname = 'III',
		sortKey = ' 6'
	},
	['iv'] = {
		category = '%s loyihasining IV darajali maqolalari',
		class = 'level-4',
		shortname = 'IV',
		sortKey = ' 7'
	},
	['roʻyxat'] = {
		category = '%s loyihasi roʻyxatlari',
		class = 'level-list',
		shortname = 'Roʻyxat',
		sortKey = ' 8'
	},
	['nomaʼlum'] = {
		category = '%s loyihasining nomaʼlum darajali maqolalari',
		shortname = '???',
		sortKey = ' 9'
	},
}

local importance_info = {
	['eng'] = {
		category = ' eng ahamiyatli maqolalari',
		class = 'importance-highest',
		shortname = 'Eng',
		sortKey = ' 0'
	},
	['yuqori'] = {
		category = ' yuqori ahamiyatli maqolalari',
		class = 'importance-high',
		shortname = 'Yuqori',
		sortKey = ' 1'
	},
	['oʻrtacha'] = {
		category = ' oʻrtacha ahamiyatli maqolalari',
		class = 'importance-medium',
		shortname = 'Oʻrtacha',
		sortKey = ' 2'
	},
	['kam'] = {
		category = ' kam ahamiyatli maqolalari',
		class = 'importance-low',
		shortname = 'Kam',
		sortKey = ' 3'
	},
	['nomaʼlum'] = {
		category = ' nomaʼlum ahamiyatli maqolalari',
		shortname = 'Nomaʼlum',
		sortKey = ' 9'
	},
}

local function isEmpty( val )
	return val == nil or val == ''
end

local function startsWith( str, prefix )
	return mw.ustring.sub( str, 1, mw.ustring.len( prefix ) ) == prefix
end

local function cutPrefix( str, length )
	return mw.ustring.sub( str, length + 1 )
end

local function endsWith( str, suffix )
	return mw.ustring.sub( str, -mw.ustring.len( suffix ) ) == suffix
end

local function cutSuffix( str, length )
	return mw.ustring.sub( str, 1, -length - 1 )
end

local function getInfo( data, key )
	if isEmpty( key ) then
		return nil
	end
	
	key = key and mw.ustring.lower( key )
	return data[ key ]
end

local function getClassInfo( class )
	return getInfo( class_info, class )
end

local function getImportanceInfo( importance )
	return getInfo( importance_info, importance )
end

local function form_cat_name( project, class, importance )
	local result = ''

	local classInfo = getClassInfo( class )
	if classInfo ~= nil then
		result = string.format( classInfo.category, project )
	else
		result = project .. ' loyihasining'
	end

	local importanceInfo = getImportanceInfo( importance )
	if importanceInfo ~= nil then
		result = result .. importanceInfo.category
	end

	return result
end

local function parse_cat_name( category )
	local result = {
		project = '',
		class = '',
		importance = '',
		is_error = false
	}

	if endsWith( category, ' по уровню' ) then
		if not startsWith( category, 'Статьи проекта ' ) then
			result.is_error = true
			return result
		end
		category = cutPrefix( category, 15 )
		category = cutSuffix( category, 10 )
		result.project = category
		result.class = '*'
		return result
	end

	if endsWith( category, ' по важности' ) then
		if not startsWith( category, 'Статьи проекта ' ) then
			result.is_error = true
			return result
		end
		category = cutPrefix( category, 15 )
		category = cutSuffix( category, 12 )
		result.project = category
		result.importance = '*'
		return result
	end

	if endsWith( category, ' высшей важности' ) then
		category = cutSuffix( category, 16 )
		result.importance = 'высшая'
	elseif endsWith( category, ' высокой важности' ) then
		category = cutSuffix( category, 17)
		result.importance = 'высокая'
	elseif endsWith( category, ' средней важности' ) then
		category = cutSuffix( category, 17 )
		result.importance = 'средняя'
	elseif endsWith( category, ' низкой важности' ) then
		category = cutSuffix( category, 16 )
		result.importance = 'низкая'
	elseif endsWith( category, ' неизвестной важности' ) then
		category = cutSuffix( category, 21 )
		result.importance = 'nomaʼlum'
	end

	if startsWith( category, 'Избранные статьи проекта ' ) then
		category = cutPrefix( category, 25 )
		result.class = 'ИС'
	elseif startsWith( category, 'Избранные списки проекта ' ) then
		category = cutPrefix( category, 25 )
		result.class = 'ИСП'
	elseif startsWith( category, 'Хорошие статьи проекта ' ) then
		category = cutPrefix( category, 23 )
		result.class = 'ХС'
	elseif startsWith( category, 'Добротные статьи проекта ' ) then
		category = cutPrefix( category, 25 )
		result.class = 'ДС'
	elseif startsWith( category, 'Списки проекта ' ) then
		category = cutPrefix( category, 15 )
		result.class = 'Список'
	elseif startsWith( category, 'Статьи проекта ' ) then
		category = cutPrefix( category, 15 )
	else
		result.is_error = true
	end

	if endsWith( category, ' I уровня' ) then
		if result.class ~= '' then
			result.is_error = true
		end
		category = cutSuffix( category, 9 )
		result.class = 'I'
	elseif endsWith( category, ' II уровня' ) then
		if result.class ~= '' then
			result.is_error = true
		end
		category = cutSuffix( category, 10 )
		result.class = 'II'
	elseif endsWith( category, ' III уровня' ) then
		if result.class ~= '' then
			result.is_error = true
		end
		category = cutSuffix( category, 11 )
		result.class = 'III'
	elseif endsWith( category, ' IV уровня' ) then
		if result.class ~= '' then
			result.is_error = true
		end
		category = cutSuffix( category, 10 )
		result.class = 'IV'
	elseif endsWith( category, ' неизвестного уровня' ) then
		if result.class ~= '' then
			result.is_error = true
		end
		category = cutSuffix( category, 20 )
		result.class = 'nomaʼlum'
	end

	result.project = category
	return result
end

local function get_cat_link( name, after, isLink )
	if isEmpty( name ) then
		return ''
	end
	return string.format(
		'[[%sTurkum:%s%s]]',
		isLink == true and ':' or '',
		name,
		not isEmpty( after ) and '|' .. after or ''
	)
end

local function add_table_header( html, info, catName, scope )
	local headerText = get_cat_link( catName, info.shortname, true )
	if info.image then
		headerText = info.image .. ' ' .. headerText
	end
	return html:tag( 'th' )
		:attr( 'scope', scope or 'row' )
		:addClass( templatestyles_class .. (info.class or '') )
		:wikitext( headerText )
end

function p._get_page_categories( name, class, importance )
	if isEmpty( name ) then
		return
	end
	
	local romanNumerals = {
		'i',
		'ii',
		'iii',
		'iv',
	}
	if tonumber( class ) ~= nil then
		class = romanNumerals[ tonumber( class ) ]
	end
	
	class = not isEmpty( class ) and mw.ustring.lower( class )
	importance = not isEmpty( importance ) and mw.ustring.lower( importance )
	
	local classOrUnknown = getClassInfo( class ) ~= nil and class or 'nomaʼlum'
	local importanceOrUnknown = getImportanceInfo( importance ) ~= nil and importance or 'nomaʼlum'
	
	-- X loyihasi maqolalari
	return get_cat_link( form_cat_name( name, nil, nil ) )
		-- X loyihasining Y ahamiyatli maqolalari
		.. get_cat_link( form_cat_name( name, nil, importanceOrUnknown ) )
		--  X loyihasining Y darajali maqolalari
		.. get_cat_link( form_cat_name( name, classOrUnknown, nil ) )
		-- X loyihasining A ahamiyatli, Y darajali maqolalari
		.. get_cat_link( form_cat_name( name, classOrUnknown, importanceOrUnknown ) )
end

function p.page_categories( frame )
	local args = getArgs( frame )
	local name = args[ '1' ] or args[ 'name' ]
	local class = args[ 'class' ]
	local importance = args[ 'importance' ]
	
	return p._get_page_categories( name, class, importance )
end

function p._substing( frame )
	local args = getArgs( frame, {
		parentOnly = true,
	} )
	local mTemplateInvocation = require( 'Modul:Template invocation' )
	local name = mTemplateInvocation.name( frame:getParent():getTitle() )
	
	return mTemplateInvocation.invocation( name, args )
end

function p._get_project_statistics( name, args )
	local frame = mw.getCurrentFrame()
	if isEmpty( name ) then
		local title = mw.title.getCurrentTitle()
		local project
		if title.namespace == 104 then
			project = title.rootText
		else
			project = 'Loyiha'
		end
		return '<code>{{Loyiha statistikasi|' .. project ..
		       '|featured=1|list=1|nocat=&lt;includeonly&gt;1&lt;/includeonly&gt;|minus=1}}</code>'
	end
	local minus = tonumber( args['minus'] ) or 0
	local align = args['align'] or 'right'
	local featured = yesno( args['featured'] )
	local list = yesno( args['list'] )
	local nocat = yesno( args['nocat'] )

	local displayed_importances = { 'eng', 'yuqori', 'oʻrtacha', 'kam', 'nomaʼlum' }
	local displayed_classes
	if featured and list then
		displayed_classes = { 'TM', 'TR', 'YM', 'XM', 'I', 'II', 'III', 'IV', 'roʻyxat', 'nomaʼlum' }
	elseif featured then
		displayed_classes = { 'TM', 'YM', 'XM', 'I', 'II', 'III', 'IV', 'nomaʼlum' }
	elseif list then
		displayed_classes = { 'I', 'II', 'III', 'IV', 'roʻyxat', 'nomaʼlum' }
	else
		displayed_classes = { 'I', 'II', 'III', 'IV', 'nomaʼlum' }
	end

	local all_pages = 0
	local importance_pages = {}

	local wrapper = mw.html.create( 'div' )
		:addClass( 'ts-module-WikiProject-wrapper' )
	
	local result = wrapper:tag( 'table' )
		:addClass( 'ts-module-WikiProject-table wikitable' )
	
	if align == 'left' or align == 'center' or align == 'right' then
		wrapper:addClass( 'is-' .. align )
	end
	
	result:tag( 'caption' )
		:wikitext( '[[Loyiha:' .. name .. '|„' .. name .. '“]] loyihasi maqolalari' )
		:done()
	
	result:tag( 'tr' )
		:tag( 'th' )
			:attr( 'scope', 'col' )
			:attr( 'rowspan', 2 )
			:wikitext( get_cat_link( 'Darajasi boʻyicha ' .. name .. ' loyihasi maqolalari', 'Sifati', true ) )
		:tag( 'th' )
			:attr( 'scope', 'colgroup' )
			:attr( 'colspan', 6 )
			:wikitext( get_cat_link( 'Ahamiyati boʻyicha ' .. name .. ' loyihasi maqolalari', 'Ahamiyati', true ) )
		:done()
	
	result:tag( 'tr' )
	for _, importance in ipairs(displayed_importances) do
		local info = getImportanceInfo( importance )
		importance_pages[ importance ] = 0
		add_table_header( result, info, form_cat_name( name, '', importance ), 'col' )
	end
	result:tag( 'th' )
		:attr( 'scope', 'col' )
		:wikitext( get_cat_link( name .. ' loyihasi maqolalari', 'Jami', true ) )
		:done()

	for _, class in ipairs(displayed_classes) do
		local info = getClassInfo( class )

		local class_pages = 0

		local tr = result:tag( 'tr' )
		local class_catname = form_cat_name( name, class, '' )
		add_table_header( tr, info, class_catname )

		for _, importance in ipairs(displayed_importances) do
			local td = tr:tag( 'td' )

			local catname = form_cat_name( name, class, importance )
			local pages = mw.site.stats.pagesInCategory( catname, 'pages' ) - minus
			if pages > 0 then
				all_pages = all_pages + pages
				class_pages = class_pages + pages
				importance_pages[importance] = importance_pages[importance] + pages

				td:wikitext( get_cat_link( catname, pages, true ) )
			end
		end

		tr:tag( 'td' )
			:addClass( 'ts-module-WikiProject-table-total' )
			:wikitext( get_cat_link( class_catname, class_pages, true ) )
	end

	local totalTr = result:tag( 'tr' )
		:addClass( 'ts-module-WikiProject-table-total' )
	
	totalTr:tag( 'th' )
		:attr( 'scope', 'row' )
		:wikitext( get_cat_link( name .. ' loyihasi maqolalari', 'Jami', true ) )
	for _, importance in ipairs(displayed_importances) do
		totalTr:tag( 'td' )
			:wikitext( get_cat_link( form_cat_name( name, '', importance ), importance_pages[importance], true ) )
	end
	totalTr:tag( 'td' )
		:wikitext( get_cat_link( name .. ' loyihasi maqolalari', all_pages, true ) )

	local footer = '' ..
		'[' .. frame:expandTemplate{ title = 'yangila', args = { ['1'] = 'yangilash' } } .. ']'
	wrapper:tag( 'div' )
		:wikitext( footer )

	local cats = ''
	local sortKey = '*'
	if not nocat then
		cats = cats .. get_cat_link( 'Vikipediya:Loyihalar boʻyicha statistika', name )
		for _, class in ipairs( displayed_classes ) do
			cats = cats .. get_cat_link( form_cat_name( name, class, '' ), sortKey )
		end
		for _, importance in ipairs(displayed_importances) do
			cats = cats .. get_cat_link( form_cat_name( name, '', importance ), sortKey )
		end
		for _, class in ipairs( displayed_classes ) do
			for _, importance in ipairs(displayed_importances) do
				cats = cats .. get_cat_link( form_cat_name( name, class, importance ), sortKey )
			end
		end
	end

	return frame:extensionTag{
		name = 'templatestyles',
		args = { src = module_styles_page }
	} .. frame:extensionTag{
		name = 'templatestyles',
		args = { src = templatestyles_page }
	} .. tostring( wrapper ) .. cats
end

function p.project_statistics( frame )
	local args = getArgs( frame )
	local name = args[ '1' ] or args[ 'name' ]
	
	if mw.isSubsting() then
		return p._substing( frame )
	end
	
	return p._get_project_statistics( name, args )
end

function p.category_description( frame )
	local args = getArgs( frame )
	local title = mw.title.getCurrentTitle()
	if title.namespace ~= 14 then
		return ''
	end
	
	if mw.isSubsting() then
		return p._substing( frame )
	end

	local parsed_title = parse_cat_name( title.text )
	if parsed_title.is_error then
		return '<strong class="error">Xatolik: не удалось распарсить заголовок.</strong>'
	end
	
	local project = parsed_title.project
	local class = parsed_title.class
	local importance = parsed_title.importance
	local name = args.name
	local result = ''

	if class == '' and importance == '' then
		-- X loyihasi maqolalari
		result = result .. frame:expandTemplate{ title = 'Turkum mundarijasi', args = { ['depth'] = '2' } }
		result = result .. '\n' .. get_cat_link( 'Loyiha:' .. project )
	elseif class == '*' then
		-- Darajasi boʻyicha X loyihasi maqolalari
		result = result .. frame:expandTemplate{ title = 'jamlovchi turkum' }
		result = result .. '\n' .. get_cat_link( 'Vikipediya:Darajasi boʻyicha loyihalar maqolalari', project )
		result = result .. '\n' .. get_cat_link( project .. ' loyihasi maqolalari', '*' )
	elseif importance == '*' then
		-- Ahamiyati boʻyicha X loyihasi maqolalari
		result = result .. frame:expandTemplate{ title = 'jamlovchi turkum' }
		result = result .. '\n' .. get_cat_link( 'Vikipediya:Ahamiyati boʻyicha maqolalar', project )
		result = result .. '\n' .. get_cat_link( project .. ' loyihasi maqolalari', '*' )
	elseif importance == '' then
		-- X loyihasining N darajali maqolalari
		result = result .. hiddencat
		if class == 'Roʻyxat' then
			result = result .. '\n' .. get_cat_link( 'Loyihalar boʻyicha roʻyxatlar', project )
		elseif class == 'TR' then
			result = result .. '\n' .. get_cat_link( 'Loyihalar boʻyicha tanlangan roʻyxatlar', project )
		elseif class == 'TM' then
			result = result .. '\n' .. get_cat_link( 'Loyihalar boʻyicha tanlangan maqolalar', project )
		elseif class == 'YM' then
			result = result .. '\n' .. get_cat_link( 'Loyihalar boʻyicha yaxshi maqolalar', project )
		elseif class == 'XM' then
			result = result .. '\n' .. get_cat_link( 'Loyihalar boʻyicha xushsifat maqolalar', project )
		elseif class == 'nomaʼlum' then
			result = result .. '\n' .. get_cat_link( 'Nomaʼlum darajali maqolalar', project )
		else
			result = result .. '\n' .. get_cat_link( class .. ' darajali maqolalar', project )
		end
		result = result .. '\n' .. get_cat_link( 'Darajasi boʻyicha ' .. project .. ' loyihasi maqolalari', getClassInfo( class ).sortKey )
	elseif class == '' then
		-- X loyihasining Y ahamiyatli maqolalari
		result = result .. hiddencat
		result = result .. '\n' .. get_cat_link( 'Maqolalar' .. getImportanceInfo( importance ).category, project )
		result = result .. '\n' .. get_cat_link( 'Ahamiyati boʻyicha ' .. project .. ' loyihasi maqolalari', getImportanceInfo( importance ).sortKey )
	else
		-- X loyihasining Y ahamiyatli, Z darajali maqolalari
		result = result .. '\n' .. get_cat_link( form_cat_name( project, class, '' ), getImportanceInfo( importance ).sortKey )
		result = result .. '\n' .. get_cat_link( form_cat_name( project, '', importance ), getClassInfo( class ).sortKey )
	end
	
	if not yesno( args['notable'] ) then
		name = project
		if args['align'] == nil then
			args['align'] = 'right'
		end
		if args['minus'] == nil then
			args['minus'] = '1'
		end
		if args['featured'] == nil then
			args['featured'] = '1'
		end
		if args['list'] == nil then
			args['list'] = '1'
		end
		args['nocat'] = '1'
		result = result .. p._get_project_statistics( name, args )
	end

	return result
end

return p