Module:Articles by class

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 = '' .. number .. ''

else

text = number

end

return mw.html.create('td')

:attr('align', 'center')

:wikitext(text)

end

local add_category = function(cat, _sort)

local link = '' .. _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)

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, exist = '', {}

if args.class and class and args.topic and topic and (args.class:lower()~=class:lower() or args.topic~=topic) then

add_category('WikiProject assessment categories needing attention')

end

topic = topic or args.topic or ''

class = class or args.class or ''

typ = typ or 'articles'

if title.namespace==14 and not title.text:match('^' .. topic .. ' articles by ' .. cfg.qualimp .. '$') then

out = frame:expandTemplate{title='Possibly empty category'}

end

for _, class in ipairs(cfg.classes) do

if cat_in_use(cat_name:format(class, cfg.suffix, topic, 'pages')) then

exist[class] = 'pages'

elseif cat_in_use(cat_name:format(class, cfg.suffix, topic, 'articles')) then

exist[class] = 'articles'

else

exist[class] = false

end

end

local header_row = mw.html.create('tr')

for _, class in ipairs(cfg.classes) do

if exist[class] then

header_row:node(template(cfg.template_name, class, topic, exist[class]))

end

end

if args.custom1 then

header_row:node(template(cfg.template_name, args.custom1, topic, 'articles'))

end

if args.custom2 then

header_row:node(template(cfg.template_name, args.custom2, topic, 'articles'))

end

if cfg.custom then

header_row:node(template(cfg.template_name, cfg.custom.name, topic, 'articles'))

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 _, class in ipairs(cfg.classes) do

if exist[class] then

second_row:node(pages_in_cat(cat_name:format(class, cfg.suffix, topic, exist[class])))

end

end

if args.custom1 then

second_row:node(pages_in_cat(cat_name:format(args.custom1, cfg.suffix, topic, 'articles')))

end

if args.custom2 then

second_row:node(pages_in_cat(cat_name:format(args.custom2, cfg.suffix, topic, 'articles')))

end

if cfg.custom then

second_row:node(pages_in_cat(cfg.custom.category:format(topic)))

end

second_row:node(col_num(total))

local caption

if args.project then -- display caption

local abc = 'articles by ' .. cfg.qualimp

local text = 'WikiProject ' .. args.project .. ' '

.. (

mw.title.new('Category:' .. topic .. ' ' .. abc).exists

and '' .. abc .. ''

or abc

) .. string.rep('  ', 3)

.. '' .. frame:expandTemplate{title = 'Purge', args = {'Refresh'}} .. ''

caption = mw.html.create('caption')

:attr('align', 'bottom')

:wikitext(text)

end

local tab = mw.html.create('table')

:addClass(args.format or 'wikitable') -- add custom CSS class if specified

:addClass('toccolours'):addClass('nomobile')

:css('table-layout', 'fixed')

:css('margin', '1em auto')

:node(header_row)

:node(second_row)

:node(caption)

if class and class~='' and class~='nocat' 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)

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

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 .. ' ' .. 'articles', '*' .. class)

end

local corner_cell = mw.html.create('th')

:attr('colspan', '2')

:attr('rowspan', '2')

:wikitext(lang:ucfirst(topic) .. '
articles')

local importance_cell = mw.html.create('th')

:attr('colspan' , #cfg.importance_classes+1)

:wikitext('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(args.format or '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('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'},

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'},

template_name = 'Importance',

suffix = 'importance'

}

end

return p