require('strict')
local p = {}
local sandbox = '/sandbox'
local cfg = mw.loadData('Module:WikiProject banner/config' .. (sandbox or ''))
local args_module = require('Module:Arguments')
local mbox = require('Module:Message box').main
local yesno = require('Module:Yesno')
local frame = mw.getCurrentFrame()
local lang = mw.getLanguage(cfg.language)
local current_title = mw.title.getCurrentTitle()
local parameter_format = function(parameter, value)
return frame:expandTemplate{title='para', args={parameter, value or ''}}
end
local wikilink = function(link, display)
if link then
return display and '[['..link..'|'..display..']]' or '[['..link..']]'
else
return display or ''
end
end
local image = function(image_name, size, alt, position)
return image_name and '[[File:'
.. image_name
.. (size and '|' .. size or '')
.. (position and '|' .. position or '')
.. (alt and '|alt=' .. alt or '')
.. ']]'
end
local if_exists = function(target, fallback) -- function to add wikilink if target exists
local title = mw.title.new(target)
if title and title.exists then
return wikilink(target)
else
return fallback or target
end
end
local isarticle = function(class)
local article = true
for _,v in ipairs(cfg.quality.non_article_classes) do
if class==v then -- class matches one of the non-article classes
article = false
break
end
end
return article
end
---------------------------
-- Importance mask --------
---------------------------
local importance_mask = function(raw_importance, class, scale, banner_name)
local importance
if scale=='inline' then -- pass importance without change
importance = raw_importance
elseif scale=='subpage' then
local custom_mask = banner_name:subPageTitle('importance')
if custom_mask.exists and #custom_mask:getContent()>1 then -- pass to custom importance mask
importance = mw.text.trim(frame:expandTemplate{
title = custom_mask.prefixedText,
args = {importance=raw_importance or '¬', class=class}
})
end
else
importance = frame:expandTemplate{
title = 'Template:Importance mask',
args = {raw_importance or '¬', class=class}}
end
if importance=='¬' then
importance = nil
end
return importance
end
---------------------------
-- Quality class mask -----
---------------------------
p.readarticleclass = function(options, page) -- used by _main and also Module:Banner shell
page = page or current_title.prefixedText
local get_parameter_value = require('Module:Template parameter value').getValue
local success, result = get_parameter_value(page, cfg.WPBS_redirects, 'class', options)
return success and result
-- returns FALSE if banner shell template does not exist on page
-- returns BLANK if class parameter is not defined or is defined blank
-- otherwise returns class parameter
end
p.class_mask = function(class, title, FQS, pagetype)
local resolveFQSgrade = function(class)
return FQS and lang:ucfirst(class) or 'NA'
end
local out
title = title or mw.title.getCurrentTitle()
local ns = title.namespace
class = class:match('^%s*(.-)%s*$'):lower()
if pagetype=='redirect' or pagetype=='soft redirect' then
out = resolveFQSgrade('redirect')
elseif pagetype=='disambiguation page' or class=='dab' or class=='disambig' or class=='disambiguation' or class=='disamb' then
out = resolveFQSgrade('disambig')
elseif pagetype=='article' then
if class=='start' or class=='stub' then -- Ucfirst
out = lang:ucfirst(class)
elseif class=='b' or class=='c' or class=='fa' or class=='fl' or class=='a' or class=='ga' then -- Upper-case
out = class:upper()
elseif class=='list' or class=='sia' or class=='si' or class=='sl' then-- List
out = 'List'
else
out = '' -- unassessed
end
elseif ns==7 or ns==711 then -- File talk
if class=='fm' and FQS then
out = 'FM'
else
out = resolveFQSgrade('file')
end
elseif ns==15 then -- Category talk
out = resolveFQSgrade('category')
elseif ns==101 then -- Portal talk
out = resolveFQSgrade('portal')
elseif ns==11 or ns==829 then -- Template talk
out = resolveFQSgrade('template')
elseif ns==5 then -- Wikipedia talk
out = resolveFQSgrade('project')
elseif ns==119 then -- Draft talk
out = resolveFQSgrade('draft')
else
out = 'NA'
end
return out
end
local page_assessment = function(project, class, importance) -- add PageAssessments parser function
local assessment = table.concat({project, class or '', importance or ''},'|')
frame:preprocess('{{#assessment:' .. assessment .. '}}')
end
local bubble = function(text, colour, conflict)
local out = mw.html.create('span')
:addClass('wpb-header-bubbles')
:css('background', colour)
:css('border', conflict and cfg.quality.conflict.border or (cfg.quality.border..' '..colour))
:wikitext(text)
return tostring(out)
end
p._main = function(args, raw_args, demo, banner_name, inactive)
---------------------------
-- Initialise parameters --
---------------------------
local project = args.PROJECT or 'PROJECT'
local project_name = args.PROJECT_NAME or 'WikiProject ' .. project
local project_link = mw.title.new(args.PROJECT_LINK or 'Wikipedia:' .. project_name)
local pagetype = demo and not args.demo_page and 'article' or require('Module:Pagetype' .. (sandbox or ''))._main({
page = args.demo_page,
dab = 'disambiguation page'
})
local rows, nested_ratings, task_forces, notes, categories, taskforce_categories = {}, {}, {}, {}, {}, {}
local add_category = function(category, key)
if category and category~='none' then
table.insert(categories, {category = category, key = key})
end
end
local parse_text = function(text)
return text and text:gsub('_PAGETYPE_', pagetype)
end
for arg_name, arg_value in pairs(args) do
local tf_match = mw.ustring.match(arg_name,'^tf (%d+)$')
local note_match = mw.ustring.match(arg_name,'^note (%d+)$')
if tf_match and yesno(arg_value, true) then
table.insert(task_forces, tf_match)
elseif note_match and yesno(arg_value, true) then
table.insert(notes, note_match)
else
local tf, cat = mw.ustring.match(arg_name,'^tf (%d+) cat (%d+)$')
if tf and yesno(arg_value, true) then
if not taskforce_categories[tf] then -- initialise table
taskforce_categories[tf] = {}
end
table.insert(taskforce_categories[tf], cat)
end
end
end
table.sort(task_forces, function (x, y) return tonumber(x) < tonumber(y) end)
table.sort(notes, function (x, y) return tonumber(x) < tonumber(y) end)
local warning = ''
---------------------------
-- Location warning -------
---------------------------
local show_namespace_warning = not (current_title.isTalkPage or demo)
if show_namespace_warning then
local text = cfg.namespace_warning.text:format(
pagetype,
current_title.talkPageTitle.fullText,
parameter_format('category', 'no')
)
local sortkey = current_title.namespace==10 and cfg.namespace_warning.sortkey_on_template_page or cfg.namespace_warning.sortkey
if current_title.namespace==10 then -- on the Template namespace
text = text .. ' ' .. cfg.namespace_warning.on_template_page:format(
parameter_format('BANNER_NAME'),
current_title.prefixedText
)
end
warning = mbox('ombox', {
image = '[[File:' .. cfg.namespace_warning.image .. '|40px]]',
type = cfg.namespace_warning.type_,
text = text
})
if not current_title.subjectPageTitle:inNamespace(2) then
add_category(cfg.namespace_warning.categories, sortkey)
end
end
---------------------------
-- Substitution warning ---
---------------------------
if args.substcheck=='SUBST' then
local text = cfg.subst_warning.text:format(
project_name,
'<code>{{'..banner_name.prefixedText..'}}</code>'
)
warning = warning .. mbox('ombox', {
image = '[[File:' .. cfg.subst_warning.image .. '|40px]]',
type = cfg.subst_warning.type_,
text = text,
}) .. cfg.subst_warning.categories
end
---------------------------
-- Primary image/text -----
---------------------------
local assessment_cat = args.ASSESSMENT_CAT or project .. ' articles'
local primary_image = function(image_name, size)
local cell = mw.html.create('td')
if image_name and image_name~='' then
cell:addClass('mbox-image wpb-image')
:wikitext(image(image_name, size, cfg.image.alt))
else
cell:addClass('mbox-empty-cell')
end
return cell
end
local portal = args.PORTAL
local portal_box = portal and frame:expandTemplate{title='Portal', args={portal}} or ''
local main_text = portal_box .. (parse_text(args.MAIN_TEXT) or cfg.main_text:format(
pagetype,
project_link.prefixedText,
project_name,
args.MAIN_ARTICLE and if_exists(args.MAIN_ARTICLE) or if_exists(project, project .. ' articles'),
project_link.talkPageTitle.prefixedText
))
local image_left_size = args.IMAGE_LEFT_SIZE or cfg.image.default_size
local metadata = function(class, data)
return mw.html.create('span'):addClass(class):wikitext(data)
end
local text_cell = mw.html.create('td')
:addClass('mbox-text')
:wikitext(main_text)
:tag('span'):addClass('metadata wpb-metadata')
:node(metadata('wpb-project', project))
:node(metadata('wpb-project_link', project_link.prefixedText))
:node(metadata('wpb-banner_name', banner_name.prefixedText))
:node(metadata('wpb-assessment_cat', assessment_cat))
:done()
local primary_row = mw.html.create('tr')
:node(primary_image(args.IMAGE_LEFT, image_left_size))
:node(text_cell)
:node(primary_image(args.IMAGE_RIGHT, args.IMAGE_RIGHT_SIZE or cfg.image.default_size))
table.insert(rows, primary_row)
---------------------------
-- Quality assessment -----
---------------------------
local assessment_link = args.ASSESSMENT_LINK
if not assessment_link then
local fallback = mw.title.new(project_link.prefixedText .. '/Assessment')
assessment_link = fallback.exists and fallback.prefixedText
elseif assessment_link=='no' then
assessment_link = nil
end
local check_exists = function(class, assessment_cat) -- check if category exists and is not blank
if not isarticle(class) then
local cat = mw.title.new('Category:' .. class .. '-Class' .. ' ' .. assessment_cat)
return (cat.exists and #cat:getContent()>0) and class or 'NA' -- automatically use NA for non-article pages if category does not exist
else
return class
end
end
local class = raw_args.class
if class then -- banner gives quality ratings
local title = args.demo_page and mw.title.new(args.demo_page) or current_title
local article_class = p.readarticleclass({ignore_subtemplates=true}, title.prefixedText)
if not article_class then
if pagetype=='article' then
add_category(cfg.category.no_banner_shell_articles)
else
add_category(cfg.category.no_banner_shell)
end
end
article_class = article_class and p.class_mask(article_class, title, false, pagetype)
local show_quality, conflict = true, false
if args.QUALITY_CRITERIA=='custom' then -- project has opted out of standard assessment scale and uses a custom mask
local custom_mask = banner_name:subPageTitle('class')
if custom_mask.exists and #custom_mask:getContent()>1 then
raw_args.demo_page = args.demo_page -- send demo_page to custom mask
class = mw.text.trim(frame:expandTemplate{
title = custom_mask.prefixedText,
args = raw_args
})
if class=='' and article_class and article_class~='' then -- if unassessed and article class exists, check if it can be inherited
local new_arg_table = {}
for arg, val in pairs(raw_args) do -- construct new argument table to send to custom mask
new_arg_table[arg] = val
end
new_arg_table.class = article_class -- replace class with inherited class
local article_class_normalised = mw.text.trim(frame:expandTemplate{
title = custom_mask.prefixedText,
args = new_arg_table
})
if article_class_normalised and article_class_normalised~='' then
class = article_class_normalised -- inherit class from article_class normalised by custom mask
else
article_class = nil -- effectively no article_class for this banner
end
end
end
else
class = p.class_mask(class, title, true, pagetype)
end
if article_class then -- banner shell exists
if article_class=='' then -- no article class defined
if class=='' then -- local class also does not exist, check whether any other class parameters are defined inside the shell
local classparam = p.readarticleclass({ignore_blank=true, only_subtemplates=true}, title.prefixedText)
if classparam=='' then -- no class parameters defined, display as globally unassessed
show_quality = false -- hide quality class in project banner
end
else
add_category(cfg.category.no_quality_rating)
end
elseif class=='' or class==article_class then -- local class matches article class or is blank
show_quality = false -- hide quality class in project banner
class = article_class
if raw_args.class~='' and args.QUALITY_CRITERIA~='custom' then
add_category(cfg.category.redundant_class)
end
elseif (article_class=='NA') and not isarticle(class) then -- article class and local class are both non-article classes
show_quality = false
else -- article class exists and differs from local class
if args.QUALITY_CRITERIA~='custom' then
conflict = true
add_category(cfg.quality.conflict.category)
end
end
end
if not isarticle(class) then
local cat = mw.title.new(cfg.quality.assessment_category:format(class, assessment_cat))
if not (cat.exists and #cat:getContent()>0) then --check if category exists and is not blank
class = 'NA' -- automatically use NA for non-article pages if category does not exist
end
end
local category = (class=='' and 'Unassessed' or class..'-Class') .. ' ' .. assessment_cat
if show_quality then -- quality rating shown in banner
local rating
if pagetype=='article' then
rating = class=='' and cfg.quality.not_yet or cfg.quality.rated:format(class)
else
rating = cfg.quality.not_required
end
local scale = args.QUALITY_CRITERIA=='custom'
and assessment_link
and cfg.quality.project_scale:format(wikilink(assessment_link..'#'..lang:ucfirst(cfg.quality.name), cfg.quality.name))
or cfg.quality.default_scale
local quality_rating = conflict and cfg.quality.conflict.text or cfg.quality.rating:format(pagetype, rating, scale)
local colour = cfg.quality.colour[class] or cfg.quality.colour.default
local class_row = mw.html.create('tr')
:tag('td')
:addClass('assess'):addClass('assess-' .. class)
:css('background', colour):wikitext(wikilink(':Category:' .. category, class=='' and '???' or class))
:css('border', conflict and cfg.quality.conflict.border or (cfg.quality.border..' '..colour))
:done()
:tag('td')
:addClass('mbox-text'):attr('colspan', '2')
:wikitext(quality_rating)
:done()
table.insert(rows, class_row)
table.insert(
nested_ratings,
1,
bubble(class=='' and 'Unassessed' or (class..'‑class'), colour, conflict)
)
end
add_category(category)
end
if args.HOOK_ASSESS then
table.insert(rows, args.HOOK_ASSESS)
end
if raw_args.b1 or raw_args.b2 or raw_args.b3 or raw_args.b4 or raw_args.b5 or raw_args.b6 then
local b_checklist = require(cfg.auxiliary_module .. (sandbox or '')).b_checklist(args, raw_args, class, demo, assessment_link)
table.insert(rows, b_checklist)
end
---------------------------
-- Importance assessment --
---------------------------
local importance = importance_mask(raw_args.importance or raw_args.priority, class, args.IMPORTANCE_SCALE, banner_name)
local importance_name = args.IMPN or (raw_args.priority and 'priority' or cfg.importance.default_name)
if importance then -- banner gives importance ratings
local category = importance .. '-' .. importance_name .. ' ' .. assessment_cat
if importance~='NA' then -- display importance rating
local rating = importance=='Unknown' and cfg.importance.not_yet or cfg.importance.rated:format(importance, importance_name)
local scale_name = cfg.importance.scale:format(importance_name)
local scale = assessment_link
and cfg.importance.project_scale:format(assessment_link..'#'..lang:ucfirst(scale_name), scale_name)
or cfg.importance.default_scale
local importance_rating = cfg.importance.rating:format(pagetype, rating, scale)
local colour = cfg.importance.colour[importance] or cfg.importance.colour.default
local importance_row = mw.html.create('tr')
:tag('td')
:addClass('assess'):addClass('import'):addClass('import-' .. importance)
:css('background', colour):wikitext(wikilink(':Category:' .. category, importance=='Unknown' and '???' or importance))
:done()
:tag('td')
:addClass('mbox-text'):attr('colspan', '2')
:wikitext(importance_rating)
:done()
table.insert(rows, importance_row)
if importance~='Unknown' then -- importance is not NA or Unknown
table.insert(
nested_ratings,
bubble(importance..'‑'..importance_name, colour)
)
end
end
add_category(category)
end
page_assessment(project, class, importance)
if args.HOOK_IMPORTANCE then
table.insert(rows, args.HOOK_IMPORTANCE)
end
if args.QII_FORMAT then
add_category(require(cfg.auxiliary_module .. (sandbox or '')).quality_importance_insection(args, class, importance, importance_name))
end
---------------------------
-- Collapsing sections ----
---------------------------
local collapse_section = function(collapse, new_rows, header)
if collapse then
local header_row = mw.html.create('tr')
:tag('th')
:attr('colspan','3'):addClass('wpb-collapsed-head'):wikitext(header)
:done()
local blank_row = mw.html.create('tr')
:tag('td')
:addClass('mbox-image wpb-gutter'):css('min-width',image_left_size)
:tag('span'):addClass('wpb-iefix'):wikitext('/ '):done() --TO FIX IE
:done()
:tag('td'):done()
:tag('td'):done()
local collapsed_rows = mw.html.create('table')
:addClass('mw-collapsible mw-collapsed')
:node(header_row)
:node(blank_row)
for _, row in ipairs(new_rows) do
collapsed_rows:node(row)
end
local collapsed_section = mw.html.create('tr')
:tag('td')
:attr('colspan','3'):addClass('wpb-collapsed-notes')
:node(collapsed_rows)
:done()
table.insert(rows, collapsed_section)
else
for _, row in ipairs(new_rows) do
table.insert(rows, row)
end
end
end
---------------------------
-- Task forces ------------
---------------------------
local nested_tf, taskforce_output = {}, {}
local tf_default_size = args.TF_SIZE or cfg.task_force.default_size
for _, k in ipairs(task_forces) do
local tf_prefix = 'TF_' .. k .. '_'
local tf_assessment_cat = args[tf_prefix..'ASSESSMENT_CAT'] or (args[tf_prefix..'NAME'] or '')..' articles'
local tf_importance
if raw_args['tf '..k..' importance'] then
tf_importance = importance_mask(raw_args['tf '..k..' importance'], class, args.IMPORTANCE_SCALE, banner_name)
if tf_importance=='Unknown' and yesno(args.INHERIT_IMPORTANCE) then
tf_importance = importance
end
end
if args[tf_prefix .. 'TEXT']~='none' then
local portal = args[tf_prefix..'PORTAL'] and frame:expandTemplate{title='Portal', args={args[tf_prefix .. 'PORTAL'], height='15', margin='0'}} or ''
local text = ''
local tf_text = args[tf_prefix..'TEXT'] or args.TF_TEXT
if tf_text then
text = portal .. tf_text
:gsub('_NAME_', args[tf_prefix .. 'NAME'] or '')
:gsub('_LINK_', args[tf_prefix .. 'LINK'] or '')
:gsub('_IMPORTANCE_', tf_importance or '')
:gsub('_PAGETYPE_', pagetype)
else
local tf_importance_text = tf_importance
and tf_importance~='NA'
and tf_importance~='Unknown'
and ' ' .. cfg.task_force.importance:format(
wikilink(':Category:' .. tf_importance .. '-' .. importance_name .. ' ' .. tf_assessment_cat, tf_importance .. '-' .. importance_name)
) or ''
text = portal .. cfg.task_force.text:format(
pagetype,
wikilink(args[tf_prefix .. 'LINK'], args[tf_prefix .. 'NAME']),
tf_importance_text
)
end
local tf_size = args[tf_prefix .. 'SIZE'] or tf_default_size
local tf_image = ''
if args[tf_prefix .. 'IMAGE'] then
tf_image = image(args[tf_prefix .. 'IMAGE'], tf_size, cfg.task_force.icon_alt, 'center')
end
local taskforce = mw.html.create('tr')
:tag('td'):wikitext(tf_image):done()
:tag('td'):addClass('mbox-text'):attr('colspan','2'):wikitext(text):done()
table.insert(taskforce_output, taskforce)
end
if args[tf_prefix..'HOOK'] then
table.insert(taskforce_output, args[tf_prefix..'HOOK'])
end
if yesno(args[tf_prefix..'QUALITY']) and class then
local tf_class = check_exists(class, tf_assessment_cat)
add_category((tf_class=='' and 'Unassessed' or tf_class..'-Class') .. ' ' .. tf_assessment_cat)
end
if tf_importance then
add_category(tf_importance .. '-' .. importance_name .. ' ' .. tf_assessment_cat)
end
if args[tf_prefix..'QII_FORMAT'] then
add_category(require(cfg.auxiliary_module .. (sandbox or '')).quality_importance_insection(args, class, tf_importance, importance_name, tf_prefix))
end
if args[tf_prefix..'NAME'] then
page_assessment(project..'/'..args[tf_prefix..'NAME'], class, tf_importance)
end
if args[tf_prefix..'MAIN_CAT'] then
add_category(args[tf_prefix..'MAIN_CAT'])
end
if args[tf_prefix..'NESTED'] then
table.insert(nested_tf, wikilink(args[tf_prefix..'LINK'], args[tf_prefix..'NESTED']))
end
for _, c in ipairs(taskforce_categories[k] or {}) do-- add additional taskforce categories
add_category(args[tf_prefix..'CAT_'..c])
end
end
if args.HOOK_TF then
table.insert(taskforce_output, args.HOOK_TF)
end
local threshold = tonumber(args.TF_COLLAPSE) or (args.TF_HEADER and cfg.task_force.lower_threshold) or cfg.task_force.upper_threshold
collapse_section(
#taskforce_output > threshold,
taskforce_output,
args.TF_HEADER or cfg.task_force.header
)
---------------------------
-- Notes ------------------
---------------------------
local note_output = {}
local note_default_size = args.NOTE_SIZE or args.NOTE_1_SIZE or cfg.note.default_size
local render_note = function(note_args)--text, image_name, size, category, sort_prefix
local sort = note_args.sort_prefix and note_args.sort_prefix .. current_title.text
add_category(note_args.category, sort)
add_category(note_args.category2, sort)
if note_args.text then
local note_image = image(note_args.image_name, note_args.size or note_default_size, cfg.note.icon_alt, 'center')
local new_note = mw.html.create('tr')
:tag('td'):css('background', note_args.background):wikitext(note_image):done()
:tag('td'):addClass('mbox-text'):attr('colspan', '2'):wikitext(note_args.text):done()
table.insert(note_output, new_note)
if note_image then
local icon = mw.html.create('span')
:addClass('wpb-header-bubbles')
:wikitext('[[File:' .. note_args.image_name .. '|' .. cfg.note.header_icon .. '|' .. note_args.text .. '|link=|alt=]]')
table.insert(nested_ratings, tostring(icon))
end
end
end
local auto = false
local auto_arg = args.auto and args.auto:lower()
if (auto_arg=='yes' or auto_arg=='stub') and class=='Stub' then
auto = 'stub'
elseif (auto_arg=='inherit' or auto_arg=='length') and class and class~='' then
auto = auto_arg
end
if auto then
local auto_cat = args.AUTO_ASSESS_CAT or cfg.auto.default_cat:format(project)
local auto_text = cfg.auto.assessed:format(
pagetype,
cfg.auto[auto], -- method of automatic assessment
parameter_format('auto')
)
local sort_prefix
if auto=='stub' then
sort_prefix = 'S'
elseif auto=='length' then
sort_prefix = 'L'
elseif auto=='inherit' then
local sort_codes = cfg.auto.sort_codes
sort_prefix = sort_codes[class] or cfg.auto.default_sort_code
end
render_note{
text = auto_text,
image_name = cfg.auto.icon,
category = auto_cat,
sort_prefix = sort_prefix
}
end
if yesno(args.attention, true) then
local attention_cat = args.ATTENTION_CAT or cfg.attention.default_cat:format(project)
render_note{
text = cfg.attention.text:format(pagetype),
image_name = cfg.attention.icon,
category = attention_cat
}
end
if yesno(args.infobox, true) then
local infobox_cat = args.INFOBOX_CAT or cfg.infobox.default_cat:format(project)
render_note{
text = cfg.infobox.text:format(pagetype),
image_name = cfg.infobox.icon,
category = infobox_cat
}
end
for _, k in ipairs(notes) do
local note_prefix = 'NOTE_' .. k .. '_'
render_note{
text = parse_text(args[note_prefix..'TEXT']),
image_name = args[note_prefix..'IMAGE'],
size = args[note_prefix..'SIZE'],
category = args[note_prefix..'CAT']
}
end
if yesno(args['image-needed'], true) then
local image_needed_args = require(cfg.auxiliary_module .. (sandbox or '')).image_needed(args, pagetype)
render_note(image_needed_args)
end
if yesno(args['collaboration-candidate'], true) or yesno(args['collaboration-current'], true) or yesno(args['collaboration-past'], true) then
local collaboration_args = require(cfg.auxiliary_module .. (sandbox or '')).collaboration(args, pagetype, current_title)
render_note(collaboration_args.candidate)
render_note(collaboration_args.current)
render_note(collaboration_args.past)
end
if yesno(args['a class'], true) then
local a_class_args = require(cfg.auxiliary_module .. (sandbox or '')).a_class(args, lang)
render_note(a_class_args)
end
if yesno(args['peer review'], true) or yesno(args['old peer review'], true) then
local peer_review_args = require(cfg.auxiliary_module .. (sandbox or '')).peer_review(args, current_title)
render_note(peer_review_args.current)
render_note(peer_review_args.past)
end
local note_count = #note_output
if args.HOOK_NOTE then
table.insert(note_output, args.HOOK_NOTE)
local hook_collapsed = 0
if args.HOOK_COLLAPSED then
local success, result = pcall(mw.ext.ParserFunctions.expr, args.HOOK_COLLAPSED)
hook_collapsed = success and tonumber(result) or 0
if args.HOOK_COLLAPSED=='auto' then
hook_collapsed = 1
end
end
note_count = note_count + hook_collapsed
end
collapse_section(
note_count > (tonumber(args.COLLAPSED) or cfg.note.threshold),
note_output,
args.COLLAPSED_HEAD or cfg.note.header
)
---------------------------
-- Bottom text ------------
---------------------------
if args.HOOK_BOTTOM then
table.insert(rows, args.HOOK_BOTTOM)
end
if args.TODO_LINK or args.TODO_TEXT then
local todolist = require(cfg.auxiliary_module .. (sandbox or '')).todo_list(args, frame)
table.insert(rows, todolist)
end
if args.BOTTOM_TEXT then
local bottom_text = mw.html.create('tr')
:tag('td')
:attr('colspan','3')
:wikitext(parse_text(args.BOTTOM_TEXT))
:done()
table.insert(rows, bottom_text)
end
if args.MAIN_CAT then
add_category(args.MAIN_CAT)
end
---------------------------
-- Nested display ---------
---------------------------
if args.HOOK_NESTED then
local hook_nested = args.HOOK_NESTED:gsub('^ / ', '') -- remove initial slash, will be added later
table.insert(nested_tf, hook_nested)
end
local nested_tf_str = ''
if #nested_tf>0 then
nested_tf_str = tostring(mw.html.create('span')
:css('font-weight', 'normal') --TODO: move to TemplateStyles.
:wikitext(': ' .. table.concat(nested_tf, ' / '))
)
end
local nested_ratings_str = #nested_ratings>0 and table.concat(nested_ratings, ' ') or ''
if args.HOOK_NESTED_ASSESS then
nested_ratings_str = nested_ratings_str .. tostring(mw.html.create('span')
:addClass('wpb-header-bubbles')
:wikitext(args.HOOK_NESTED_ASSESS)
)
end
local header_row = mw.html.create('tr')
:addClass('wpb-header')
:tag('td')
:addClass('wpb-header-icon')
:attr('width', '50px') --TODO: move to TemplateStyles.
:css('text-align', 'center') --TODO: move to TemplateStyles.
:wikitext(image(args.IMAGE_LEFT, cfg.image.header_size, cfg.image.alt))
:done()
:tag('td')
:addClass('wpb-header-combined')
:wikitext(wikilink(project_link.prefixedText, project) .. nested_tf_str .. ' ' .. nested_ratings_str)
:done()
---------------------------
-- Prepare categories -----
---------------------------
local categories_formatted = ''
if args.demo_page then -- for testing purposes
local category_list = mw.html.create('ul')
for _, cat in ipairs(categories) do
local item = mw.html.create('li')
:wikitext(wikilink(':Category:' .. cat.category, cat.category))
category_list:node(item)
end
local category_box = mw.html.create('div')
:css('background-color', '#F5F5F5'):css('border-width', '1px') --TODO: move to TemplateStyles.
:css('width', '500px') --TODO: move to TemplateStyles.
:wikitext('Categories:')
:node(category_list)
categories_formatted = tostring(category_box)
elseif not demo then
local categories_linked = {}
for _, cat in ipairs(categories) do
local cat_link = wikilink('Category:' .. cat.category, cat.key)
table.insert(categories_linked, cat_link)
end
categories_formatted = table.concat(categories_linked)
end
---------------------------
-- Make banner ------------
---------------------------
local banner_rows = mw.html.create('table')
for _, row in ipairs(rows) do
banner_rows:node(row)
end
local banner = mw.html.create('table')
:addClass('tmbox tmbox-notice mw-collapsible innercollapse wpb')
:addClass(inactive and cfg.status.inactive_class or nil)
:css('table-layout', 'fixed') --TODO: move to TemplateStyles.
:node(header_row)
:tag('tr'):tag('td')
:addClass('mbox-text wpb-main')
:attr('colspan','2')
:node(banner_rows)
:allDone()
if args.listas then
frame:preprocess('{{DEFAULTSORT:' .. args.listas .. '}}')
end
local tstyle = frame:extensionTag ('templatestyles', '', {src='Module:Message box/tmbox.css'}) ..
frame:extensionTag ('templatestyles', '', {src = 'Module:WikiProject banner' .. (sandbox or '') .. '/styles.css'})
return warning .. tstyle .. tostring(banner) .. categories_formatted, note_count, #taskforce_output, assessment_link
end
local parameter_check = function(frame, banner_name, project_name)
---------------------------
-- Unknown parameters -----
---------------------------
local parent_args = args_module.getArgs(frame, {parentOnly = true})
local parameters = {}
for parameter in banner_name:getContent():gmatch('{{{([^|}]+)') do
table.insert(parameters, parameter)
end
parameters.preview = cfg.unknown_parameters.preview:format(wikilink(banner_name.fullText))
local unknown_category = cfg.unknown_parameters.tracking:format(project_name)
if not mw.title.new(unknown_category).exists then
unknown_category = cfg.unknown_parameters.default
end
parameters.unknown = unknown_category and '[[' .. unknown_category .. '|_VALUE_]]' or ''
return require('Module:Check for unknown parameters')._check(parameters, parent_args)
end
local initialise = function(args, raw_args, inactive_status)
args.demo_page = args_module.getArgs(frame, {parentOnly = true}).demo_page
local project_name = args.PROJECT_NAME or 'WikiProject ' .. (args.PROJECT or 'PROJECT')
local banner_name = mw.title.new(args.BANNER_NAME or 'Template:WikiProject ' .. (args.PROJECT or 'PROJECT'))
local demo = not yesno(args.category or true, true) or args.demo_page
local on_template_page = not demo and current_title.rootPageTitle==banner_name.rootPageTitle
local unknown_parameters = banner_name.exists and not demo and parameter_check(frame, banner_name, project_name) or ''
if on_template_page then
local templatepage = require('Module:WikiProject banner/templatepage' .. (sandbox or '')).templatepage
return templatepage(args, raw_args, inactive_status)
else
return unknown_parameters
.. p._main(args, raw_args, demo or inactive_status, banner_name, inactive_status and true or false), nil -- nil to disregard subsequent returned values
end
end
p.main = function(frame)
local args = args_module.getArgs(frame, {frameOnly = true})
local raw_args = args_module.getArgs(frame, {frameOnly = true, removeBlanks = false})
return initialise(args, raw_args)
end
---------------------------
-- Inactive projects ------
---------------------------
p.inactive = function(frame)
local args = args_module.getArgs(frame, {frameOnly = true})
local project_name = args.PROJECT_NAME or 'WikiProject ' .. (args.PROJECT or 'PROJECT')
local project_link = mw.title.new(args.PROJECT_LINK or 'Wikipedia:' .. project_name)
local _status = cfg.status[args.PROJECT_STATUS] or cfg.status.default_inactive
local main_text = cfg.inactive.text:format(
'_PAGETYPE_',
project_link.prefixedText,
project_name,
_status
)
return initialise({
PROJECT = args.PROJECT,
BANNER_NAME = args.BANNER_NAME,
IMAGE_LEFT = cfg.inactive.image,
IMAGE_LEFT_SIZE = cfg.inactive.image_size,
MAIN_TEXT = main_text,
HOOK_NESTED_ASSESS = ' ' .. cfg.inactive.nested:format(_status),
substcheck = args.substcheck,
category = args.category
},
{
class = frame.args.class,
substcheck = '' -- to prevent warning on templatepage
},
_status
)
end
return p