Edge Rewrite
// HTMLRewriter · presentation

This page was redesigned at the edge.

Cloudflare fetched the original article and streamed it through HTMLRewriter to apply an entirely new visual system without rebuilding the source page.

Jump to content

Module:Articles by class

Permanently protected module
From Wikipedia, the free encyclopedia

require('strict')
local p = {}
local frame = mw.getCurrentFrame()
local args = require('Module:Arguments').getArgs(frame)
local title = args.page and mw.title.new(args.page) or mw.title.getCurrentTitle()
local cat_name = '%s-%s %s %s'
local cats = {}
local lang = mw.language.getContentLanguage()

local class_suffix = function(class, unassessed_suffix)
	local suffix = class:lower()=='unassessed' and (unassessed_suffix or '') or '-Class'
	return class .. suffix
end

local col_num = function(n, link)
	local text
	local number = lang:formatNum(n)
	if link then
		text = '[[' .. link .. '|' .. number .. ']]'
	else
		text = number
	end
	return mw.html.create('td')
		:attr('align', 'center')
		:wikitext(text)
end

local add_category = function(cat, _sort)
	local link = '[[Category:' .. cat .. (_sort and ('|' .. _sort) or '') .. ']]'
	table.insert(cats, link)
end

local cat_in_use = function(cat)
	local cat_title = mw.title.new('Category:' .. cat)
	return cat_title and cat_title.exists or mw.site.stats.pagesInCategory(cat, 'pages')>0
end

local template = function(template, class, topic, page)
	return frame:expandTemplate{
		title = template,
		args = {
			[1] = class,
			topic = topic,
			category = topic .. ' ' .. page,
			bold = 'no'
		}
	}
end

local create_table = function(cfg)
	local class, topic, typ = title.text:match(cfg.pattern)
	local pagetype = function(class)
		return cfg.non_article[class:lower()] and 'pages' or 'articles'
	end
	if not class and cfg.pattern2 then -- try alternate pattern
		class, topic, typ = title.text:match(cfg.pattern2)
	end
	if not topic then
		topic = args.topic or title.text:match('^(.+) articles by ' .. cfg.qualimp .. '$')
	end
	local out, in_use = '', {}
	if args.topic and topic and args.topic~=topic then
		add_category('WikiProject assessment categories needing attention')
	end
	topic = topic or args.topic or ''
	typ = typ or 'articles'
	local header_row = mw.html.create('tr')
	for _, c in ipairs(cfg.classes) do
		in_use[c] = cat_in_use(cat_name:format(c, cfg.suffix, topic, pagetype(c)))
		if in_use[c] then
			header_row:node(template(cfg.template_name, c, topic, pagetype(c)))
		end
	end
	local custom = args.custom or args.custom1
	if custom then
		header_row:node(template(cfg.template_name, custom, topic, pagetype(custom)))
	end
	if cfg.custom then
		header_row:node(template(cfg.template_name, cfg.custom.name, topic, pagetype(cfg.custom.name)))
	end
	local total_cell = mw.html.create('td'):attr('align', 'center'):wikitext('Total')
	header_row:node(total_cell)
	local total = 0
	local pages_in_cat = function(cat)
		local pages = mw.site.stats.pagesInCategory(cat, 'pages')
		total = total + pages
		return col_num(pages)
	end
	local second_row = mw.html.create('tr')
	for _, c in ipairs(cfg.classes) do
		if in_use[c] then
			second_row:node(pages_in_cat(cat_name:format(c, cfg.suffix, topic, pagetype(c))))
		end
	end
	if custom then
		second_row:node(pages_in_cat(cat_name:format(custom, cfg.suffix, topic, pagetype(custom))))
	end
	if cfg.custom then
		second_row:node(pages_in_cat(cfg.custom.category:format(topic)))
	end
	second_row:node(col_num(total))
	if title.namespace==14 then -- we are in Category namespace
		if total==0 then -- total number of articles within topic is zero
			add_category('WikiProject assessment categories needing attention')
		elseif class then
			out = frame:expandTemplate{
				title='Possibly empty category',
				args = {hide = mw.site.stats.pagesInCategory(title.text, 'pages')>0 and 'true'}
			}
		end
	end
	local caption
	if args.project then -- display caption
		local abc = 'articles by ' .. cfg.qualimp
		local text = '[[Wikipedia:WikiProject ' .. args.project .. '|WikiProject ' .. args.project .. ']] '
			.. (
				mw.title.new('Category:' .. topic .. ' ' .. abc).exists
				and '[[:Category:' .. topic .. ' ' .. abc .. '|' .. abc .. ']]'
				or abc
			) .. string.rep('  ', 3)
			.. '<small>' .. frame:expandTemplate{title = 'Purge', args = {'Refresh'}} .. '</small>'
		caption = mw.html.create('caption')
			:attr('align', 'bottom')
			:wikitext(text)
	end
	local tab = mw.html.create('table')
		:addClass('wikitable')
		:addClass('toccolours'):addClass('nomobile')
		:css('table-layout', 'fixed')
		:css('margin', '1em auto')
		:node(header_row)
		:node(second_row)
		:node(caption)
	if class and (args.sort or topic~='') then
		add_category(args.parent or (topic .. ' articles by ' .. cfg.qualimp), class)
		local suffix = class:lower()=='unassessed' and '' or ('-' .. cfg.suffix)
		add_category(class .. suffix .. ' ' .. typ, args.sort or topic)
	elseif title.text:match('^' .. topic .. ' articles by ' .. cfg.qualimp .. '$') then
		add_category('Wikipedia 1.0 assessments')
	end
	return out .. tostring(tab) .. table.concat(cats)
end

p.quality_and_importance = function()
	local cfg = {
		quality_classes = {'FA', 'A', 'GA', 'B', 'C', 'Start', 'Stub', 'FL', 'List', 'Draft', 'Redirect', 'Unassessed'},
		importance_classes = {'Top', 'High', 'Mid', 'Low', 'Unknown'},
		forms = {'C T of I', 'I C T', 'C I T', 'C, I T'}
	}
	local projects = mw.loadJsonData('Template:Articles by Quality and Importance/config')
	local pagetype = function(class)
		return (class=='Redirect' or class=='Draft') and 'pages' or 'articles'
	end
	local totals = {}
	local grand_total = 0
	local unassessed_suffix = ''
	local form = 'C T of I'
	local class, topic, importance
	if args.topic then
		topic = args.topic
	else
		for _, form in pairs(cfg.forms) do
			local offsets, order = {}, {}
			for _, s in ipairs{'C', 'I', 'T'} do
				table.insert(offsets, {letter = s, offset = form:find(s)})
			end
			table.sort(offsets, function(m, n) return m.offset<n.offset end)
			for n, v in ipairs(offsets) do
				order[v.letter] = n
			end
			local form2 = form
				:gsub('C', '_C_'):gsub('I', '_I_'):gsub('T', '_T_')
				:gsub('_C_', '(%%a+)-Class')
				:gsub('_I_', '(%%a+)-importance')
				:gsub('_T_', '(.+) %%a+')
			local pattern = '^' .. form2 .. '$'
			local m1, m2, m3 = title.text:match(pattern)
			if m1 then -- match found
				local m = {m1, m2, m3}
				class = m[order.C]
				importance = m[order.I]
				topic = m[order.T]
				break
			end
		end
		if not topic then -- no topic, cannot continue
			if title.namespace==14 then
				return '[[Category:WikiProject assessment categories needing attention]]'
			else
				return nil
			end
		end
	end
	if projects[topic] then -- configuration settings are provided
		if projects[topic].bottom then
			table.insert(cfg.importance_classes, 5, 'Bottom')
		end
		unassessed_suffix = projects[topic].unassessed_suffix or ''
		if projects[topic].redirect==false then
			table.remove(cfg.quality_classes, 11)
		end
		if projects[topic].draft==false then
			table.remove(cfg.quality_classes, 10)
		end
		if projects[topic].pattern then
			form = projects[topic].pattern
		end
	end
	form = form:gsub('C', '_C_'):gsub('I', '_I_'):gsub('T', '_T_')
	if class and class~='' and importance and importance ~='' then
		add_category(topic .. ' articles by quality and importance', class..importance)
		add_category(class_suffix(class, unassessed_suffix) .. ' ' .. topic .. ' ' .. pagetype(class), '*' .. importance)
		add_category(
			importance .. '-importance' .. ' ' .. topic .. ' ' .. (importance=='NA' and 'pages' or 'articles'),
			'*' .. class
		)
	end
	local corner_cell = mw.html.create('th')
		:attr('colspan', '2')
		:attr('rowspan', '2')
		:wikitext(lang:ucfirst(topic) .. '<br>articles')
	local importance_cell = mw.html.create('th')
		:attr('colspan' , #cfg.importance_classes+1)
		:wikitext('[[:Category:' .. topic .. ' articles by importance|Importance]]')
	local top_row = mw.html.create('tr')
		:node(corner_cell)
		:node(importance_cell)
	local importance_row = mw.html.create('tr')
	for _, importance in ipairs(cfg.importance_classes) do
		importance_row:node(template('Importance', importance, topic, 'articles'))
	end
	local importance_cell = mw.html.create('th'):wikitext('Total')
	importance_row:node(importance_cell)
	local quality_cells = function(row, class)
		local total = 0
		local typ = pagetype(class)
		row:node(template('Class', class, topic, typ))
		for _, importance in ipairs(cfg.importance_classes) do
			if typ=='pages' and importance=='Unknown' then
				importance = 'NA' -- use NA-importance on non-articles
			end
			local cat_name = form
				:gsub('_C_', class_suffix(class, unassessed_suffix))
				:gsub('_I_', importance .. '-importance')
				:gsub('_T_', topic .. ' ' .. typ)
			local pages = mw.site.stats.pagesInCategory(cat_name, 'pages')
			total = total + pages
			if totals[importance] then
				totals[importance] = totals[importance] + pages
			else
				totals[importance] = pages
			end
			row:node(col_num(pages, ':Category:' .. cat_name))
		end
		row:node(col_num(total, ':Category:' .. class_suffix(class) .. ' ' .. topic .. ' ' .. typ))
		grand_total = grand_total + total
	end
	local tab = mw.html.create('table')
		:addClass('wikitable')
		:addClass('toccolours'):addClass('nomobile')
		:css('table-layout', 'fixed')
		:css('margin', '1em auto')
		:node(top_row)
		:node(importance_row)
	local quality_column = mw.html.create('th')
		:attr('rowspan', #cfg.quality_classes+1)
		:wikitext('[[:Category:' .. topic .. ' articles by quality|Quality]]')
	for n, _class in ipairs(cfg.quality_classes) do
		local row = mw.html.create('tr')
		if n==1 then
			row:node(quality_column)
		end
		quality_cells(row, cfg.quality_classes[n])
		tab:node(row)
	end
	local total_row = mw.html.create('tr')
		:node(importance_cell)
	for _, importance in ipairs(cfg.importance_classes) do
		local cat_name = importance .. '-importance ' .. topic .. ' ' .. 'articles'
		total_row:node(col_num(totals[importance] or 0, ':Category:' .. cat_name))
	end
	total_row:node(col_num(grand_total))
	tab:node(total_row)
	return tostring(tab) .. table.concat(cats)
end

p.quality = function()
	return create_table{
		pattern = '^(%a+)-Class (.+) (%a+)$',
		pattern2 = '^(Unassessed) (.+) (%a+)$', -- match unassessed category
		qualimp = 'quality',
		classes = {'FA', 'A', 'GA', 'B', 'C', 'Start', 'Stub', 'FL', 'AL', 'BL', 'CL', 'List', 'SIA', 'Future', 'Category', 'Disambig', 'Draft', 'FM', 'File', 'Portal', 'Project', 'Redirect', 'Template', 'User', 'NA'},
		non_article = {category = true, disambig = true, draft = true, fm = true, file = true, portal = true, project = true, redirect = true, template = true, user = true, na = true},
		template_name = 'Class',
		suffix = 'Class',
		custom = {name = 'Unassessed', category = 'Unassessed %s articles'}
	}
end

p.importance = function()
	return create_table{
		pattern = '^(%a+)-importance (.+) (%a+)$',
		qualimp = 'importance',
		classes = {'Top', 'High', 'Mid', 'Low', 'Bottom', 'NA', 'Unknown'},
		non_article = {na = true},
		template_name = 'Importance',
		suffix = 'importance'
	}
end

return p