Module:WikiProject banner/sandbox: Difference between revisions

Content deleted Content added
can't we just put it through tostring? using the colour of importance does not seem to make sense for this because it is not an importance
m Removed protection from "Module:WikiProject banner/sandbox"
 
(703 intermediate revisions by 14 users not shown)
Line 1:
require('strict')
local p = {}
local sandbox = '/sandbox' -- BE SURE TO COMMENT OUT this definition when deploying to live
local cfg = mw.loadData('Module:WikiProject banner/config' .. (sandbox or ''))
local auxiliary = cfg.auxiliary_module .. (sandbox or '')
local args_module = require('Module:Arguments')
local mbox = require('Module:Message box').main
local yesno = require('Module:Yesno')
Line 20 ⟶ 22:
end
 
local imagedisplay_error = function(argstext)
local span = mw.html.create('div')
return string.format(
:addClass('error')
'[[File:%s%s%s%s%s]]',
:wikitext(text)
args.image,
return tostring(span)
(args.size and args.size ~= '') and '|' .. args.size or '',
end
(args.___location and args.___location ~= '') and '|' .. args.___location or '',
 
(args.alt and args.alt ~= '') and '|alt=' .. args.alt or '',
local image = function(image_name, size, alt, position)
(args.link and args.link ~= '') and '|link=' .. args.link or ''
return image_name and '[[File:'
)
.. image_name
.. (size and '|' .. size or '')
.. (position and '|' .. position or '')
.. (alt and '|alt=' .. alt or '')
.. ']]'
end
 
Line 40 ⟶ 47:
end
 
local isarticleimportance_mask = function(raw_importance, scale, banner_name, pagetype, class)
---------------------------
local article = true
-- Importance mask --------
for _,v in ipairs(cfg.quality.non_article_classes) do
---------------------------
if class==v then -- class matches one of the non-article classes
local importance
article = false
if scale=='inline' then -- pass importance without change
break
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,
pagetype = pagetype
}
})
end
elseif raw_importance then-- standard importance scale
importance = cfg.importance.na
if pagetype=='article' or pagetype=='set index article' or pagetype=='redirect' or pagetype=='draft' then
local mask = cfg.importance.mask
if mask[raw_importance:lower()] then -- valid importance specified
importance = mask[raw_importance:lower()]
elseif pagetype=='article' or pagetype=='set index article' then -- unspecified or invalid importance, use "Unknown" for articles
importance = cfg.importance.unknown
end
end
end
return article
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').getValuegetParameter
local success, result = get_parameter_value(page, cfg.WPBS_redirectsbanner_shell.redirects, 'class', options)
return success and result
-- returns FALSE if banner shell template does not exist on page
Line 60 ⟶ 92:
-- otherwise returns class parameter
end
p.class_mask = function(class, title, FQS, pagetype, article)
 
local importance_maskresolveFQSgrade = function(raw_importance, class, scale, banner_name)
return FQS and lang:ucfirst(class) or 'NA'
local importance
end
if scale=='inline' then -- pass importance without change
local out
importance = raw_importance
title = title or mw.title.getCurrentTitle()
elseif scale=='subpage' then
local ns = title.namespace
local custom_mask = banner_name:subPageTitle('importance')
class = class:match('^%s*(.-)%s*$'):lower()
if custom_mask.exists and #custom_mask:getContent()>1 then -- pass to custom importance mask
if pagetype=='redirect' or pagetype=='soft redirect' then
importance = frame:expandTemplate{
out = resolveFQSgrade('redirect')
title=custom_mask.prefixedText,
elseif pagetype=='disambiguation page' then
args={importance=raw_importance or '¬', class=class}
out = resolveFQSgrade('disambig')
}
elseif article or pagetype=='article' or pagetype=='set index article' then
if pagetype=='set index article' then
out = 'List'
elseif 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' then
out = 'FM'
else
out = resolveFQSgrade('file')
end
else
local grade = cfg.quality.ns_to_class[ns] or 'NA'
importance = frame:expandTemplate{title='Template:Importance mask', args={raw_importance or '¬', class=class}}
out = resolveFQSgrade(grade)
end
if importance=='¬' then
importance = nil
end
return importanceout
end
 
Line 87 ⟶ 134:
end
 
local bubble = function(text, shortTextconflict, colour, optionstyle)
local out = mw.html.create('span')
option = tonumber(option)
if option==4 then
out = mw.html.create('span')
:addClass('wpb-header-bubbles')
:css('border', '0.2em solid ' .. colour)
:wikitext(text)
elseif option==5 then
local highContrastColors = {["FA"] = "#7595D7", ["FL"] = "#7595D7", ["FM"] = "#7595D7", ["A"] = "#0DA6A6", ["AL"] = "#0DA6A6", ["GA"] = "#14AD14", ["B"] = "#5AA70E", ["C"] = "#9A9A00", ["Start"] = "#D5803C", ["Stub"] = "#D67B7B", ["List"] = "#9F89D7", ["NA"] = "#959595", ["Top"] = "#D56DD5", ["High"] = "#CA77CA", ["Mid"] = "#BE80BD", ["Low"] = "#AF88B0"}
local contrastColour = highContrastColors[shortText]
out = mw.html.create('span')
:addClass('wpb-header-bubbles')
:addClass(style)
:css('color', contrastColour)
:addClass(conflict and 'conflict' or nil)
:css('border', '0.16em solid ' .. contrastColour)
:wikitext(text)
else
out = mw.html.create('span')
:addClass('wpb-header-bubbles')
:css('background', colour)
:css('border', '0.075em solid ' .. colour)
:wikitext(text)
end
return tostring(out)
end
 
function p._main = function(args, raw_args, demodemo_page, 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 = demodemo_page==true and 'article' or require('Module:Pagetype')._main({})
page = demo_page,
local rows, collapsed, nested_ratings, task_forces, notes, categories = {}, {}, {}, {}, {}, {}
dab = 'disambiguation page',
sia = 'set index article',
draft = 'draft'
})
local article = pagetype=='article' or pagetype=='set index article'
local rows, nested_ratings, task_forces, notes, categories, taskforce_categories = {}, {}, {}, {}, {}, {}
local add_category = function(category, key)
if notcategory demoand category~='none' then
localtable.insert(categories, cat_link{category = wikilink('Category:' .. category, key = key})
table.insert(categories, cat_link)
end
end
local parse_textparse_pt = function(text) -- function to replace _PAGETYPE_ with the actual page type
local ptype = article and 'article' or pagetype -- display "article" for articles otherwise page type
return text and string.gsub(text, '_PAGETYPE_', pagetype)
return text and text:gsub('_PAGETYPE_', ptype)
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) then
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 note_matchtf, cat = mw.ustring.match(arg_name,'^notetf (%d+) cat (%d+)$')
if note_matchtf and yesno(arg_value, true) then
if not taskforce_categories[tf] then -- initialise table
table.insert(notes, note_match)
taskforce_categories[tf] = {}
end
table.insert(taskforce_categories[tf], cat)
end
end
Line 144 ⟶ 186:
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 assessment_category = function(cat, name)
local warning = ''
if cat then
return cat:gsub(' articles', '') -- remove "articles" from category
else
return name or ''
end
end
local assessment_cat = assessment_category(args.ASSESSMENT_CAT, project)
---------------------------
-- Location warning -------
---------------------------
local warning = ''
local show_namespace_warning = not (current_title.isTalkPage or demo)
if not current_title.isTalkPage and not demo_page then
if show_namespace_warning then
local text = stringcfg.namespace_warning.text:format(
cfg.namespace_warning.text .. '<br><span style="font-size:95%%">' .. cfg.namespace_warning.small .. '</span>',
pagetype,
current_title.talkPageTitle.fullText,
parameter_format('category', 'no')
Line 158 ⟶ 205:
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 .. string' ' .. cfg.namespace_warning.on_template_page:format(
cfg.namespace_warning.on_template_page,
parameter_format('BANNER_NAME'),
current_title.prefixedText
Line 167 ⟶ 213:
image = '[[File:' .. cfg.namespace_warning.image .. '|40px]]',
type = cfg.namespace_warning.type_,
text = parse_pt(text)
})
if not current_title.subjectPageTitle:inNamespace(2) then
Line 177 ⟶ 223:
---------------------------
if args.substcheck=='SUBST' then
local text = stringcfg.subst_warning.text:format(
cfg.subst_warning.text,
project_name,
'<code>&#123;&#123;'..banner_name.prefixedText..'&#125;&#125;</code>'
Line 191 ⟶ 236:
-- Primary image/text -----
---------------------------
local primary_image = function(image_name, size)
local project_talk = wikilink(project_link.talkPageTitle.prefixedText,'the discussion')
local assessment_cat = args.ASSESSMENT_CAT or project .. ' articles'
local primary_image = function(image_name, image_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))
image = image_name,
size = image_size,
alt = 'WikiProject icon'
}))
else
cell:addClass('mbox-empty-cell')
end
cell:done()
return cell
end
local mainarticle = args.MAIN_ARTICLE
local topic = mainarticle and if_exists(mainarticle) or if_exists(project, project .. ' articles')
local portal = args.PORTAL
local portal_box = portal and frame:expandTemplate{title='Portal', args={portal}} or ''
local main_text = portal_box .. (parse_textparse_pt(args.MAIN_TEXT) or stringcfg.main_text:format(
project_link.prefixedText,
cfg.maintext,
project_name,
pagetype,
args.MAIN_ARTICLE and if_exists(args.MAIN_ARTICLE) or if_exists(project, project .. ' articles'),
wikilink(project_link.prefixedText, project_name),
project_link.talkPageTitle.prefixedText
topic,
project_talk
))
local image_left_size = args.IMAGE_LEFT_SIZE or argscfg.IMAGE_LEFT_LARGE or '80px'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')
primary_row
:node(primary_image(args.IMAGE_LEFT, image_left_size))
:tagnode('td'text_cell)
:node(primary_image(args.IMAGE_RIGHT, args.IMAGE_RIGHT_SIZE or cfg.image.default_size))
:addClass('mbox-text')
:wikitext(main_text)
:tag('span')
:addClass('metadata wpb-metadata')
:tag('span')
:addClass('wpb-project')
:wikitext(project)
:done()
:tag('span')
:addClass('wpb-project_link')
:wikitext(project_link.prefixedText)
:done()
:tag('span')
:addClass('wpb-banner_name')
:wikitext(banner_name.prefixedText)
:done()
:tag('span')
:addClass('wpb-assessment_cat')
:wikitext(assessment_cat)
:done()
:done()
:done()
:node(primary_image(
args.IMAGE_RIGHT,
args.IMAGE_RIGHT_SIZE or args.IMAGE_RIGHT_LARGE or '80px'
))
:done()
table.insert(rows, primary_row)
---------------------------
-- Banner shell checks ----
---------------------------
local title = demo_page and demo_page~=true and mw.title.new(demo_page) or current_title
local article_class = p.readarticleclass({ignore_subtemplates=true}, title.prefixedText)
if article_class then -- banner shell exists
local special_chars = '([%%%(%)%.%+%-%*%?%[%]%^%$])'
local banner_name_escaped = banner_name.text
local page_content = require('Module:Wikitext Parsing').PrepareText(title:getContent()) -- get content of current page
local content_without_shell
for capture in mw.ustring.gmatch(page_content, '%b{}') do -- look for possible templates on page
for _, redirect in ipairs(cfg.banner_shell.redirects) do
if mw.ustring.find(capture, '^{{%s*' .. redirect .. '%s*[|}].*}}$') then -- found a banner shell
banner_name_escaped = banner_name_escaped:gsub(special_chars, '%%%1') -- escape each special character
capture = capture:gsub(special_chars, '%%%1')
content_without_shell = mw.ustring.gsub(page_content, capture, '') -- remove banner shell content from page content
end
if content_without_shell then break end
end
if content_without_shell then break end
end
local template_outside_shell
if content_without_shell and mw.ustring.find(content_without_shell, '{{%s*' .. banner_name_escaped .. '%s*[|}]') then -- found banner template outside of the shell
add_category(cfg.banner_shell.category.outside_shell)
end
else -- no banner shell on page
if article then
add_category(cfg.banner_shell.category.no_banner_shell_articles)
elseif title.namespace==3 then --User talk namespace
for _, user in ipairs(cfg.banner_shell.valid_users) do
if string.find(title.rootText, user) then
add_category(cfg.banner_shell.category.no_banner_shell)
end
end
elseif title.namespace~=2 then --User namespace
add_category(cfg.banner_shell.category.no_banner_shell)
end
end
---------------------------
-- Quality assessment -----
Line 262 ⟶ 323:
assessment_link = nil
end
local check_fallbacks = function(class, category)
local class_mask = require('Module:Class mask')._main
if article or args.QUALITY_CRITERIA=='custom' then -- no fallbacks for articles or projects with custom quality scales
local class
return class
if args.QUALITY_SCALE=='inline' then
else -- check fallbacks for non-article classes
class = raw_args.class
local new_class = class
elseif args.QUALITY_SCALE=='subpage' then
local custom_maskcategory_exists = banner_name:subPageTitlefunction('class')
local cat = mw.title.new(cfg.quality.assessment_category:format(class, category .. ' ' .. (article and 'articles' or 'pages')))
if custom_mask.exists then
return cat.exists and #cat:getContent()>0 -- check if category exists and is not blank
class = frame:expandTemplate{
end
title=custom_mask.prefixedText,
if class=='FM' and not category_exists('FM') then
args=raw_args
new_class = 'File' -- fall back to File-class if FM category does not exist
}
end
if not category_exists(new_class) then
new_class = 'NA' -- use NA for non-article pages if category does not exist
end
return new_class
end
else
args.FQS = args.QUALITY_SCALE=='extended' and 'yes' or 'no'
args[1] = raw_args.class
class = class_mask(args, current_title)
end
local show_quality = true
if class=='¬' then
class = nil
end
local class = raw_args.class
if class then -- banner gives quality ratings
article_class = article_class and p.class_mask(article_class, title, false, pagetype, article)
if args.QUALITY_CRITERIA~='custom' then -- project uses standard scale and will inherit article class if needed
if args.QUALITY_CRITERIA=='custom' then -- project has opted out of standard assessment scale and uses a custom mask
local article_class = p.readarticleclass({ignore_subtemplates=true}, current_title.prefixedText)
local custom_mask = banner_name:subPageTitle('class')
article_class = article_class and class_mask({article_class}, current_title)
if custom_mask.exists and #custom_mask:getContent()>1 then
if article_class then -- banner shell exists
raw_args.demo_page = demo_page -- send demo_page to custom mask
if article_class=='' then -- no article class defined
class = mw.text.trim(frame:expandTemplate{
if class=='' then -- local class also does not exist, check whether any other class parameters are defined inside the shell
title = custom_mask.prefixedText,
local classparam = p.readarticleclass({ignore_blank=true, only_subtemplates=true}, current_title.prefixedText)
args = raw_args
if classparam=='' then -- no class parameters defined, display as globally unassessed
})
show_quality = false -- hide quality class in project banner
if class=='' and article_class and article_class~='' then -- if unassessed and article class exists, check if it can be inherited
end
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
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
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
add_category('Articles with conflicting quality ratings')
end
end
else
class = p.class_mask(class, title, true, pagetype, article)
end
local check_redundant = function()
if raw_args.class~='' and args.QUALITY_CRITERIA~='custom' then -- banner has a non-blank class value which is ignored
add_category(cfg.banner_shell.category.redundant_class)
end
end
class = check_fallbacks(class, assessment_cat)
local show = false -- hide quality class in project banner by default
if article_class then -- banner shell exists
if class=='' then -- local class is blank
class = check_fallbacks(article_class, assessment_cat) -- check fallbacks again now that class may have changed
check_redundant()
elseif class==article_class then -- local class matches article class
check_redundant()
elseif article_class=='' then -- local class defined and no article class defined
show = true
add_category(cfg.banner_shell.category.no_quality_rating)
if args.QUALITY_CRITERIA~='custom' then
warning = warning .. display_error(cfg.banner_shell.piqa_warning)
end
elseif article_class=='FM' and args.QUALITY_CRITERIA~='custom' then
class = check_fallbacks('FM', assessment_cat)
check_redundant()
elseif not article and class~='FM' then -- article class and local class are both non-article classes
check_redundant()
elseif args.QUALITY_CRITERIA=='custom' then -- project uses custom criteria and class differs
show = true -- show quality class in project banner
else -- article class exists and differs from local class
show = 'conflict'
add_category(cfg.banner_shell.conflict.category2:format(class, article_class))
end
else -- banner shell does not exist
show = true
end
local category = (class=='' and 'Unassessed' or class..'-Class') .. ' ' .. assessment_cat .. ' ' .. (article and 'articles' or 'pages')
if show_quality then -- quality rating shown in banner
if show then -- quality rating shown in banner
local class_module = require('Module:Class')._class
local rating
if pagetype=='article' then
rating = class=='' and cfg.quality.not_yet or string.format(cfg.quality.rated, :format(class)
else
rating = cfg.quality.not_required
end
local scale = args.QUALITY_CRITERIA=='custom'
and assessment_link and string.format(
and cfg.quality.project_scale:format(wikilink(assessment_link..'#'..lang:ucfirst(cfg.quality.name), cfg.quality.name))
or cfg.quality.default_scale
wikilink(assessment_link..'#'..lang:ucfirst(cfg.quality.name), cfg.quality.name)
local quality_rating = show=='conflict'
) or cfg.quality.default_scale
and cfg.banner_shell.conflict.text
local quality_rating = string.format(
or cfg.quality.rating:format(rating, scale)
local cssClass = 'class-' .. (class=='' and 'unassessed' or class:lower())
pagetype,
rating,
scale
)
local class_row = mw.html.create('tr')
:tag('td')
class_row
:addClass('assess')
:node(class_module{class, category = assessment_cat})
:addClass(cssClass)
:addClass(show=='conflict' and 'conflict' or nil)
:wikitext(wikilink(':Category:' .. category, class=='' and '???' or class))
:done()
:tag('td')
:addClass('mbox-text')
:attr('colspan', '2')
:wikitext(parse_pt(quality_rating))
:allDonedone()
table.insert(rows, class_row)
table.insert(
local new_bubble = bubble(
nested_ratings,
class .. '‑class',
class1,
bubble(class=='' and 'Unassessed' or (class..'‑class'), show=='conflict', cssClass)
frame:expandTemplate{ title = 'Class/colour', args = {class} },
args.mockup
)
table.insert(nested_ratings, 1, new_bubble)
end
add_category(category)
add_category((class=='' and 'Unassessed' or class..'-Class') .. ' ' .. assessment_cat)
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('Module:WikiProject banner/auxiliary' .. (sandbox or '')).b_checklist(args, raw_args, class, demodemo_page, assessment_link)
table.insert(rows, b_checklist)
end
Line 352 ⟶ 452:
-- Importance assessment --
---------------------------
local importance = importance_mask(raw_args.importance or raw_args.priority, class, args.IMPORTANCE_SCALE, banner_name, pagetype, class)
local importance_name = args.IMPN or (raw_args.priority and 'priority' or cfg.importance.default_name)
if importance and importance~='NA' then -- displaybanner gives importance ratingratings
local ratingcategory = importance== .. 'Unknown-' and.. importance_name cfg.importance.not_yet or' ' string.format(cfg.importance assessment_cat ..rated, ' ' .. (importance,=='NA' importance_nameand 'pages' or 'articles')
if importance~='NA' then -- display importance rating
local scale_name = string.format(cfg.importance.scale, importance_name)
local rating = importance=='Unknown' and cfg.importance.not_yet or cfg.importance.rated:format(importance, importance_name)
local scale = assessment_link and string.format(
local scale_name = cfg.importance.project_scale,scale:format(importance_name)
local scale = assessment_link
wikilink(assessment_link..'#'..lang:ucfirst(scale_name), scale_name)
and cfg.importance.project_scale:format(assessment_link..'#'..lang:ucfirst(scale_name), scale_name)
) or cfg.importance.default_scale
or cfg.importance.default_scale
local importance_rating = string.format(
local importance_rating = parse_pt(cfg.importance.rating:format(rating, scale))
local cssClass = 'import-' .. importance:lower()
pagetype,
local importance_row = mw.html.create('tr')
rating,
:tag('td')
scale
:addClass('assess')
)
:addClass(cssClass)
local importance_row = mw.html.create('tr')
:wikitext(wikilink(':Category:' .. category, importance=='Unknown' and '???' or importance))
importance_row
:done()
:node(frame:expandTemplate{title='Importance', args={importance, category=assessment_cat, impn=importance_name}})
:tag('td')
:addClass('mbox-text')
:attr('colspan', '2')
:wikitext(importance_rating)
:allDonedone()
table.insert(rows, importance_row)
if importance~='Unknown' then -- importance is not NA or Unknown
table.insert(
local new_bubble = bubble(
nested_ratings,
importance .. '‑' .. importance_name,
bubble(importance .. '‑' .. importance_name, false, cssClass)
)
frame:expandTemplate{ title = 'Importance/colour', args = {importance} },
end
args.mockup
)
table.insert(nested_ratings, new_bubble)
end
add_category(category)
end
if importance then --add importance category
add_category((importance=='' and 'Unknown' or importance..'-' .. importance_name) .. ' ' .. assessment_cat)
end
if class or importance then
Line 394 ⟶ 490:
if args.HOOK_IMPORTANCE then
table.insert(rows, args.HOOK_IMPORTANCE)
end
if args.QII_FORMAT then
add_category(require(auxiliary).quality_importance_insection(args, class, importance, importance_name, assessment_cat, article))
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('/&nbsp;')
: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 argscfg.TF_1_SIZE or 'x25px'task_force.default_size
for _, k in ipairs(task_forces) do
local tf_prefix = 'TF_' .. k .. '_'
local tf_assessment_cat = assessment_category(
args[tf_prefix..'ASSESSMENT_CAT'] or (,
args[tf_prefix..'NAME'] or '')..' articles'
)
local tf_importance = raw_args['tf '..k..' importance'] and importance_mask(raw_args['tf '..k..' importance'], class, args.IMPORTANCE_SCALE, banner_name)
if yesno(args[tf_prefix..'QUALITY']) and class then
local tf_class = check_fallbacks(class, tf_assessment_cat)
add_category((tf_class=='' and 'Unassessed' or tf_class..'-Class') .. ' ' .. tf_assessment_cat .. ' ' .. (article and 'articles' or 'pages'))
end
local tf_importance, tf_importance_category
if raw_args['tf '..k..' importance'] then
tf_importance = importance_mask(raw_args['tf '..k..' importance'], args.IMPORTANCE_SCALE, banner_name, pagetype, class)
if tf_importance=='Unknown' and yesno(args.INHERIT_IMPORTANCE) then
tf_importance = importance
end
tf_importance_category = tf_importance .. '-' .. importance_name .. ' ' .. tf_assessment_cat .. ' ' .. (tf_importance=='NA' and 'pages' or 'articles')
add_category(tf_importance_category)
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 = ''
iflocal tf_text = args[tf_prefix..'PORTALTEXT'] thenor args.TF_TEXT
if tf_text then
text = frame:expandTemplate{title='Portal', args={args[tf_prefix .. 'PORTAL'], height='15', margin='0'}}
text = portal .. tf_text
end
if :gsub('_NAME_', args[tf_prefix .. 'TEXTNAME'] thenor '')
text = text .. parse_text :gsub('_LINK_', args[tf_prefix .. 'TEXTLINK'] or '')
:gsub('_IMPORTANCE_', tf_importance or '')
else
local tf_importance_text = tf_importance
text = text .. 'This ' .. pagetype .. ' is supported by <b>' .. wikilink(args[tf_prefix .. 'LINK'],args[tf_prefix .. 'NAME']) .. '</b>'
if tf_importance and tf_importance~='NA'
and tf_importance~='Unknown' then
and ' ' .. cfg.task_force.importance:format(
text = text .. ' (marked as ' .. wikilink(':Category:' .. tf_importance .. '-' .. importance_name .. ' ' .. tf_assessment_cat, tf_importance .. '-' .. importance_name) .. ')'
end wikilink(
':Category:' .. tf_importance_category,
text = text .. '.'
tf_importance .. '-' .. importance_name
)
) or ''
text = portal .. cfg.task_force.text:format(
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')
image = args[tf_prefix..'IMAGE'],
size = tf_size,
___location = 'center',
alt = 'Taskforce icon',
}
end
local taskforce = mw.html.create('tr')
taskforce
:tag('td')
:wikitext(tf_image)
Line 436 ⟶ 599:
:addClass('mbox-text')
:attr('colspan','2')
:wikitext(parse_pt(text))
:allDonedone()
table.insert(rowstaskforce_output, taskforce)
end
if args[tf_prefix..'HOOK'] then
table.insert(rowstaskforce_output, args[tf_prefix..'HOOK'])
end
if yesno(args[tf_prefix..'QUALITY']) and class then
add_category((class=='' and 'Unassessed' or class..'-Class') .. ' ' .. tf_assessment_cat)
end
if tf_importanceargs[tf_prefix..'QII_FORMAT'] then
add_category(tf_importance .require(auxiliary).quality_importance_insection(args, '-'class, ..tf_importance, importance_name, ..tf_assessment_cat, 'article, ' .. tf_assessment_cattf_prefix))
end
if args[tf_prefix..'NAME'] then
Line 457 ⟶ 617:
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(rowstaskforce_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 'x25px'
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
iflocal sort = note_args.categorysort_prefix and note_args.category~='none'sort_prefix then.. current_title.text
add_category(note_args.category, sort)
local sort = note_args.sort_prefix and note_args.sort_prefix .. current_title.text
add_category(note_args.categorycategory2, sort)
end
local note_image = note_args.image_name and image{
image = note_args.image_name,
size = note_args.size or note_default_size,
___location = 'center',
alt = 'Note icon',
link = ''
} or ''
if note_args.text then
local retnote_image = mw.html.createimage('tr')
note_args.image_name,
ret:tag('td'):wikitext(note_image):done()
note_args.size or note_default_size,
:tag('td'):addClass('mbox-text'):attr('colspan', '2'):wikitext(note_args.text):allDone()
cfg.note.icon_alt,
return ret
'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(parse_pt(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 .. '|' .. parse_pt(note_args.text) .. '|link=|alt=]]')
table.insert(nested_ratings, tostring(icon))
end
end
end
local auto = false
local auto_arg = args.auto and stringargs.auto:lower(args.auto)
if (auto_arg=='yes' or auto_arg=='stub') and class=='Stub' then
auto = 'stub'
Line 493 ⟶ 674:
end
if auto then
local auto_cat = args.AUTO_ASSESS_CAT or string.format(cfg.auto.default_cat, :format(project)
local auto_text = stringcfg.auto.assessed:format(
cfg.auto.assessed,
pagetype,
cfg.auto[auto], -- method of automatic assessment
parameter_format('auto')
Line 509 ⟶ 688:
sort_prefix = sort_codes[class] or cfg.auto.default_sort_code
end
local auto_note = render_note{
text = auto_text,
image_name = cfg.auto.icon,
Line 515 ⟶ 694:
sort_prefix = sort_prefix
}
table.insert(collapsed, auto_note)
end
if yesno(args.attention, true) then
local attention_cat = args.ATTENTION_CAT or string.format(cfg.attention.default_cat, :format(project)
local attention_note = render_note{
text = string.format(cfg.attention.text, pagetype),
image_name = cfg.attention.icon,
category = attention_cat
}
table.insert(collapsed, attention_note)
end
if yesno(args.infobox, true) then
local infobox_cat = args.INFOBOX_CAT or string.format(cfg.infobox.default_cat, :format(project)
local infobox_note = render_note{
text = string.format(cfg.infobox.text, pagetype),
image_name = cfg.infobox.icon,
category = infobox_cat
}
table.insert(collapsed, infobox_note)
end
for _, k in ipairs(notes) do
local note_prefix = 'NOTE_' .. k .. '_'
local note = render_note{
text = parse_textparse_pt(args[note_prefix..'TEXT']),
image_name = args[note_prefix..'IMAGE'],
size = args[note_prefix..'SIZE'],
category = args[note_prefix..'CAT']
}
table.insert(collapsed, note)
end
if yesno(args['image-needed'], true) then
local note_count = #collapsed
local image_needed_args = require(auxiliary).image_needed(args)
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(auxiliary).collaboration(args, 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(auxiliary).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(auxiliary).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(collapsednote_output, args.HOOK_NOTE)
local hook_collapsed = 0
if args.HOOK_COLLAPSED then
local success, result = pcall(mw.ext.ParserFunctions.expr, args.HOOK_COLLAPSED)
Line 558 ⟶ 753:
note_count = note_count + hook_collapsed
end
collapse_section(
---------------------------
note_count > (tonumber(args.COLLAPSED) or cfg.note.threshold),
-- Collapsed secton -------
note_output,
---------------------------
args.COLLAPSED_HEAD or cfg.note.header
if note_count > (tonumber(args.COLLAPSED) or 2) then -- collapse note section
)
local collapsed_section = mw.html.create('tr')
local collapsed_rows = collapsed_section:tag('td')
:attr('colspan','3')
:addClass('wpb-collapsed-notes')
:tag('table')
:addClass('mw-collapsible mw-collapsed')
:tag('tr')
:tag('th')
:attr('colspan','3')
:addClass('wpb-collapsed-head')
:wikitext(args.COLLAPSED_HEAD or 'More information:')
:done()
:done()
:tag('tr')
:tag('td')
:addClass('mbox-image wpb-gutter')
:css('min-width',image_left_size)
:tag('span')
:addClass('wpb-iefix')
:wikitext('/&nbsp;') --TO FIX IE
:done()
:done()
:tag('td'):done()
:tag('td'):done()
:done()
for _, row in ipairs(collapsed) do
collapsed_rows:node(row)
end
collapsed_rows:allDone()
table.insert(rows, collapsed_section)
else
for _, row in ipairs(collapsed) do
table.insert(rows, row)
end
end
---------------------------
-- Bottom text ------------
Line 602 ⟶ 763:
if args.HOOK_BOTTOM then
table.insert(rows, args.HOOK_BOTTOM)
end
if args.TODO_LINK or args.TODO_TEXT then
local todolist = require(auxiliary).todo_list(args, frame)
table.insert(rows, todolist)
end
if args.BOTTOM_TEXT then
local bottom_text = mw.html.create('tr')
:tag('td')
bottom_text
:tag('td')
:attr('colspan','3')
:wikitext(parse_textparse_pt(args.BOTTOM_TEXT))
:allDonedone()
table.insert(rows, bottom_text)
end
Line 616 ⟶ 780:
end
---------------------------
-- MakeNested bannerdisplay ------------
---------------------------
local nested_tf_str = #nested_tf>0 and ' / ' .. table.concat(nested_tf, ' /&nbsp;') or ''
if args.HOOK_NESTED then
local hook_nested = args.HOOK_NESTED:gsub('^&#32;/ ', '') -- remove initial slash, will be added later
nested_tf_str = nested_tf_str .. ' ' .. args.HOOK_NESTED
table.insert(nested_tf, hook_nested)
end
local nested_tf_str = ''
local nested_ratings_str = #nested_ratings>0 and table.concat(nested_ratings, '') or ''
if #nested_tf>0 then
nested_tf_str = tostring(mw.html.create('span')
:addClass('wpb-nested-task-force')
: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')
local status_class = (cfg.status[args.PROJECT_STATUS] or cfg.status.default) .. '-wikiproject'
:addClass('wpb-header')
local banner = mw.html.create('table')
:tag('td')
local banner_rows = banner
:addClass('tmbox tmboxwpb-notice mwheader-collapsible innercollapse wpbicon')
:wikitext(image(args.IMAGE_LEFT, cfg.image.header_size, cfg.image.alt))
:addClass(status_class)
:css('table-layout', 'fixed')
:tag('tr')
:addClass('wpb-header')
:tag('td')
:attr('width', '50px')
:css('text-align', 'center')
:wikitext(image({
image = args.IMAGE_LEFT,
size = 'x25px',
alt = 'WikiProject icon'
}))
:done()
:tag('td')
:addClass('wpb-header-namecombined')
:wikitext(wikilink(project_link.prefixedText, project) .. nested_tf_str .. ' ' .. nested_ratings_str)
:done()
---------------------------
:done()
-- Prepare categories -----
---------------------------
local categories_formatted = ''
if demo_page and demo_page~=true 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')
:addClass('wpb-category-box')
:wikitext('Categories:')
:node(category_list)
categories_formatted = tostring(category_box)
elseif not demo_page 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 wpb-table')
:addClass(inactive and cfg.inactive.class or nil)
:node(header_row)
:tag('tr')
:tag('td')
:addClass('mbox-text wpb-main')
:attr('colspan','2')
:tagnode('table'banner_rows)
:allDone()
for _, row in ipairs(rows) do
local tstyle = frame:extensionTag('templatestyles', '', {src='Module:Message box/tmbox.css'}) ..
banner_rows:node(row)
frame:extensionTag ('templatestyles', '', {src = 'Module:WikiProject banner' .. (sandbox or '') .. '/styles.css'})
end
return warning .. tstyle .. tostring(banner) .. categories_formatted, note_count, #taskforce_output, assessment_link
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='WPBannerMeta/sandbox/styles.css'})
return warning .. tstyle .. tostring(banner) .. table.concat(categories)
end
 
local initialise = function(args, raw_args, inactive_status)
function p.main(frame)
---------------------------
local args = require('Module:Arguments').getArgs(frame, {
-- Initialise arguments ---
wrappers = {'Template:WPBannerMeta'}
---------------------------
})
local parent_args = args_module.getArgs(frame, {parentOnly = true})
local raw_args = frame:getParent().args
local category = parent_args.category or args.category or true
local banner_name = mw.title.new(args.BANNER_NAME or 'Template:WikiProject ' .. (args.PROJECT or 'PROJECT'))
local demo_page = parent_args.demo_page
local demo = not yesno(args.category or true, true)
local config, project
local on_template_page = not demo and (
if args.project then -- check for config page
current_title.rootPageTitle==banner_name.rootPageTitle
project = args.project
or (current_title.rootPageTitle and current_title.rootPageTitle.prefixedText=='Template:WPBannerMeta')
local config_file = mw.title.new('Template:WikiProject ' .. args.project .. '/config')
)
if on_template_pageconfig_file.exists then
config = mw.loadJsonData(config_file.fullText)
local templatepage = require('Module:WikiProject banner/templatepage' .. (sandbox or '')).templatepage
return templatepage(args, raw_args)
else
return nil
return p._main(args, raw_args, demo, banner_name)
end
end
if config then -- use config file
if parent_args.taskforce then -- split comma-separated list
for taskforce in mw.text.gsplit(parent_args.taskforce, ',%s*') do
parent_args[taskforce] = 'yes'
end
end
args, raw_args = require(auxiliary).map_config(config, parent_args) -- map parameters from config page
args.PROJECT = project
end
local on_template_page = false
local banner_name = mw.title.new(args.BANNER_NAME or 'Template:WikiProject ' .. (args.PROJECT or 'PROJECT'))
if not demo_page then
if yesno(category, true) then
on_template_page = current_title.rootPageTitle==banner_name.rootPageTitle
else
demo_page = true
end
end
local project_name = args.PROJECT_NAME or 'WikiProject ' .. (args.PROJECT or 'PROJECT')
local unknown_parameters = ''
if banner_name.exists and not demo_page then -- check for unknown parameters
local parameters = {}
for parameter in banner_name:getContent():gmatch('{{{([^|}]+)') do
table.insert(parameters, parameter)
end
parameters.showblankpositional = "1"
local check_for_unknown = require('Module:Check for unknown parameters')._check
local unknowns = check_for_unknown(parameters, parent_args)
if unknowns and unknowns~='' then -- there are some unknown parameters
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 ''
unknown_parameters = check_for_unknown(parameters, parent_args)
end
end
if on_template_page then
local templatepage = require('Module:WikiProject banner/templatepage' .. (sandbox or '')).templatepage
return templatepage(args, raw_args, inactive_status, config)
else
return unknown_parameters
.. p._main(args, raw_args, demo_page, 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.inactive.status[args.PROJECT_STATUS] or cfg.inactive.default
local main_text = cfg.inactive.text:format(
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
}, {
substcheck = '' -- to prevent warning on templatepage
}, _status
)
end