Module:WikiProject banner

From the AARoads Wiki: Read about the road before you go
Jump to navigation Jump to search

Module:WikiProject banner can be used to create WikiProject banners, enabling new projects to easily create a banner to place on article talk pages, ensuring standardisation between projects. A list of all WikiProject banners using this meta-template can be found here.

As this is a meta template, it should not be transcluded directly on to talk pages when you want to tag a page. Instead, use the template provided by the WikiProject.

WikiProject banners are categorised into a subcategory of Category:Project banner templates. It is not necessary to include a category link in the documentation for each project banner. Any project banners with issues are automatically added to Category:Project banners with errors.


The template can be used at varying levels of complexity, from the very simple to the extremely complicated. Simple options are listed here first, with complexity increasing down the page.

Two different types of parameters are used: formatting and display:

  • Formatting parameters customise the meta-template for a particular project, defining link targets, categories, images, and text. All formatting parameters use UPPERCASE and underscores (_) instead of spaces, for example |PROJECT= and |NOTE_1_CAT=.
  • Display parameters customise the template output for each individual article that the banner is displayed on. These are the parameters which are entered on the talk page (|class=, |importance=, etc.) and they must be 'passed through' the project banner to the meta-template underneath. To 'pass' the parameter foo, you need to include the code foo={{{foo|}}}.


Common parameters
{{#invoke:WikiProject banner|main
|PROJECT           = 
|DOC               = auto
|IMAGE_LEFT        = 
|MAIN_TEXT         = 
|PORTAL            = 
|MAIN_CAT          = 
 |INFOBOX_CAT      = 

In the examples below, a WikiProject banner will be constructed for the (currently) nonexistent WikiProject Interstate 80.

Simple options

  • PROJECT (Required) – the name of the project without the word "WikiProject", used in a variety of contexts; first letter should usually be capitalised. Eg: Interstate 80
    • BANNER_NAME={{subst:FULLPAGENAME}} – it is assumed that page name of the banner template is "Template:WikiProject <PROJECT>". If this is not the case then define the page name in this parameter. Eg: Template:Interstate 80 project
    • PROJECT_LINK – it is assumed that the project is located at "Wikipedia:WikiProject <PROJECT>". If this is not the case, then define the full link to the project page in this parameter. Eg: AARoads:Interstate 80
    • PROJECT_NAME – if your project is not called "WikiProject <PROJECT>" then define the exact name of the project with this parameter.
  • substcheck – this allows the template to detect if it has been substituted instead of transcluded and give an error message. substcheck=<includeonly>{{subst:</includeonly><includeonly>substcheck}}</includeonly>
  • category (Required) – the 'category' parameter must be passed through the template to enable category optout. E.g.: category={{{category|}}}.
  • listas (Required) – the 'listas' parameter must be passed through the template. Eg: listas={{{listas|}}}
  • IMAGE_LEFT – the location of an image to use in the top-left corner of the banner. Do not include the "File:" prefix. Images used on WikiProject banners must be free images. Eg: I-80.svg
    • IMAGE_LEFT_SIZE – the size of IMAGE_LEFT. Default is 80px. Eg: 50px
  • IMAGE_RIGHT – the location of an image to use in the top-right corner of the banner. Do not include the "File:" prefix. Images used on WikiProject banners must be free images. Eg: I-80.svg
    • IMAGE_RIGHT_SIZE – the size of IMAGE_RIGHT. Default is 80px. Eg: 50px
  • MAIN_TEXT – the default text is "This article is within the scope of [[WikiProject {{{PROJECT_LINK}}}]], a collaborative effort to improve the coverage of {{{PROJECT or MAIN_ARTICLE}}} articles on Wikipedia. If you would like to participate, please visit the project page, where you can join the [[Talk:{{{PROJECT_LINK}}}]] discussion and see a list of open tasks." If defined, the alternate message will be displayed.
    • MAIN_ARTICLE – the default article is PROJECT; alternatively, the linked article can be changed to either a raw article title or more complicated text. Eg: (default) Interstate 80"...the coverage of Interstate 80 on the AARoads Wiki...".
  • MAIN_CAT – the default is no main category created; if defined, all pages displaying the template will be sorted into Category:MAIN_CAT. Eg: Interstate 80 project articlesCategory:Interstate 80 project articles
  • BOTTOM_TEXT – if defined, contains text that will appear across the bottom of the banner and above the collapsed section (if one is present). Please do not use this parameter to 'hook' extra code to the bottom of the template – see the hooks section below for a better solution.


{{#invoke:WikiProject banner|main
|PROJECT          = Interstate 80
|PROJECT_LINK     = AARoads:Interstate 80
|IMAGE_LEFT       = I-80.svg
|MAIN_ARTICLE     = Interstate 80
Project iconInterstate 80
Project iconThis article falls within the topic of Interstate 80. Please visit The Interchange, where you can join the discussion and see a list of open tasks.


Many projects use the AARoads:Assessment schema to grade their articles by quality and the corresponding importance scale to place their articles in order of priority.

  • class (Required)– the class parameter must be passed through, if the quality scale is used. Eg: class={{{class|}}}
    • auto the auto parameter must be passed through, if the auto assess option is needed. Eg: auto={{{auto|}}} Projects which use bots to automatically categorise articles can have the bot add the following parameter to the project banner, which triggers the display of a small notice that the article was tagged by a bot rather than a human:
      |auto=stub, for an article which includes a stub template, to indicate that it has automatically been rated Stub-class;
      |auto=inherit, to show that the class has automatically been inherited from other WikiProject's assessments on the same page;
      |auto=length, to show that the class has automatically been deduced from the length of the article.
    • b1, b2, b3, b4, b5, b6 – the six B-class criteria parameters.
  • importance– if defined, enables the standard importance scale (Top, High, Mid, Low, NA, Unknown). Eg: importance={{{importance|}}}
    • IMPORTANCE_SCALE – configures the importance scale, if used. The possible options are:
      • standard – enables the 'standard' importance scale (Top, High, Mid, Low, NA and Unknown). (This is the default behaviour.)
      • inline – allows for a simple custom importance scale to be defined, generally with {{Importance mask}}.
      • subpage – allows for a more complex custom importance scale to be used using a subpage called /importance.
  • ASSESSMENT_LINK – the link to a WikiProject-specific quality (and/or importance) scale. If there is a page at "Wikipedia:WikiProject <PROJECTLINK>/Assessment" then this will be used by default. To override this, you can set this parameter to no.
  • ASSESSMENT_CAT – articles are sorted into categories based on their quality; so A-Class Articles on Interstate 80 would be categorised by default into Category:A-Class Interstate 80 articles. To change the default, define this parameter so that featured articles are instead categorised into Category:A-Class ASSESSMENT_CAT. Eg: |ASSESSMENT_CAT=Interstate 80 articlesCategory:A-Class Interstate 80 articles


{{#invoke:WikiProject banner|main
|PROJECT             = Interstate 80
|IMAGE_LEFT          = I-80.svg
|QUALITY_SCALE       = extended
|ASSESSMENT_LINK     = AARoads:Assessment
Project iconInterstate 80 NA‑class
Project iconThis article falls within the topic of Interstate 80. Please visit The Interchange, where you can join the discussion and see a list of open tasks.
NAThis article has been rated as NA-class on the AARoads Wiki's content assessment scale.

Alerts and notes

Built into the module is the ability to display a number of other fields that contain useful information about the article. There are also three predefined fields for:

  1. articles which have been automatically assessed by a bot (see above);
  2. articles in need of immediate attention;
  3. articles in need of an infobox.

The parameters are:

  • attention – pass this parameter through to enable the use of the attention note. Eg: attention={{{attention|}}}, then by including |attention=yes on the talk page.
  • infobox – pass this parameter through to enable the use of the needs-infobox note. Eg: infobox={{{needs-infobox|}}}, then by including |needs-infobox=yes on the talk page.
  • note 1– pass this parameter through to trigger any defined note. Eg: note 1={{{needs-photo|}}}, then by including |needs-photo=yes on the talk page.
    • NOTE_1_TEXT – the text of note 1. E.g.: This page has been marked as needing a photograph. If this is left blank there is no visual output.
    • NOTE_1_IMAGE – an image can be defined for each note. Remember that all images must be free, not fair-use. Eg: Gnome-dev-camera.svg
    • NOTE_1_CAT – if defined, all articles displaying note 1 will be categorised into Category:NOTE_1_CAT. Eg: Requested photographs of Interstate 80Category:Requested photographs of Interstate 80
  • COLLAPSED – when more than a threshold number of notes and alerts are triggered on a page, they are automagically collapsed into a show/hide box. The threshold number can be customised by setting this parameter to the maximum number of notes on a page that will not trigger the collapse. The default is 2, so if three notes are triggered on a page, they will not be collapsed, but if a fourth is also triggered, the collapse box appears. So setting |COLLAPSED=0 will always create a collapse box (if there are any notes to fill it), while |COLLAPSED=999 will never trigger a collapse box. Eg: 6
    • COLLAPSED_HEAD – the heading for the collapsed section; the default is More information: Eg: Additional information:
  • NOTE_SIZE – the size of the image used for the icons. (It is recommended to precede the size with "x" as this specifies the height of the image instead of the width, which results in a neater banner because all rows have equal height.) The default is a height of 25px. Eg: x30px


{{#invoke:WikiProject banner|main
|PROJECT            = Interstate 80
|IMAGE_LEFT         = I-80.svg
|QUALITY_SCALE      = extended
|ASSESSMENT_LINK    = AARoads:Assessment
 |INFOBOX_CAT       = 
|note 1={{{needs-photo|}}}
 |NOTE_1_TEXT       = This page has been marked as needing a [[photograph]].
 |NOTE_1_IMAGE      = Gnome-dev-camera.svg
 |NOTE_1_CAT        = Requested photographs of Interstate 80
|note 2 = {{{audio-file|}}}
 |NOTE_2_TEXT       = An [[audio file format|audio file]] has been created of this article.
 |NOTE_2_IMAGE      = Nuvola apps arts.svg
 |NOTE_2_CAT        = Interstate 80 articles with audio files
Project iconInterstate 80 NA‑class
Project iconThis article falls within the topic of Interstate 80. Please visit The Interchange, where you can join the discussion and see a list of open tasks.
NAThis article has been rated as NA-class on the AARoads Wiki's content assessment scale.
More information:
Note icon
This article has been marked as needing immediate attention.
Note icon
This article has been marked as needing an infobox.
Note icon
This page has been marked as needing a photograph.
Note icon
An audio file has been created of this article.

Task forces

The module can accommodate task forces, each with its own image, links and importance scale, if desired. The following parameters are available:

  • tf 1 – this parameter must be passed through to enable and trigger the display of the task force section. Eg: tf 1={{{I-280|}}}
    • TF_1_LINK – the full page name of the task force's project page. Eg: AARoads:Interstate 280
    • TF_1_NAME – the name of the task force. This is used as the label for the task force link (unless |TF_1_TEXT= is used instead). Eg: the Floridiae task force
    • TF_1_NESTED – if defined, a link of the form "/ [[{{{TF_1_LINK}}}|{{{TF_1_NESTED}}}]]" is added after the main project's name when the banner is collapsed inside a {{WikiProject banner shell}}. Eg: Interstate 280
    • TF_1_TEXT – if defined, replaces the default "This page is supported by..." text. E.g.: This page is within the scope of the [[AARoads:Interstate 280|Interstate 280]]. New participants are always welcome! If defined to be "none", then no output will be displayed, although appropriate categories will still be added.
    • TF_1_IMAGE – an image can be defined for each task force. Remember that all images must be free, not fair-use. Eg: I-280.svg
    • TF_1_QUALITY – if defined, enables the quality categorisations for the main project (e.g.: Category:A-Class Interstate 280 articles) to be duplicated for the task force. The class arising from |class= and |QUALITY_SCALE= will be used; Eg: yes
    • tf 1 importance– if defined, enables the use of a separate importance (or priority, if used) scale for the task force.Eg: tf 1 importance={{{floridiae-importance|}}}
    • TF_1_ASSESSMENT_CAT (Required if quality or importance assessments are used) – the assessment category to be used for the task force-specific quality and importance assessments. Identical in syntax to |ASSESSMENT_CAT=. Eg: Interstate 280 articlesCategory:A-Class Interstate 280 articles
    • TF_1_MAIN_CAT – if defined, all pages displaying "tf 1" will be categorised into Category:TF_1_MAIN_CAT. Eg: Interstate 280 articlesCategory:Interstate 280 articles
    • TF_1_HOOK – additional code to "hook" on the template only if this task force is used.
  • TF_SIZE – the size of the taskforce icons. (It is recommended to precede the size with "x" as this specifies the height of the image instead of the width, which results in a neater banner because all rows have equal height.) The default is a height of 25px. Eg: x30px


{{#invoke:WikiProject banner|main
|PROJECT              = Interstate 80
|IMAGE_LEFT           = I-80.svg
|QUALITY_SCALE        = standard
|tf 1={{{I-280|}}}
 |TF_1_LINK           = AARoads:Interstate 280
 |TF_1_NAME           = Interstate 280
 |TF_1_NESTED         = I-280
 |TF_1_TEXT           = 
 |TF_1_IMAGE          = I-280.svg
 |TF_1_ASSESSMENT_CAT = Interstate 280 articles
 |TF_1_MAIN_CAT       = Interstate 280 articles
Project iconInterstate 80: I-280 NA‑class
Project iconThis article falls within the topic of Interstate 80. Please visit The Interchange, where you can join the discussion and see a list of open tasks.
NAThis article has been rated as NA-class on the AARoads Wiki's content assessment scale.
Taskforce icon
This article also falls under Interstate 280.

Advanced features

B-class checklist

Enables a B-class checklist. There are six official criteria (although some projects use five) that an article needs to satisfy in order to be classified as B-class. A checklist can provide a helpful aid for editors to show where an article needs improvement.

{{#invoke:WikiProject banner|main


Required parameters

  • The six B-Class criteria: b1, b2, b3, b4, b5, b6

Optional parameters

  • B_DISPLAY_ON_START – if set to "yes", the checklist will be displayed on every Start-class article. The default behaviour is to only display on Start-class when one or more of the parameters b1-b6 have been filled in.
  • B_MAIN_CAT – specifies a category to use when any of the checklist parameters are blank.
  • B1_CAT to B6_CAT – specifies individual categories to use when the individual checklist parameters are blank or set to no.

Custom parameter names

The standard parameter names (i.e. b1, b2, etc.) should be passed as an alternative to any custom parameters (e.g. B-Class-1, B-Class-2, etc.). For example:


If only the standard parameters are used, then eg: b1={{{b1|}}}, etc. is fine.

Collapsing task forces

By default, the list of task forces will be collapsed into a show/hide box if there are more than 5 task forces. You can configure this behaviour with the following parameters:

  • TF_COLLAPSE – the threshold number of task forces for them to collapse, e.g. if |TF_COLLAPSE=3 then they will collapse whenever there are more than 3 task forces.
  • TF_HEADER – the heading for the collapsed section. The default is Associated task forces:

To-do list

This enables a project to-do list or other similar list to be integrated into a project banner.

|TODO_LINK        = 
|TODO_TEXT        = 
 |TODO_TITLE      = 
 |TODO_STYLE      = 

There are two main parameters, |TODO_LINK= and |TODO_TEXT=. Only one should be used at any time. If the to-do list is located on a different page then TODO_LINK should be used. However, if you've just got some text to include then you can use the TODO_TEXT option instead.

Styling can be adjusted using the |TODO_STYLE= and |TODO_TITLE_STYLE= parameters.

If you are using |TODO_LINK= and don't want to see the edit links at the top of the textbox, set TODO_EDITLINKS=no.


{{#invoke:WikiProject banner|main
|PROJECT          = Interstate 80
|NAME             = The Interstate 80 taskforce
|IMAGE_LEFT       = I-80.svg
|TODO_LINK        = Template:To do/to do
 |TODO_TITLE      = Interstate 80 project To-do
Project iconInterstate 80
Project iconThis article falls within the topic of Interstate 80. Please visit The Interchange, where you can join the discussion and see a list of open tasks.
Interstate 80 project To-do:
  • This is just a test to-do list to help editors make sure that the text
  • shows
    1. up
    2. correctly
  • Normally, the "/to do" subpage should only be created under the article's Talk page, unless it is a notice board or project page.
  • To use this template for an article, insert {{to do}} at the top of that article's Talk discussion page. To use it for a project or as your own personal list, add it to the project page or your user page, respectively.

Image-needed note


This feature adds a note than can be used to track when articles needs an image, photograph, diagram, illustration, etc. It will populate various categories such as

It takes the following parameters:

Required parameters

  • image-needed – pass through whichever parameter you are using to trigger this note, e.g. |image-needed={{{needs-image|}}}.

Optional parameters

  • IM_IMAGE – specifies the icon to be used (without the File namespace prefix); the default is Camera-photo.svg ([[File:Camera-photo.svg|20px]]).
  • image-type – pass through the type which can be used to accommodate other components that are needed, e.g. diagram, equation, map, etc. If this is not specified then "image or photograph" is used. E.g. |image-type={{{type|}}}.
  • image-details – to allow an editor to pass more details about the required image, e.g. |image-details={{{details|}}}.
  • image-location – pass this parameter through to allow an editor to specify the location of the requested image, e.g. |image-location={{{location|}}}. This will also populate categories of the form Category:Wikipedia requested photographs in Scotland.
  • IM_LOCATION_CATEGORY – a default category to use when the location is not specified or leads to a non-existent category.
  • image-topic – pass this through to allow an editor to specify a topic area that the photograph relates to, e.g. |image-topic={{{topic|}}}. This will populate categories such as Category:Wikipedia requested photographs of toys.
  • IM_TOPIC_CATEGORY – a default category in case the topic is not specified or leads to a non-existent category, e.g. |IM_TOPIC_CATEGORY=Wikipedia requested images of politics.

Collaboration note

 |COLL_LINK          = 
 |COLL_TEXT          =
 |COLL_IMAGE         = 
 |COLL_PAST_CAT      = 

This featue enables a project collaboration system to be integrated into a project banner. The following parameters are used:

Required parameters

  • collaboration-candidate – pass the parameter that will trigger the collaboration candidate note, if used, e.g. |collaboration-candidate={{{collaboration-candidate|}}}
  • collaboration-current – the parameter that will trigger the current collaboration note, if used. E.g. |collaboration-current={{{collaboration|}}}
  • collaboration-past – the parameter that will trigger the past collaboration note, if used. e.g. |collaboration-past={{{past-collaboration|}}}
  • COLL_LINK – the full link to where the review for the particular article is held. E.g. |COLL_LINK=Wikipedia:WikiProject Paranormal/Collaboration

Optional parameters

  • COLL_TEXT – the text to display in place of the default "project collaboration", e.g. |COLL_TEXT=Collaboration of the Month
  • COLL_IMAGE – the name of the image to use. If not specified then Crystal 128 kuser.png is used.
  • COLL_CANDIDATE_CAT – if defined, pages using |candidate=yes will be categorised into this category, e.g. |COLL_CANDIDATE_CAT=Paranormal collaboration candidatesCategory:Paranormal collaboration candidates
  • COLL_CURRENT_CAT – if defined, pages using |current=yes will be categorised into this category, e.g. |COLL_CURRENT_CAT=Paranormal collaborationsCategory:Paranormal collaborations
  • COLL_PAST_CAT – if defined, pages using |past=yes will be categorised into this category, e.g. |COLL_PAST_CAT=Past paranormal collaborationsCategory:Past paranormal collaborations

A-class review note

|a class={{{**PARAMETER**|}}}
 |ACR_REVIEW_LINK       = 
 |ACR_PASS_CAT          = 
 |ACR_FAIL_CAT          = 
 |ACR_CURRENT_CAT       = 

This feature enables an A-Class review process to be integrated into a project banner. The following parameters are used:

Required parameters

  • a class – the parameter that will trigger the note. Accepted values are "pass", "fail", "current" (any capitalisation); everything else is treated as null. Eg: a class={{{A-Class|}}}
  • ACR_SUBPAGE_LINK – the full link to where the review for this particular article is held. Eg: AARoads:A-Class review/{{SUBJECTPAGENAME}}
  • ACR_REVIEW_LINK – the full link to the main A-Class review page (where instructions etc. are held). Eg: AARoads:A-Class review/{{SUBJECTPAGENAME}}

Optional parameters

  • ACR_PASS_CAT – pages using |a class=pass will be categorised into this category. Eg: Successful requests for Interstate 80 A-Class reviewCategory:Successful requests for Interstate 80 A-Class review
  • ACR_FAIL_CAT – pages using |a class=fail will be categorised into this category. Eg: Failed requests for Interstate 80 A-Class reviewCategory:Failed requests for Interstate 80 A-Class review
  • ACR_CURRENT_CAT – pages using |a class=current will be categorised into this category. Eg: Current requests for Interstate 80 A-Class reviewCategory:Current requests for Interstate 80 A-Class review
  • ACR_IMAGE – a custom image can be set, using the same syntax as for other note images. Eg: Exquisite-kfind.png
  • ACR_SIZE – a custom image size can be set, using the usual note syntax. Eg: 20x20px
  • ACR_INVALID_CAT – pages specifying the A Class parameter without a valid SUBPAGE_LINK page existing will be categorised into this category.

Additional task force categories

Sometimes it is desirable to populate additional categories when certain task forces are used. For example the |attention= parameter is used to draw attention to articles which need immediate attention in the cycling project. Articles within the scope of the Tour de France task force populate the additional category of Category:Tour de France articles needing attention.

This can be achieved by using the following code:

{{#invoke:WikiProject banner|main
|tf 2={{{tdf|}}}
 |TF_2_LINK            = Wikipedia:WikiProject Cycling/Tour de France task force
 |tf 2 cat 1={{{attention|}}}
  |TF_2_CAT_1          = Tour de France articles needing attention
 |tf 2 cat 2={{{needs-infobox|}}}
  |TF_2_CAT_2          = Tour de France articles needing infoboxes

Peer review note

|peer review={{{**PARAMETER**|}}}
|old peer review={{{**PARAMETER**|}}}
 |peer review title={{{**PARAMETER**|}}}
 |PR_LINK           = 
 |PR_IMAGE          = 
 |PR_CAT            = 
 |PR_OLD_CAT        = 

This feature enables a peer review process to be integrated into a project banner. The following parameters are used:

Required parameters

  • peer review – the parameter that will trigger the active peer review note; should be passed through, e.g. |peer review={{{peer-review|}}}
  • old peer review – the parameter that will trigger the old peer review note; should be passed through, e.g. |old peer review={{{old-peer-review|}}}
  • PR_LINK – the full link to where the review for this particular article is held, e.g. |PR_LINK=AARoads:Interstate 80/Assessment

Optional parameters

  • PR_IMAGE – the name of the image to use. If not specified then Exquisite-kfind.png is used.
  • PR_CAT – if defined, pages using |peer review=yes will be categorised into this category, e.g. |PR_CAT=Requests for Interstate 80 peer reviewCategory:Requests for Interstate 80 peer review
  • PR_OLD_CAT – if defined, pages using |old peer review=yes will be categorised into this category.
  • peer review title – If the page has been moved since it was reviewed, pass this parameter to specify the old page title (the one the review was archived under) to make the link point correctly to the review.
  • PR_INVALID_CAT – if defined, pages without a valid existing peer review page will be categorised into this category.

Inactive WikiProject banners

A number of WikiProjects have been identified as inactive or defunct (see Category:Inactive WikiProjects). In this case, the project banner can be given a less prominent form. Keeping an inactive project's template on relevant talkpages helps any group of users who later wishes to revive the project. This template will auto-categorize the project banner into Category:Inactive WikiProject banners.

The easiest way to convert a banner template to an inactive state, is to replace main with inactive.


  • The only required parameter is |PROJECT= - the name of the WikiProject (but without the word "WikiProject")
  • An additional parameter |PROJECT_STATUS= can be used to identify the status of the inactive project. Currently recognised values are inactive and defunct. The default is inactive.
  • All the other parameters can and should be retained, as this will make it easier to "revive" the project in the future.


{{#invoke:WikiProject banner|inactive
 |PROJECT     = Interstate 238
Project iconInterstate 238 (inactive)
Project iconThis article is within the scope of Interstate 238, a project which is currently considered to be inactive.
When inside a banner shell the result is:
{{#invoke:WikiProject banner|inactive
 |PROJECT        = Interstate 238
 |PROJECT_STATUS = defunct
Project iconInterstate 238 (defunct)
Project iconThis article is within the scope of Interstate 238, a project which is currently considered to be defunct.
When inside a banner shell the result is:

See also

  • {{WikiProject banner shell}} – template to combine multiple WikiProject Banners
  • {{WPBannerDoc}} – convenience template that generates standardised parameter documentation for use on the /doc page

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

local wikilink = function(link, display)
	if link then
		return display and '[[''|'..display..']]' or '[['']]'
		return display or ''

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 '')
		.. ']]'

local if_exists = function(target, fallback) -- function to add wikilink if target exists
	local title =
	if title and title.exists then
		return wikilink(target)
		return fallback or target

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
	return article

-- 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}
		importance = frame:expandTemplate{
			title = 'Template:Importance mask',
			args = {raw_importance or '¬', class=class}}
	if importance=='¬' then
		importance = nil
	return importance

-- 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
p.class_mask = function(class, title, FQS, pagetype)
	local resolveFQSgrade = function(class)
		return lang:ucfirst(class) or 'NA'
	local out = '' -- default to unassessed
	title = title or mw.title.getCurrentTitle()
	local ns = title.namespace
	class = class:match('^%s*(.-)%s*$'):lower()
	if ns==1 or ns==7 then -- Talk
		if pagetype=='disambiguation page' or class=='dab' or class=='disambig' or class=='disambiguation' or class=='disamb' then
			out = resolveFQSgrade('disambig')
		elseif class=='future' or class=='file' or class=='redirect' then -- Ucfirst
			out = lang:ucfirst(class)
		elseif class=='a' or class=='al' or class=='am' or class=='b' or class=='bl' or class=='c' or class=='cl' or class=='d' or class=='dl' or class=='e' or class=='el' then -- Upper-case
			out = class:upper()
		elseif class=='list' then-- List
			out = 'List'
	elseif ns==15 then -- Category talk
		out = 'Category'
	elseif ns==101 then -- Annex talk
		out = 'Annex'
	elseif ns==11 then -- Template talk
		out = 'Template'
	elseif ns==829 then -- Module talk
		out = 'Module'
	elseif ns==5 then -- AARoads talk
		out = 'Project'
	elseif pagetype=='redirect' or pagetype=='soft redirect' then
		out = 'Redirect'
		out = 'NA'
	return out

local page_assessment = function(project, class, importance) -- add PageAssessments parser function
	local assessment = table.concat({project, class or '', importance or ''},'|')
	frame:preprocess('{{#assessment:' .. assessment .. '}}')

local bubble = function(text, colour, conflict)
	local out = mw.html.create('span')
		:css('background', colour)
		:css('border', conflict and cfg.quality.conflict.border or (cfg.quality.border..' '..colour))
	return tostring(out)

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 project
local project_link = or 'AARoads:' .. 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})
local parse_text = function(text)
	return text and text:gsub('_PAGETYPE_', pagetype)
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)
		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] = {}
			table.insert(taskforce_categories[tf], cat)
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(
		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(
	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)
-- Substitution warning ---
if args.substcheck=='SUBST' then
	local text = cfg.subst_warning.text:format(
	warning = warning .. mbox('ombox', {
		image = '[[File:' .. cfg.subst_warning.image .. '|40px]]',
		type = cfg.subst_warning.type_,
		text = text,
	}) .. cfg.subst_warning.categories
-- 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))
	return cell
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(
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)
local text_cell = mw.html.create('td')
	: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))
local primary_row = mw.html.create('tr')
	:node(primary_image(args.IMAGE_LEFT, image_left_size))
	: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 = .. '/Assessment')
	assessment_link = fallback.exists and fallback.prefixedText
elseif assessment_link=='no' then
	assessment_link = nil
local check_exists = function(class, assessment_cat) -- check if category exists and is not blank
	if not isarticle(class) then
		local cat ='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
		return class
local class = raw_args.class
if class then -- banner gives quality ratings
	local title = args.demo_page and or current_title
	local article_class = p.readarticleclass({ignore_subtemplates=true}, title.prefixedText)
	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
				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
					article_class = nil -- effectively no article_class for this banner
		class = p.class_mask(class, title, true, pagetype)
	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
		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('Project banners with redundant class parameter')
		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
	if not isarticle(class) then
		local cat =, 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
	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)
			rating = cfg.quality.not_required
		local scale = args.QUALITY_CRITERIA=='custom'
			and assessment_link
			and cfg.quality.project_scale:format(wikilink(assessment_link..'#'..lang:ucfirst(,
			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')
				: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))
				:addClass('mbox-text'):attr('colspan', '2')
		table.insert(rows, class_row)
			bubble(class=='' and 'Unassessed' or (class..'‑class'), colour, conflict)
if args.HOOK_ASSESS then
	table.insert(rows, args.HOOK_ASSESS)
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)
-- 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')
				:addClass('assess'):addClass('import'):addClass('import-' .. importance)
				:css('background', colour):wikitext(wikilink(':Category:' .. category, importance=='Unknown' and '???' or importance))
				:addClass('mbox-text'):attr('colspan', '2')
		table.insert(rows, importance_row)
		if importance~='Unknown' then -- importance is not NA or Unknown
				bubble(importance..'‑'..importance_name, colour)
page_assessment(project, class, importance)
if args.HOOK_IMPORTANCE then
	table.insert(rows, args.HOOK_IMPORTANCE)
if args.QII_FORMAT then
	add_category(require(cfg.auxiliary_module .. (sandbox or '')).quality_importance_insection(args, class, importance, importance_name))
-- Collapsing sections ----
local collapse_section = function(collapse, new_rows, header)
	if collapse then
		local header_row = mw.html.create('tr')
		local blank_row = mw.html.create('tr')
				:addClass('mbox-image wpb-gutter'):css('min-width',image_left_size)
				:tag('span'):addClass('wpb-iefix'):wikitext('/&nbsp;'):done() --TO FIX IE
		local collapsed_rows = mw.html.create('table')
			:addClass('mw-collapsible mw-collapsed')
			for _, row in ipairs(new_rows) do
		local collapsed_section = mw.html.create('tr')
		table.insert(rows, collapsed_section)
		for _, row in ipairs(new_rows) do
			table.insert(rows, row)
-- 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
	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)
			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(
				wikilink(args[tf_prefix .. 'LINK'], args[tf_prefix .. 'NAME']),
		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')
		local taskforce = mw.html.create('tr')
		table.insert(taskforce_output, taskforce)
	if args[tf_prefix..'HOOK'] then
		table.insert(taskforce_output, args[tf_prefix..'HOOK'])
	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)
	if tf_importance then
		add_category(tf_importance .. '-' .. importance_name .. ' ' .. tf_assessment_cat)
	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))
	if args[tf_prefix..'NAME'] then
		page_assessment(project..'/'..args[tf_prefix..'NAME'], class, tf_importance)
	if args[tf_prefix..'MAIN_CAT'] then
	if args[tf_prefix..'NESTED'] then
		table.insert(nested_tf, wikilink(args[tf_prefix..'LINK'], args[tf_prefix..'NESTED']))
	for _, c in ipairs(taskforce_categories[k] or {}) do-- add additional taskforce categories
if args.HOOK_TF then
	table.insert(taskforce_output, args.HOOK_TF)
local threshold = tonumber(args.TF_COLLAPSE) or (args.TF_HEADER and cfg.task_force.lower_threshold) or cfg.task_force.upper_threshold
	#taskforce_output > threshold,
	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')
				:wikitext('[[File:' .. note_args.image_name .. '|' .. cfg.note.header_icon .. '|' .. note_args.text .. '|link=|alt=]]')
			table.insert(nested_ratings, tostring(icon))
local auto = false
local auto_arg = and
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
if auto then
	local auto_cat = args.AUTO_ASSESS_CAT or
	local auto_text =
		pagetype,[auto], -- method of automatic assessment
	local sort_prefix
	if auto=='stub' then
		sort_prefix = 'S'
	elseif auto=='length' then
		sort_prefix = 'L'
	elseif auto=='inherit' then
		local sort_codes =
		sort_prefix = sort_codes[class] or
		text = auto_text,
		image_name =,
		category = auto_cat,
		sort_prefix = sort_prefix
if yesno(args.attention, true) then
	local attention_cat = args.ATTENTION_CAT or cfg.attention.default_cat:format(project)
		text = cfg.attention.text:format(pagetype),
		image_name = cfg.attention.icon,
		category = attention_cat
if yesno(args.infobox, true) then
	local infobox_cat = args.INFOBOX_CAT or cfg.infobox.default_cat:format(project)
		text = cfg.infobox.text:format(pagetype),
		image_name = cfg.infobox.icon,
		category = infobox_cat
for _, k in ipairs(notes) do
	local note_prefix = 'NOTE_' .. k .. '_'
		text = parse_text(args[note_prefix..'TEXT']),
		image_name = args[note_prefix..'IMAGE'],
		size = args[note_prefix..'SIZE'],
		category = args[note_prefix..'CAT']
if yesno(args['image-needed'], true) then
	local image_needed_args = require(cfg.auxiliary_module .. (sandbox or '')).image_needed(args, pagetype)
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)
if yesno(args['a class'], true) then
	local a_class_args = require(cfg.auxiliary_module .. (sandbox or '')).a_class(args, lang)
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)
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
	note_count = note_count + hook_collapsed
	note_count > (tonumber(args.COLLAPSED) or cfg.note.threshold),
	args.COLLAPSED_HEAD or cfg.note.header
-- Bottom text ------------
if args.HOOK_BOTTOM then
	table.insert(rows, args.HOOK_BOTTOM)
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)
if args.BOTTOM_TEXT then
	local bottom_text = mw.html.create('tr')
	table.insert(rows, bottom_text)
if args.MAIN_CAT then
-- Nested display ---------
if args.HOOK_NESTED then
	local hook_nested = args.HOOK_NESTED:gsub('^&#32;/ ', '') -- remove initial slash, will be added later
	table.insert(nested_tf, hook_nested)
local nested_tf_str = ''
if #nested_tf>0 then
	nested_tf_str = tostring(mw.html.create('span')
		:css('font-weight', 'normal')
		:wikitext(': ' .. table.concat(nested_tf, ' / '))
local nested_ratings_str = #nested_ratings>0 and table.concat(nested_ratings, ' ') or ''
	nested_ratings_str = nested_ratings_str .. tostring(mw.html.create('span')
local header_row = mw.html.create('tr')
		:attr('width', '50px')
		:css('text-align', 'center')
		:wikitext(image(args.IMAGE_LEFT, cfg.image.header_size, cfg.image.alt))
		:wikitext(wikilink(project_link.prefixedText, project) .. nested_tf_str .. '  ' .. nested_ratings_str)
-- 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))
	local category_box = mw.html.create('div')
		:css('background-color', '#F5F5F5'):css('border-width', '1px')
		:css('width', '500px')
	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)
	categories_formatted = table.concat(categories_linked)
-- Make banner ------------
local banner_rows = mw.html.create('table')
for _, row in ipairs(rows) do
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')
		:addClass('mbox-text wpb-main')
if args.listas then
	frame:preprocess('{{DEFAULTSORT:' .. args.listas .. '}}')
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

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)
parameters.preview = cfg.unknown_parameters.preview:format(wikilink(banner_name.fullText))
local unknown_category = cfg.unknown_parameters.tracking:format(project_name)
if not then
	unknown_category = cfg.unknown_parameters.default
parameters.unknown = unknown_category and '[[' .. unknown_category .. '|_VALUE_]]' or ''
return require('Module:Check for unknown parameters')._check(parameters, parent_args)

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 (args.PROJECT or 'PROJECT')
	local banner_name = or 'Template:Banner/' .. (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)
		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

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)
-- Inactive projects ------
p.inactive = function(frame)
	local args = args_module.getArgs(frame, {frameOnly = true})
	local project_name = args.PROJECT_NAME or (args.PROJECT or 'PROJECT')
	local project_link = or 'AARoads:' .. project_name)
	local _status = cfg.status[args.PROJECT_STATUS] or cfg.status.default_inactive
	local main_text = cfg.inactive.text:format(
	return initialise({
			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

return p